static ssize_t handle_read( const int64 clientsocket ) { struct http_data* h = io_getcookie( clientsocket ); ssize_t l; if( ( l = io_tryread( clientsocket, static_inbuf, sizeof static_inbuf ) ) <= 0 ) { handle_dead( clientsocket ); return 0; } /* If we get the whole request in one packet, handle it without copying */ if( !array_start( &h->request ) ) { if( memchr( static_inbuf, '\n', l ) ) return http_handle_request( clientsocket, static_inbuf, l ); h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; array_catb( &h->request, static_inbuf, l ); return 0; } h->flag |= STRUCT_HTTP_FLAG_ARRAY_USED; array_catb( &h->request, static_inbuf, l ); if( array_failed( &h->request ) ) return http_issue_error( clientsocket, CODE_HTTPERROR_500 ); if( ( array_bytes( &h->request ) > 8192 ) && !accesslist_isblessed( (char*)&h->ip, OT_PERMISSION_MAY_SYNC ) ) return http_issue_error( clientsocket, CODE_HTTPERROR_500 ); if( memchr( array_start( &h->request ), '\n', array_bytes( &h->request ) ) ) return http_handle_request( clientsocket, array_start( &h->request ), array_bytes( &h->request ) ); return 0; }
static int __cdbb_findnext(struct cdbb *a, const char *needle, struct nentry *n, int ignorecase) { uint32 kp, dp, ks, vs; unsigned char *k, *v; if (cdb_nextkey(a->r, &a->kfindpos) != 1) return -1; kp = cdb_keypos(a->r); ks = cdb_keylen(a->r); k = alloca(ks); cdb_read(a->r, k, ks, kp); dp = cdb_datapos(a->r); vs = cdb_datalen(a->r); /* in some cases we do not need to read e.g. when deleting * or filtering but for simplicity we just do it anyways */ v = alloca(vs); cdb_read(a->r, v, vs, dp); /* search value */ if (ignorecase) { if (strcasestr((char *)v, needle) == NULL) return 0; } else { if (strstr((char *)v, needle) == NULL) return 0; } array_catb(&n->k, (char *)k, ks); array_catb(&n->e, (char *)v, vs); return 1; }
static void test_content() { static const char a[] = "left "; static const char b[] = "right"; static const char ab[] = "left right"; array x = {0}, y = {0}, z = {0}; array_catb(&x, a, strlen(a)); array_catb(&y, b, strlen(b)); array_catb(&z, ab, strlen(ab)); array_cat(&x, &y); assert(array_equal(&x, &z)); }
void cdbb_add_vop(struct cdbb *a, char *n, size_t ns, char *v, size_t vs, enum opt t) { cdbb_add_op(a, n, ns, t); /* write to tnum -1 because add_op already incremented */ array_catb(&a->ops[a->tnum - 1].v, v, vs); }
/** * Copy data to the compression buffer of a connection. We do collect * some data there until it's full so that we can achieve better * compression ratios. * If the (pre-)compression buffer is full, we try to flush it ("actually * compress some data") and to add the new (uncompressed) data afterwards. * This function closes the connection on error. * @param Idx Connection handle. * @param Data Pointer to the data. * @param Len Length of the data to add. * @return true on success, false otherwise. */ GLOBAL bool Zip_Buffer( CONN_ID Idx, const char *Data, size_t Len ) { size_t buflen; assert( Idx > NONE ); assert( Data != NULL ); assert( Len > 0 ); buflen = array_bytes(&My_Connections[Idx].zip.wbuf); if (buflen + Len >= WRITEBUFFER_SLINK_LEN) { /* compression buffer is full, flush */ if( ! Zip_Flush( Idx )) return false; } /* check again; if zip buf is still too large do not append data: * otherwise the zip wbuf would grow too large */ buflen = array_bytes(&My_Connections[Idx].zip.wbuf); if (buflen + Len >= WRITEBUFFER_SLINK_LEN) { Log(LOG_ALERT, "Zip Write buffer space exhausted: %lu bytes", buflen + Len); Conn_Close(Idx, "Zip Write buffer space exhausted", NULL, false); return false; } return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len); } /* Zip_Buffer */
/** * Compress data in ZIP buffer and move result to the write buffer of * the connection. * This function closes the connection on error. * @param Idx Connection handle. * @return true on success, false otherwise. */ GLOBAL bool Zip_Flush( CONN_ID Idx ) { int result; unsigned char zipbuf[WRITEBUFFER_SLINK_LEN]; int zipbuf_used = 0; z_stream *out; out = &My_Connections[Idx].zip.out; out->avail_in = (uInt)array_bytes(&My_Connections[Idx].zip.wbuf); if (!out->avail_in) return true; /* nothing to do. */ out->next_in = array_start(&My_Connections[Idx].zip.wbuf); assert(out->next_in != NULL); out->next_out = zipbuf; out->avail_out = (uInt)sizeof zipbuf; #ifdef DEBUG_ZIP Log(LOG_DEBUG, "out->avail_in %d, out->avail_out %d", out->avail_in, out->avail_out); #endif result = deflate( out, Z_SYNC_FLUSH ); if(( result != Z_OK ) || ( out->avail_in > 0 )) { Log( LOG_ALERT, "Compression error: code %d!?", result ); Conn_Close( Idx, "Compression error!", NULL, false ); return false; } if (out->avail_out <= 0) { /* Not all data was compressed, because data became * bigger while compressing it. */ Log(LOG_ALERT, "Compression error: buffer overflow!?"); Conn_Close(Idx, "Compression error!", NULL, false); return false; } assert(out->avail_out <= WRITEBUFFER_SLINK_LEN); zipbuf_used = WRITEBUFFER_SLINK_LEN - out->avail_out; #ifdef DEBUG_ZIP Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used); #endif if (!array_catb(&My_Connections[Idx].wbuf, (char *)zipbuf, (size_t) zipbuf_used)) { Log (LOG_ALERT, "Compression error: can't copy data!?"); Conn_Close(Idx, "Compression error!", NULL, false); return false; } My_Connections[Idx].bytes_out += zipbuf_used; My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf); array_trunc(&My_Connections[Idx].zip.wbuf); return true; } /* Zip_Flush */
void array_cate(array* to, const array* const from, int64 pos, int64 stop) { if(pos < 0 || stop < pos) { array_fail(to); return; } array_catb(to, from->p + pos, stop - pos); }
/* add contents of array src to array dest. */ bool array_cat(array * dest, const array * const src) { if (array_UNUSABLE(src)) return false; return array_catb(dest, src->mem, src->used); }
int array_catn(struct array *a, const void *dat, unsigned long len) { unsigned long clen = len * a->es; if (!len) return 0; if (clen / len != a->es) return 0; return array_catb(a, dat, clen); }
int strarray_pushd(strarray* arr, const char* s) { char* d; if((d = str_dup(s))) { array_catb((array*)arr, (void*)&d, sizeof(char*)); } return !!d; }
static int fmt_day_idx(array * fmt, struct taia *l) { char buf[FMT_TAIA_STR]; int len; len = fmt_time_str(buf, l); array_catb(fmt, buf, len); array_cats(fmt, "@"); return 0; }
/* return false on failure (realloc failure, invalid src/dest array) */ bool array_copyb(array * dest, const char *src, size_t len) { assert(dest != NULL); assert(src != NULL ); if (!src || !dest) return false; array_trunc(dest); return array_catb(dest, src, len); }
void cdbb_add_op(struct cdbb *a, char *n, size_t ns, enum opt t) { array *c = &a->ops[a->tnum].n; memset(&a->ops[a->tnum].v, 0, sizeof(array)); a->ops[a->tnum].svs = 0; a->ops[a->tnum].sv = NULL; a->ops[a->tnum].t = t; memset(c, 0, sizeof(array)); array_catb(c, n, ns); ++(a->tnum); }
int cdbb_read_nentry(struct cdbb *a, char *k, size_t ks, struct nentry *n) { int err, dlen; unsigned char *buf; array_catb(&n->k, k, ks); err = cdb_find(a->r, (unsigned char *)k, ks); if (err <= 0) return err; err = 0; /* num */ do { dlen = cdb_datalen(a->r); buf = alloca(dlen); if (cdb_read(a->r, buf, dlen, cdb_datapos(a->r)) < 0) return -2; array_catb(&n->e, (char *)buf, dlen); err++; } while (cdb_findnext(a->r, (unsigned char *)k, ks) > 0); return err; }
static void http_senddata( const int64 sock, struct ot_workstruct *ws ) { struct http_data *cookie = io_getcookie( sock ); ssize_t written_size; if( !cookie ) { io_close(sock); return; } /* whoever sends data is not interested in its input-array */ if( ws->keep_alive && ws->header_size != ws->request_size ) { size_t rest = ws->request_size - ws->header_size; if( array_start(&cookie->request) ) { memmove( array_start(&cookie->request), ws->request + ws->header_size, rest ); array_truncate( &cookie->request, 1, rest ); } else array_catb(&cookie->request, ws->request + ws->header_size, rest ); } else array_reset( &cookie->request ); written_size = write( sock, ws->reply, ws->reply_size ); if( ( written_size < 0 ) || ( ( written_size == ws->reply_size ) && !ws->keep_alive ) ) { array_reset( &cookie->request ); free( cookie ); io_close( sock ); return; } if( written_size < ws->reply_size ) { char * outbuf; tai6464 t; if( !( outbuf = malloc( ws->reply_size - written_size ) ) ) { array_reset( &cookie->request ); free(cookie); io_close( sock ); return; } memcpy( outbuf, ws->reply + written_size, ws->reply_size - written_size ); iob_addbuf_free( &cookie->batch, outbuf, ws->reply_size - written_size ); /* writeable short data sockets just have a tcp timeout */ if( !ws->keep_alive ) { taia_uint( &t, 0 ); io_timeout( sock, t ); io_dontwantread( sock ); } io_wantwrite( sock ); } }
int main(int argc, char* argv[]) { stralloc dir = {0, 0, 0}; int c; int digit_optind = 0; const char* rel_to = 0; int index = 0; static const struct longopt opts[] = { {"help", 0, 0, 'h'}, {"list", 0, &opt_list, 1}, {"numeric", 0, &opt_numeric, 1}, {"relative", 0, &opt_relative, 1}, {"output", 1, 0, 'o'}, {"exclude", 1, 0, 'x'}, {"time-style", 1, 0, 't'}, {"dereference", 0, &opt_deref, 1}, {"min-size", 1, 0, 'm'}, #if WINDOWS {"separator", 1, 0, 's'}, #endif {0} }; #if WINDOWS && defined(O_BINARY) setmode(STDOUT_FILENO, O_BINARY); #endif for(;;) { c = getopt_long(argc, argv, "hlnro:x:t:m:", opts, &index); if(c == -1) break; if(c == 0) continue; switch(c) { case 'h': usage(argv[0]); return 0; case 'x': { char* s = optarg; array_catb(&exclude_masks, (void*)&s, sizeof(char*)); break; } case 'o': { buffer_1->fd = io_err_check(open_trunc(optarg)); break; } case 't': { opt_timestyle = optarg; break; } case 's': { opt_separator = optarg[0]; break; } case 'l': opt_list = 1; break; case 'L': opt_deref = 1; break; case 'n': opt_numeric = 1; break; case 'r': opt_relative = 1; break; case 'm': scan_ulong(optarg, &opt_minsize); break; default: usage(argv[0]); return 1; } } /* while(optind < argc) { if(!str_diff(argv[optind], "-l") || !str_diff(argv[optind], "--list")) { opt_list = 1; } else if(!str_diff(argv[optind], "-n") || !str_diff(argv[optind], "--numeric")) { opt_numeric = 1; } else if(!str_diff(argv[optind], "-r") || !str_diff(argv[optind], "--relative")) { relative = 1; } else if(!str_diff(argv[optind], "-o") || !str_diff(argv[optind], "--output")) { buffer_1->fd = io_err_check(open_trunc(argv[optind + 1])); ++optind; } else if(!str_diff(argv[optind], "--relative")) { relative = 1; } else if(!str_diff(argv[optind], "-t") || !str_diff(argv[optind], "--time-style")) { optind++; opt_timestyle = argv[optind]; } else { break; } optind++; } */ array_catb(&exclude_masks, "\0\0\0\0\0\0\0\0", sizeof(char**)); print_strarray(buffer_2, &exclude_masks); if(optind < argc) { while(optind < argc) { if(opt_relative) opt_relative_to = argv[optind]; stralloc_copys(&dir, argv[optind]); list_dir_internal(&dir, 0); optind++; } } else { stralloc_copys(&dir, "."); list_dir_internal(&dir, 0); } return 0; }
void array_cats(array* to,const char* from) { array_catb(to,from,str_len(from)); }
/** * uncompress data and copy it to read buffer. * Returns true if data has been unpacked or no * compressed data is currently pending in the zread buffer. * This function closes the connection on error. * @param Idx Connection handle. * @return true on success, false otherwise. */ GLOBAL bool Unzip_Buffer( CONN_ID Idx ) { int result; unsigned char unzipbuf[READBUFFER_LEN]; int unzipbuf_used = 0; unsigned int z_rdatalen; unsigned int in_len; z_stream *in; assert( Idx > NONE ); z_rdatalen = (unsigned int)array_bytes(&My_Connections[Idx].zip.rbuf); if (z_rdatalen == 0) return true; in = &My_Connections[Idx].zip.in; in->next_in = array_start(&My_Connections[Idx].zip.rbuf); assert(in->next_in != NULL); in->avail_in = z_rdatalen; in->next_out = unzipbuf; in->avail_out = (uInt)sizeof unzipbuf; #ifdef DEBUG_ZIP Log(LOG_DEBUG, "in->avail_in %d, in->avail_out %d", in->avail_in, in->avail_out); #endif result = inflate( in, Z_SYNC_FLUSH ); if( result != Z_OK ) { Log(LOG_ALERT, "Decompression error: %s (code=%d, ni=%d, ai=%d, no=%d, ao=%d)!?", in->msg, result, in->next_in, in->avail_in, in->next_out, in->avail_out); Conn_Close(Idx, "Decompression error!", NULL, false); return false; } assert(z_rdatalen >= in->avail_in); in_len = z_rdatalen - in->avail_in; unzipbuf_used = READBUFFER_LEN - in->avail_out; #ifdef DEBUG_ZIP Log(LOG_DEBUG, "unzipbuf_used: %d - %d = %d", READBUFFER_LEN, in->avail_out, unzipbuf_used); #endif assert(unzipbuf_used <= READBUFFER_LEN); if (!array_catb(&My_Connections[Idx].rbuf, (char*) unzipbuf, (size_t)unzipbuf_used)) { Log (LOG_ALERT, "Decompression error: can't copy data!?"); Conn_Close(Idx, "Decompression error!", NULL, false); return false; } if( in->avail_in > 0 ) { array_moveleft(&My_Connections[Idx].zip.rbuf, 1, in_len ); } else { array_trunc( &My_Connections[Idx].zip.rbuf ); My_Connections[Idx].zip.bytes_in += unzipbuf_used; } return true; } /* Unzip_Buffer */
/* append trailing NUL byte to array */ bool array_cat0(array * a) { return array_catb(a, "", 1); }
/* append string to dest */ bool array_cats(array * dest, const char *src) { return array_catb(dest, src, strlen(src)); }
int array_cat(struct array *a, const void *dat) { return array_catb(a, dat, a->es); }