static void text_insert_help(struct menu *menu) { GtkTextBuffer *buffer; GtkTextIter start, end; const char *prompt = _(menu_get_prompt(menu)); struct gstr help = str_new(); menu_get_ext_help(menu, &help); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); gtk_text_buffer_get_bounds(buffer, &start, &end); gtk_text_buffer_delete(buffer, &start, &end); gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, NULL); gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, NULL); str_free(&help); }
void notify_script_err_msg (enum err_contest idxc, int fline, int lline, const char * msg, ...) { struct msg_cell *cell = emalloc (sizeof(struct msg_cell)); str_t tail; va_list ap; str_init_from_c (cell->msg, contest_id[idxc]); va_start (ap, msg); str_init (tail, 64); str_vprintf (tail, msg, 0, ap); str_append (cell->msg, tail, ' '); str_free (tail); va_end (ap); cell->line = emalloc(sizeof(struct line_info)); cell->line->first = fline; cell->line->last = lline; cell->next = top; top = cell; }
void str_replace_text(struct mystr* p_str, const char* p_from, const char* p_to) { static struct mystr s_lhs_chunk_str; static struct mystr s_rhs_chunk_str; unsigned int lhs_len; str_copy(&s_lhs_chunk_str, p_str); str_free(p_str); do { lhs_len = str_getlen(&s_lhs_chunk_str); str_split_text(&s_lhs_chunk_str, &s_rhs_chunk_str, p_from); /* Copy lhs to destination */ str_append_str(p_str, &s_lhs_chunk_str); /* If this was a 'hit', append the 'to' text */ if (str_getlen(&s_lhs_chunk_str) < lhs_len) { str_append_text(p_str, p_to); } /* Current rhs becomes new lhs */ str_copy(&s_lhs_chunk_str, &s_rhs_chunk_str); } while (!str_isempty(&s_lhs_chunk_str)); }
/* <MedlineDate>2003 Jan-Feb</MedlineDate> */ static int medin_medlinedate( fields *info, char *p, int level ) { int fstatus; str tmp; str_init( &tmp ); p = str_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 ); if ( str_memerr( &tmp ) ) return BIBL_ERR_MEMERR; if ( str_has_value( &tmp ) ) { fstatus = fields_add( info, "PARTDATE:YEAR", str_cstr( &tmp ), level ); if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; } p = str_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 ); if ( str_memerr( &tmp ) ) return BIBL_ERR_MEMERR; if ( str_has_value( &tmp ) ) { str_findreplace( &tmp, "-", "/" ); fstatus = fields_add( info, "PARTDATE:MONTH", str_cstr( &tmp ), level ); if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; } (void) str_cpytodelim( &tmp, skip_ws( p ), " \t\n\r", 0 ); if ( str_memerr( &tmp ) ) return BIBL_ERR_MEMERR; if ( str_has_value( &tmp ) ) { fstatus = fields_add( info, "PARTDATE:DAY", str_cstr( &tmp ), level ); if ( fstatus!=FIELDS_OK ) return BIBL_ERR_MEMERR; } str_free( &tmp ); return BIBL_OK; }
static int mtime_interpret(string_list_ty *result, const string_list_ty *args, const struct expr_position_ty *pp, const struct opcode_context_ty *ocp) { size_t j; trace(("mtime\n")); (void)pp; assert(result); assert(args); assert(args->nstrings); for (j = 1; j < args->nstrings; j++) { time_t mtime; long depth; depth = 32767; mtime = cook_mtime_newest(ocp, args->string[j], &depth, depth); if (mtime < 0) return -1; if (mtime == 0) string_list_append(result, str_false); else { struct tm *tm; char buffer[1000]; string_ty *s; tm = localtime(&mtime); strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", tm); s = str_from_c(buffer); string_list_append(result, s); str_free(s); } } return 0; }
void add_common_resource(resp r) { char outTemp[256]; strp outType; NAMEINFO_NODE *new_nameinfo; if (!r || !r->b || !r->b->buffer) return; /* Refuse to add a resource without data */ ALLOC(new_nameinfo, NAMEINFO_NODE); new_nameinfo->next = NULL; new_nameinfo->data.rcslength = r->b->len; new_nameinfo->data.rcsdata = (LPBYTE)buff_ind(r->b); r->b = NULL; new_nameinfo->data.rcsflags = r->flags; if (!HIWORD(r->name)) { if (LOWORD(r->name) > 0x7fff) FATAL(("Resource identifier %d is too large", (int)(LOWORD(r->name)))); new_nameinfo->data.rcsitemname = (char *)(LOWORD(r->name) | (r->type == RT_STRING ? 0x0000 : 0x8000)); } else new_nameinfo->data.rcsitemname = (char *)(r->name); if (HIWORD(r->type)) new_nameinfo->data.wType = (WORD)(RT_USER_DEF); else new_nameinfo->data.wType = LOWORD(r->type); incr_res_count((char *)r->type, new_nameinfo); if (!HIWORD(r->name)) sprintf(outTemp, "%d", (int)r->name); else sprintf(outTemp, "%s", r->name); outType = resource_type_name(r->type); VPRINT(("Added resource: %s %s", outType, outTemp)); str_free(outType); res_free(r); }
void ben_free_r(BEN * node) { ITEM *item = NULL; if (node == NULL) { return; } switch (node->t) { case BEN_DICT: if (node->v.d != NULL) { item = list_start(node->v.d); while (item != NULL) { item = ben_free_item(node, item); } list_free(node->v.d); } break; case BEN_LIST: if (node->v.l != NULL) { item = list_start(node->v.l); while (item != NULL) { item = ben_free_item(node, item); } list_free(node->v.l); } break; case BEN_STR: if (node->v.s != NULL) { str_free(node->v.s); } break; } }
void multi_fit_engine_print_fit_results(struct multi_fit_engine *fit, str_t text) { str_t pname; size_t k, j, kp; str_set_null(text); str_init(pname, 16); for(j = 0, kp = 0; j < fit->common_parameters->number; j++, kp++) { fit_param_t *fp = fit->common_parameters->values + j; get_param_name(fp, pname); str_printf_add(text, "COMMON / %9s : %.6g\n", CSTR(pname), gsl_vector_get(fit->results, j)); } for(k = 0; k < fit->samples_number; k++) { for(j = 0; j < fit->private_parameters->number; j++, kp++) { fit_param_t *fp = fit->private_parameters->values + j; get_param_name(fp, pname); str_printf_add(text, "SAMPLE(%02i)/ %9s : %.6g\n", k, CSTR(pname), gsl_vector_get(fit->results, kp)); } } str_append_c(text, "Residual Chi Square by sample:\n", '\n'); for(k = 0; k < fit->samples_number; k++) { double chisq = gsl_vector_get(fit->chisq, k); str_printf_add(text, "ChiSq(%02i): %g\n", k, chisq); } str_free(pname); }
NOEXPORT void win_log(LPCTSTR txt) { struct LIST *curr; size_t txt_len; static size_t log_len=0; txt_len=_tcslen(txt); curr=str_alloc(sizeof(struct LIST)+txt_len*sizeof(TCHAR)); curr->len=txt_len; _tcscpy(curr->txt, txt); curr->next=NULL; if(tail) tail->next=curr; tail=curr; if(!head) head=tail; log_len++; while(log_len>LOG_LINES) { curr=head; head=head->next; str_free(curr); log_len--; } new_logs=1; }
static int prepost_interpret(string_list_ty *result, const string_list_ty *args, const expr_position_ty *pp, const struct opcode_context_ty *ocp) { size_t j; trace(("prepost\n")); (void)ocp; assert(result); assert(args); assert(args->nstrings); if (args->nstrings < 3) { sub_context_ty *scp; scp = sub_context_new(); sub_var_set_string(scp, "Name", args->string[0]); error_with_position ( pp, scp, i18n("$name: requires two or more arguments") ); sub_context_delete(scp); return -1; } for (j = 3; j < args->nstrings; j++) { string_ty *s; s = str_cat_three(args->string[1], args->string[j], args->string[2]); string_list_append(result, s); str_free(s); } return 0; }
unsigned name2addrlist(SOCKADDR_LIST *addr_list, char *name) { char *tmp, *host_name, *port_name; unsigned retval; /* first check if this is a UNIX socket */ #ifdef HAVE_STRUCT_SOCKADDR_UN if(*name=='/') { if(offsetof(struct sockaddr_un, sun_path)+strlen(name)+1 > sizeof(struct sockaddr_un)) { s_log(LOG_ERR, "Unix socket path is too long"); return 0; /* no results */ } addr_list->addr=str_realloc(addr_list->addr, (addr_list->num+1)*sizeof(SOCKADDR_UNION)); addr_list->addr[addr_list->num].un.sun_family=AF_UNIX; strcpy(addr_list->addr[addr_list->num].un.sun_path, name); return ++(addr_list->num); /* ok - return the number of addresses */ } #endif /* setup host_name and port_name */ tmp=str_dup(name); port_name=strrchr(tmp, ':'); if(port_name) { host_name=tmp; *port_name++='\0'; } else { /* no ':' - use default host IP */ host_name=NULL; port_name=tmp; } /* fill addr_list structure */ retval=hostport2addrlist(addr_list, host_name, port_name); str_free(tmp); return retval; }
static void search_conf(void) { struct symbol **sym_arr; struct gstr res; again: switch (dialog_inputbox("Search Configuration Parameter", "Enter Keyword", 10, 75, NULL)) { case 0: break; case 1: show_helptext("Search Configuration", search_help); goto again; default: return; } sym_arr = sym_re_search(dialog_input_result); res = get_relations_str(sym_arr); free(sym_arr); show_textbox("Search Results", str_get(&res), 0, 0); str_free(&res); }
void http_client_request_unref(struct http_client_request **_req) { struct http_client_request *req = *_req; struct http_client *client = req->client; i_assert(req->refcount > 0); if (--req->refcount > 0) return; if (req->destroy_callback != NULL) { req->destroy_callback(req->destroy_context); req->destroy_callback = NULL; } /* only decrease pending request counter if this request was submitted */ if (req->state > HTTP_REQUEST_STATE_NEW) req->client->pending_requests--; http_client_request_debug(req, "Destroy (requests left=%d)", client->pending_requests); if (client->pending_requests == 0 && client->ioloop != NULL) io_loop_stop(client->ioloop); if (req->delayed_error != NULL) http_client_host_remove_request_error(req->host, req); if (req->payload_input != NULL) i_stream_unref(&req->payload_input); if (req->payload_output != NULL) o_stream_unref(&req->payload_output); if (req->headers != NULL) str_free(&req->headers); pool_unref(&req->pool); *_req = NULL; }
NOEXPORT void smtp_server(CLI *c) { char *line; s_poll_init(c->fds); s_poll_add(c->fds, c->local_rfd.fd, 1, 0); switch(s_poll_wait(c->fds, 0, 200)) { /* wait up to 200ms */ case 0: /* fd not ready to read */ s_log(LOG_DEBUG, "RFC 2487 detected"); break; case 1: /* fd ready to read */ s_log(LOG_DEBUG, "RFC 2487 not detected"); return; /* return if RFC 2487 is not used */ default: /* -1 */ sockerror("RFC2487 (s_poll_wait)"); longjmp(c->err, 1); } line=fd_getline(c, c->remote_fd.fd); if(!is_prefix(line, "220")) { s_log(LOG_ERR, "Unknown server welcome"); str_free(line); longjmp(c->err, 1); } fd_printf(c, c->local_wfd.fd, "%s + stunnel", line); str_free(line); line=fd_getline(c, c->local_rfd.fd); if(!is_prefix(line, "EHLO ")) { s_log(LOG_ERR, "Unknown client EHLO"); str_free(line); longjmp(c->err, 1); } fd_printf(c, c->local_wfd.fd, "250-%s Welcome", line); fd_putline(c, c->local_wfd.fd, "250 STARTTLS"); str_free(line); line=fd_getline(c, c->local_rfd.fd); if(!is_prefix(line, "STARTTLS")) { s_log(LOG_ERR, "STARTTLS expected"); str_free(line); longjmp(c->err, 1); } fd_putline(c, c->local_wfd.fd, "220 Go ahead"); str_free(line); }
NOEXPORT void connect_server(CLI *c) { char *request, *proto, *header; NAME_LIST host_list; request=fd_getline(c, c->local_rfd.fd); if(!is_prefix(request, "CONNECT ")) { fd_putline(c, c->local_wfd.fd, "HTTP/1.0 400 Bad Request Method"); fd_putline(c, c->local_wfd.fd, "Server: stunnel/" STUNNEL_VERSION); fd_putline(c, c->local_wfd.fd, ""); str_free(request); longjmp(c->err, 1); } proto=strchr(request+8, ' '); if(!proto || !is_prefix(proto, " HTTP/")) { fd_putline(c, c->local_wfd.fd, "HTTP/1.0 400 Bad Request Protocol"); fd_putline(c, c->local_wfd.fd, "Server: stunnel/" STUNNEL_VERSION); fd_putline(c, c->local_wfd.fd, ""); str_free(request); longjmp(c->err, 1); } *proto='\0'; header=str_dup(""); do { /* ignore any headers */ str_free(header); header=fd_getline(c, c->local_rfd.fd); } while(*header); /* not empty */ str_free(header); host_list.name=request+8; host_list.next=NULL; if(!namelist2addrlist(&c->connect_addr, &host_list, DEFAULT_LOOPBACK)) { fd_putline(c, c->local_wfd.fd, "HTTP/1.0 404 Not Found"); fd_putline(c, c->local_wfd.fd, "Server: stunnel/" STUNNEL_VERSION); fd_putline(c, c->local_wfd.fd, ""); str_free(request); longjmp(c->err, 1); } str_free(request); fd_putline(c, c->local_wfd.fd, "HTTP/1.0 200 OK"); fd_putline(c, c->local_wfd.fd, "Server: stunnel/" STUNNEL_VERSION); fd_putline(c, c->local_wfd.fd, ""); }
static void handle_dir_common(struct vsf_session* p_sess, int full_details) { static struct mystr s_option_str; static struct mystr s_filter_str; static struct mystr s_dir_name_str; static struct vsf_sysutil_statbuf* s_p_dirstat; int remote_fd; int dir_allow_read = 1; struct vsf_sysutil_dir* p_dir = 0; str_empty(&s_option_str); str_empty(&s_filter_str); /* By default open the current directory */ str_alloc_text(&s_dir_name_str, "."); if (!pasv_active(p_sess) && !port_active(p_sess)) { vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Use PORT or PASV first."); return; } /* Do we have an option? Going to be strict here - the option must come * first. e.g. "ls -a .." fine, "ls .. -a" not fine */ if (!str_isempty(&p_sess->ftp_arg_str) && str_get_char_at(&p_sess->ftp_arg_str, 0) == '-') { /* Chop off the '-' */ str_mid_to_end(&p_sess->ftp_arg_str, &s_option_str, 1); /* A space will separate options from filter (if any) */ str_split_char(&s_option_str, &s_filter_str, ' '); } else { /* The argument, if any, is just a filter */ str_copy(&s_filter_str, &p_sess->ftp_arg_str); } if (!str_isempty(&s_filter_str)) { /* First check - is it an outright directory, as in "ls /pub" */ p_dir = str_opendir(&s_filter_str); if (p_dir != 0) { /* Listing a directory! */ str_copy(&s_dir_name_str, &s_filter_str); str_free(&s_filter_str); } else { struct str_locate_result locate_result = str_locate_char(&s_filter_str, '/'); if (locate_result.found) { /* Includes a path! Reverse scan for / in the arg, to get the * base directory and filter (if any) */ str_copy(&s_dir_name_str, &s_filter_str); str_split_char_reverse(&s_dir_name_str, &s_filter_str, '/'); /* If we have e.g. "ls /.message", we just ripped off the leading * slash because it is the only one! */ if (str_isempty(&s_dir_name_str)) { str_alloc_text(&s_dir_name_str, "/"); } } } } if (p_dir == 0) { /* NOTE - failure check done below, it's not forgotten */ p_dir = str_opendir(&s_dir_name_str); } /* Fine, do it */ remote_fd = get_remote_transfer_fd(p_sess); if (vsf_sysutil_retval_is_error(remote_fd)) { goto dir_close_out; } vsf_cmdio_write(p_sess, FTP_DATACONN, "Here comes the directory listing."); if (p_sess->is_anonymous && p_dir && tunable_anon_world_readable_only) { vsf_sysutil_dir_stat(p_dir, &s_p_dirstat); if (!vsf_sysutil_statbuf_is_readable_other(s_p_dirstat)) { dir_allow_read = 0; } } if (p_dir == 0 || !dir_allow_read) { vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "Transfer done (but failed to open directory)."); } else { (void) vsf_ftpdataio_transfer_dir(p_sess, remote_fd, p_dir, &s_dir_name_str, &s_option_str, &s_filter_str, full_details); } (void) dispose_remote_transfer_fd(p_sess); dir_close_out: if (p_dir) { vsf_sysutil_closedir(p_dir); } port_cleanup(p_sess); pasv_cleanup(p_sess); }
static opcode_status_ty execute(const opcode_ty *op, opcode_context_ty *icp) { opcode_status_ty status; const opcode_setenv_append_ty *this; string_list_ty *name; string_list_ty *value; string_ty *s; char *tmp; trace(("opcode_setenv_append::execute()\n{\n")); status = opcode_status_success; this = (const opcode_setenv_append_ty *)op; value = opcode_context_string_list_pop(icp); name = opcode_context_string_list_pop(icp); switch (name->nstrings) { case 0: error_with_position ( &this->pos, 0, i18n("lefthand side of assignment is empty") ); status = opcode_status_error; break; case 1: /* * If the environment variable is already set, prepend * its existing value to the value list the user gave us. */ tmp = getenv(name->string[0]->str_text); if (tmp) { string_ty *tmp2; tmp2 = str_from_c(tmp); string_list_prepend(value, tmp2); str_free(tmp2); } s = wl2str(value, 0, value->nstrings, " "); env_set(name->string[0]->str_text, s->str_text); str_free(s); break; default: error_with_position ( &this->pos, 0, i18n("lefthand side of assignment is more than one word") ); status = opcode_status_error; break; } string_list_delete(name); string_list_delete(value); trace(("return %s;\n", opcode_status_name(status))); trace(("}\n")); return status; }
static opcode_status_ty script(const opcode_ty *op, opcode_context_ty *icp) { opcode_status_ty status; const opcode_setenv_append_ty *this; string_list_ty *name; string_list_ty *value; string_ty *name1; string_ty *name2; string_ty *value1; string_ty *value2; trace(("opcode_setenv_append::script()\n{\n")); status = opcode_status_success; this = (const opcode_setenv_append_ty *)op; value = opcode_context_string_list_pop(icp); name = opcode_context_string_list_pop(icp); switch (name->nstrings) { case 0: error_with_position ( &this->pos, 0, i18n("lefthand side of assignment is empty") ); status = opcode_status_error; break; case 1: name1 = wl2str(name, 0, name->nstrings, " "); name2 = str_quote_shell(name1); str_free(name1); value1 = wl2str(value, 0, value->nstrings, " "); value2 = str_quote_shell(value1); str_free(value1); printf("%s=%s\n", name2->str_text, value2->str_text); printf("export %s\n", name2->str_text); str_free(name1); str_free(value2); break; default: error_with_position ( &this->pos, 0, i18n("lefthand side of assignment is more than one word") ); status = opcode_status_error; break; } string_list_delete(name); string_list_delete(value); trace(("return %s;\n", opcode_status_name(status))); trace(("}\n")); return status; }
int s_poll_wait(s_poll_set *fds, int sec, int msec) { CONTEXT *context; /* current context */ static CONTEXT *to_free=NULL; /* delayed memory deallocation */ /* FIXME: msec parameter is currently ignored with UCONTEXT threads */ (void)msec; /* skip warning about unused parameter */ /* remove the current context from ready queue */ context=ready_head; ready_head=ready_head->next; if(!ready_head) /* the queue is empty */ ready_tail=NULL; /* it it safe to s_log() after new ready_head is set */ /* it's illegal to deallocate the stack of the current context */ if(to_free) { /* a delayed deallocation is scheduled */ #ifdef DEBUG_UCONTEXT s_log(LOG_DEBUG, "Releasing context %ld", to_free->id); #endif str_free(to_free->stack); str_free(to_free); to_free=NULL; } /* manage the current thread */ if(fds) { /* something to wait for -> swap the context */ context->fds=fds; /* set file descriptors to wait for */ context->finish=sec<0 ? -1 : time(NULL)+sec; /* append the current context to the waiting queue */ context->next=NULL; if(waiting_tail) waiting_tail->next=context; waiting_tail=context; if(!waiting_head) waiting_head=context; } else { /* nothing to wait for -> drop the context */ to_free=context; /* schedule for delayed deallocation */ } while(!ready_head) /* wait until there is a thread to switch to */ scan_waiting_queue(); /* switch threads */ if(fds) { /* swap the current context */ if(context->id!=ready_head->id) { #ifdef DEBUG_UCONTEXT s_log(LOG_DEBUG, "Context swap: %ld -> %ld", context->id, ready_head->id); #endif swapcontext(&context->context, &ready_head->context); #ifdef DEBUG_UCONTEXT s_log(LOG_DEBUG, "Current context: %ld", ready_head->id); #endif } return ready_head->ready; } else { /* drop the current context */ #ifdef DEBUG_UCONTEXT s_log(LOG_DEBUG, "Context set: %ld (dropped) -> %ld", context->id, ready_head->id); #endif setcontext(&ready_head->context); ioerror("setcontext"); /* should not ever happen */ return 0; } }
/* * run the request */ static HTTPResponse *_runRequest(WOAppReq *app, WOAppHandle woappHandle, WOInstanceHandle instHandle, HTTPRequest *req) { WOConnection *c; HTTPResponse *resp = NULL; int send_status, keepConnection, retryRequest = 0; const char *idString = NULL; WOLog(WO_INFO,"Trying to contact %s:%s on %s(%d)", app->name,app->instance,app->host,app->port); /* Tag the request with a unique identifier (if it hasn't been already) */ /* (It might already have been tagged if we are retrying the request due to refusing new sessions, for example) */ idString = req_HeaderForKey(req, REQUEST_ID_HEADER); if (idString == NULL) { String *requestID = tr_uniqueID(); if (requestID) { req_addHeader(req, REQUEST_ID_HEADER, requestID->text, STR_COPYVALUE); idString = req_HeaderForKey(req, REQUEST_ID_HEADER); str_free(requestID); } } do { c = tr_open(instHandle); /* connect */ if (c == NULL) { WOLog(WO_INFO,"%s:%s NOT LISTENING on %s(%d)", app->name,app->instance,app->host,app->port); app->error = err_connect; return NULL; } /* * app found and is listening on port */ if (app->scheduler->beginTransaction) app->scheduler->beginTransaction(app, instHandle); /* Make sure that we're the only connection header, and we're explicit about the setting */ req_removeHeader(req,CONNECTION); if (c->isPooled) { req_addHeader(req,CONNECTION,HTTP_KEEP_ALIVE,0); } else { req_addHeader(req,CONNECTION,HTTP_CLOSE,0); } WOLog(WO_INFO,"%s:%s on %s(%d) connected [pooled: %s]", app->name, app->instance, app->host, app->port, c->isPooled ? "Yes" : "No"); /* * send the request.... */ send_status = req_sendRequest(req, c->fd); if (send_status != 0) { if ((send_status == TR_RESET) && (retryRequest == 0) && !req->haveReadStreamedData) { /* If we get here the connection was reset. This means the instance has either quit or crashed. */ /* Bump the generation number so all pooled connections to this instance will be invalidated. */ /* Then retry the request with a new connection. If the instance is not running the retry will */ /* fail with a different error and the instance will be marked dead. */ _WOInstance *inst = ac_lockInstance(instHandle); /* note: if we get here, keepConnection == 0 --> this connection will be closed */ if (inst) { ac_cycleInstance(inst, c->generation); ac_unlockInstance(instHandle); } retryRequest++; WOLog(WO_INFO, "retrying request due to connection reset"); /* Must close connection before continuing */ tr_close(c, instHandle, 0); continue; } else { WOLog(WO_ERR,"Failed to send request"); tr_close(c, instHandle, 0); /* close app connection */ if (send_status == -1) app->error = err_read; else app->error = err_send; return NULL; } } /* Note that we have a request queued */ WOLog(WO_INFO,"Request %s sent, awaiting response", req->request_str); /* While the app is processing the request, take the opportunity to check/update the config. */ ac_readConfiguration(); /* * now wait for the response... */ resp = resp_getResponseHeaders(c, instHandle); /* go ahead and read the first chunk of response data */ if (resp && req->method != HTTP_HEAD_METHOD) { if (resp_getResponseContent(resp, 1) == -1) { resp_free(resp); resp = NULL; } } /* Validate the ID */ if (idString && resp) { const char *respID = st_valueFor(resp->headers, REQUEST_ID_HEADER); if (respID != NULL) { if (strcmp(respID, idString) != 0) { WOLog(WO_ERR, "Got response with wrong ID! Dumping response. request ID = %s, response ID = %s", idString, respID); /* note this will cause the connection to be closed below */ resp_free(resp); resp = NULL; } else st_removeKey(resp->headers, REQUEST_ID_HEADER); } else WOLog(WO_WARN, "Got response with no ID."); } app->response = resp; /* * check if this connection can be kept open */ keepConnection = 0; #ifndef CGI /* doesn't make sense to keep the connection for CGI */ if (resp && resp->headers) { const char *keepAlive; keepAlive = st_valueFor(resp->headers, CONNECTION); if (keepAlive) { /* if the keep alive header is set, honor the value */ if (strcasecmp(keepAlive, HTTP_KEEP_ALIVE) == 0) keepConnection = 1; } else { /* no keep alive header - keep alive by default for HTTP/1.1 only */ if (resp->flags & RESP_HTTP11) keepConnection = 1; } } #endif if (resp != NULL) { if (app->scheduler->finalizeTransaction) if (app->scheduler->finalizeTransaction(app, instHandle)) keepConnection = 0; st_removeKey(resp->headers, REFUSING_SESSIONS_HEADER); st_removeKey(resp->headers, LOAD_AVERAGE_HEADER); st_removeKey(resp->headers, CONNECTION); WOLog(WO_INFO,"received ->%d %s",resp->status,resp->statusMsg); retryRequest = 0; } else { if (c != NULL && tr_connectionWasReset(c)) { /* If we get here the connection was reset. This means the instance has either quit or crashed. */ /* Bump the generation number so all pooled connections to this instance will be invalidated. */ /* Then retry the request with a new connection. If the instance is not running the retry will */ /* fail with a different error and the instance will be marked dead. */ /* Note that only one retry due to a connection reset error is allowed. This is to prevent an */ /* infinite loop if the instance dies while processing the request and restarts quickly enough */ /* to process the retry. */ _WOInstance *inst = ac_lockInstance(instHandle); /* note: if we get here, keepConnection == 0 --> this connection will be closed */ if (inst) { ac_cycleInstance(inst, c->generation); ac_unlockInstance(instHandle); } retryRequest++; if (retryRequest == 1) WOLog(WO_INFO, "retrying request due to connection reset"); } else app->error = err_response; } if (resp && resp->content_read < resp->content_length) { resp->keepConnection = keepConnection; resp->instHandle = instHandle; resp->flags |= RESP_CLOSE_CONNECTION; } else { tr_close(c, instHandle, keepConnection); } } while (retryRequest == 1); return resp; }
NOEXPORT void cache_transfer(SSL_CTX *ctx, const u_char type, const long timeout, const u_char *key, const size_t key_len, const u_char *val, const size_t val_len, unsigned char **ret, size_t *ret_len) { char session_id_txt[2*SSL_MAX_SSL_SESSION_ID_LENGTH+1]; const char hex[16]="0123456789ABCDEF"; const char *type_description[]={"new", "get", "remove"}; unsigned i; SOCKET s; ssize_t len; struct timeval t; CACHE_PACKET *packet; SERVICE_OPTIONS *section; if(ret) /* set error as the default result if required */ *ret=NULL; /* log the request information */ for(i=0; i<key_len && i<SSL_MAX_SSL_SESSION_ID_LENGTH; ++i) { session_id_txt[2*i]=hex[key[i]>>4]; session_id_txt[2*i+1]=hex[key[i]&0x0f]; } session_id_txt[2*i]='\0'; s_log(LOG_INFO, "cache_transfer: request=%s, timeout=%ld, id=%s, length=%lu", type_description[type], timeout, session_id_txt, (long unsigned)val_len); /* allocate UDP packet buffer */ if(key_len>SSL_MAX_SSL_SESSION_ID_LENGTH) { s_log(LOG_ERR, "cache_transfer: session id too big (%lu bytes)", (unsigned long)key_len); return; } if(val_len>MAX_VAL_LEN) { s_log(LOG_ERR, "cache_transfer: encoded session too big (%lu bytes)", (unsigned long)key_len); return; } packet=str_alloc(sizeof(CACHE_PACKET)); /* setup packet */ packet->version=1; packet->type=type; packet->timeout=htons((u_short)(timeout<64800?timeout:64800));/* 18 hours */ memcpy(packet->key, key, key_len); memcpy(packet->val, val, val_len); /* create the socket */ s=s_socket(AF_INET, SOCK_DGRAM, 0, 0, "cache_transfer: socket"); if(s==INVALID_SOCKET) { str_free(packet); return; } /* retrieve pointer to the section structure of this ctx */ section=SSL_CTX_get_ex_data(ctx, index_opt); if(sendto(s, (void *)packet, #ifdef USE_WIN32 (int) #endif (sizeof(CACHE_PACKET)-MAX_VAL_LEN+val_len), 0, §ion->sessiond_addr.sa, addr_len(§ion->sessiond_addr))<0) { sockerror("cache_transfer: sendto"); closesocket(s); str_free(packet); return; } if(!ret || !ret_len) { /* no response is required */ closesocket(s); str_free(packet); return; } /* set recvfrom timeout to 200ms */ t.tv_sec=0; t.tv_usec=200; if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (void *)&t, sizeof t)<0) { sockerror("cache_transfer: setsockopt SO_RCVTIMEO"); closesocket(s); str_free(packet); return; } /* retrieve response */ len=recv(s, (void *)packet, sizeof(CACHE_PACKET), 0); closesocket(s); if(len<0) { if(get_last_socket_error()==S_EWOULDBLOCK || get_last_socket_error()==S_EAGAIN) s_log(LOG_INFO, "cache_transfer: recv timeout"); else sockerror("cache_transfer: recv"); str_free(packet); return; } /* parse results */ if(len<(int)sizeof(CACHE_PACKET)-MAX_VAL_LEN || /* too short */ packet->version!=1 || /* wrong version */ safe_memcmp(packet->key, key, key_len)) { /* wrong session id */ s_log(LOG_DEBUG, "cache_transfer: malformed packet received"); str_free(packet); return; } if(packet->type!=CACHE_RESP_OK) { s_log(LOG_INFO, "cache_transfer: session not found"); str_free(packet); return; } *ret_len=(size_t)len-(sizeof(CACHE_PACKET)-MAX_VAL_LEN); *ret=str_alloc(*ret_len); s_log(LOG_INFO, "cache_transfer: session found"); memcpy(*ret, packet->val, *ret_len); str_free(packet); }
NOEXPORT int conf_init(SERVICE_OPTIONS *section) { #if OPENSSL_VERSION_NUMBER>=0x10002000L SSL_CONF_CTX *cctx; NAME_LIST *curr; char *cmd, *param; if(!section->config) return 0; /* OK */ cctx=SSL_CONF_CTX_new(); if(!cctx) { sslerror("SSL_CONF_CTX_new"); return 1; /* FAILED */ } SSL_CONF_CTX_set_ssl_ctx(cctx, section->ctx); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_flags(cctx, section->option.client ? SSL_CONF_FLAG_CLIENT : SSL_CONF_FLAG_SERVER); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); for(curr=section->config; curr; curr=curr->next) { cmd=str_dup(curr->name); param=strchr(cmd, ':'); if(param) *param++='\0'; switch(SSL_CONF_cmd(cctx, cmd, param)) { case 2: s_log(LOG_DEBUG, "OpenSSL config \"%s\" set to \"%s\"", cmd, param); break; case 1: s_log(LOG_DEBUG, "OpenSSL config command \"%s\" executed", cmd); break; case -2: s_log(LOG_ERR, "OpenSSL config command \"%s\" was not recognised", cmd); str_free(cmd); SSL_CONF_CTX_free(cctx); return 1; /* FAILED */ case -3: s_log(LOG_ERR, "OpenSSL config command \"%s\" requires a parameter", cmd); str_free(cmd); SSL_CONF_CTX_free(cctx); return 1; /* FAILED */ default: sslerror("SSL_CONF_cmd"); str_free(cmd); SSL_CONF_CTX_free(cctx); return 1; /* FAILED */ } str_free(cmd); } if(!SSL_CONF_CTX_finish(cctx)) { sslerror("SSL_CONF_CTX_finish"); SSL_CONF_CTX_free(cctx); return 1; /* FAILED */ } SSL_CONF_CTX_free(cctx); #else /* OpenSSL earlier than 1.0.2 */ (void)section; /* squash the unused parameter warning */ #endif /* OpenSSL 1.0.2 or later */ return 0; /* OK */ }
static void dropbox_free(void *data) { struct dropbox_section *section = data; str_free(§ion->status); free(section); }
void fpga_loader_free(struct fpga_loader_t *loader) { str_free(loader->blif); str_free(loader->cwd); free(loader); }
void client_destroy(struct client *client, const char *reason) { if (client->destroyed) return; client->destroyed = TRUE; if (!client->login_success && reason != NULL) { reason = t_strconcat(reason, " ", client_get_extra_disconnect_reason(client), NULL); } if (reason != NULL) client_log(client, reason); if (last_client == client) last_client = client->prev; DLLIST_REMOVE(&clients, client); if (client->input != NULL) i_stream_close(client->input); if (client->output != NULL) o_stream_close(client->output); if (client->master_tag != 0) { i_assert(client->auth_request == NULL); i_assert(client->authenticating); i_assert(client->refcount > 1); client->authenticating = FALSE; master_auth_request_abort(master_auth, client->master_tag); client->refcount--; } else if (client->auth_request != NULL) { i_assert(client->authenticating); sasl_server_auth_abort(client); } else { i_assert(!client->authenticating); } if (client->io != NULL) io_remove(&client->io); if (client->to_disconnect != NULL) timeout_remove(&client->to_disconnect); if (client->to_auth_waiting != NULL) timeout_remove(&client->to_auth_waiting); if (client->auth_response != NULL) str_free(&client->auth_response); if (client->fd != -1) { net_disconnect(client->fd); client->fd = -1; } if (client->proxy_password != NULL) { safe_memset(client->proxy_password, 0, strlen(client->proxy_password)); i_free_and_null(client->proxy_password); } if (client->proxy_sasl_client != NULL) dsasl_client_free(&client->proxy_sasl_client); if (client->login_proxy != NULL) login_proxy_free(&client->login_proxy); if (client->v.destroy != NULL) client->v.destroy(client); if (client_unref(&client) && initial_service_count == 1) { /* as soon as this connection is done with proxying (or whatever), the process will die. there's no need for authentication anymore, so close the connection. do this only with initial service_count=1, in case there are other clients with pending authentications */ auth_client_disconnect(auth_client, "unnecessary connection"); } login_client_destroyed(); login_refresh_proctitle(); }
int req_sendRequest(HTTPRequest *req, net_fd socket) { struct iovec *buffers; int bufferCount, appStatus; int browserStatus = 0; String *headersString; buffers = WOMALLOC(3 * sizeof(struct iovec)); headersString = str_create(req->request_str, 0); if (headersString) { st_perform(req->headers, (st_perform_callback)req_appendHeader, headersString); } buffers[0].iov_base = headersString->text; buffers[0].iov_len = headersString->length; buffers[1].iov_base = "\r\n"; buffers[1].iov_len = 2; bufferCount = 2; if (req->content_length > 0) { bufferCount++; buffers[2].iov_base = req->content; buffers[2].iov_len = req->content_buffer_size; } appStatus = transport->sendBuffers(socket, buffers, bufferCount); str_free(headersString); /* If we are streaming the content data, continue until we have sent everything. */ /* Note that we reuse buffers, and the existing content-data buffer. */ if (req->content_length > req->content_buffer_size) { long total_sent = req->content_buffer_size; long len_read, amount_to_read; req->haveReadStreamedData = 1; while (total_sent < req->content_length) { amount_to_read = req->content_length - total_sent; if (amount_to_read > req->content_buffer_size) amount_to_read = req->content_buffer_size; len_read = req->getMoreContent(req, req->content, amount_to_read, 0); if (len_read > 0) { if(appStatus == 0) { buffers[0].iov_base = req->content; buffers[0].iov_len = len_read; appStatus = transport->sendBuffers(socket, buffers, 1); // 2009/04/28: in case of a transport error, carry on with reading // incoming input stream (= browser data). That way, // the browser (hopefully) switch to the receive mode // after sending the complete request and receives/shows // the adaptor error message (old behaviour: endless // sending/uploading view). if(appStatus != 0) { WOLog(WO_ERR, "Failed to send streamed content."); } } total_sent += len_read; } else if (len_read < 0) { WOLog(WO_ERR, "Failed to read streamed content."); browserStatus = -1; break; } } } WOFREE(buffers); if(browserStatus != 0) WOLog(WO_ERR, "error receiving request"); if (appStatus == 0) { // 2009/04/30: as long as we haven't received any error message from // the instance, flush the socket to complete the data // transfer! appStatus = transport->flush_connection(socket); } else WOLog(WO_ERR, "error sending request"); return ((appStatus != 0) ? appStatus : browserStatus); }
static int transfer_dir_internal(struct vsf_session* p_sess, int is_control, struct vsf_sysutil_dir* p_dir, const struct mystr* p_base_dir_str, const struct mystr* p_option_str, const struct mystr* p_filter_str, int is_verbose) { struct mystr_list dir_list = INIT_STRLIST; struct mystr_list subdir_list = INIT_STRLIST; struct mystr dir_prefix_str = INIT_MYSTR; struct mystr_list* p_subdir_list = 0; struct str_locate_result loc_result = str_locate_char(p_option_str, 'R'); int failed = 0; enum EVSFRWTarget target = kVSFRWData; if (is_control) { target = kVSFRWControl; } if (loc_result.found && tunable_ls_recurse_enable) { p_subdir_list = &subdir_list; } vsf_ls_populate_dir_list(&dir_list, p_subdir_list, p_dir, p_base_dir_str, p_option_str, p_filter_str, is_verbose); if (p_subdir_list) { int retval; str_copy(&dir_prefix_str, p_base_dir_str); str_append_text(&dir_prefix_str, ":\r\n"); retval = ftp_write_str(p_sess, &dir_prefix_str, target); if (retval != 0) { failed = 1; } } if (!failed) { failed = write_dir_list(p_sess, &dir_list, target); } /* Recurse into the subdirectories if required... */ if (!failed) { struct mystr sub_str = INIT_MYSTR; unsigned int num_subdirs = str_list_get_length(&subdir_list); unsigned int subdir_index; for (subdir_index = 0; subdir_index < num_subdirs; subdir_index++) { int retval; struct vsf_sysutil_dir* p_subdir; const struct mystr* p_subdir_str = str_list_get_pstr(&subdir_list, subdir_index); if (str_equal_text(p_subdir_str, ".") || str_equal_text(p_subdir_str, "..")) { continue; } str_copy(&sub_str, p_base_dir_str); str_append_char(&sub_str, '/'); str_append_str(&sub_str, p_subdir_str); p_subdir = str_opendir(&sub_str); if (p_subdir == 0) { /* Unreadable, gone missing, etc. - no matter */ continue; } str_alloc_text(&dir_prefix_str, "\r\n"); retval = ftp_write_str(p_sess, &dir_prefix_str, target); if (retval != 0) { failed = 1; vsf_sysutil_closedir(p_subdir); break; } retval = transfer_dir_internal(p_sess, is_control, p_subdir, &sub_str, p_option_str, p_filter_str, is_verbose); vsf_sysutil_closedir(p_subdir); if (retval != 0) { failed = 1; break; } } str_free(&sub_str); } str_list_free(&dir_list); str_list_free(&subdir_list); str_free(&dir_prefix_str); if (!failed) { return 0; } else { return -1; } }
void process_post_login(struct vsf_session* p_sess) { int retval; if (p_sess->is_anonymous) { vsf_sysutil_set_umask(tunable_anon_umask); p_sess->bw_rate_max = tunable_anon_max_rate; } else { vsf_sysutil_set_umask(tunable_local_umask); p_sess->bw_rate_max = tunable_local_max_rate; } if (tunable_async_abor_enable) { vsf_sysutil_install_sighandler(kVSFSysUtilSigURG, handle_sigurg, p_sess); vsf_sysutil_activate_sigurg(VSFTP_COMMAND_FD); } /* Kitsune */ vsf_sysutil_kitsune_set_update_point("postlogin.c"); if(!kitsune_is_updating()) { /* Handle any login message */ vsf_banner_dir_changed(p_sess, FTP_LOGINOK); vsf_cmdio_write(p_sess, FTP_LOGINOK, "Login successful. Have fun."); } else { /* Set sigchld function pointer (normally done in twoprocess.c) */ vsf_sysutil_default_sig(kVSFSysUtilSigCHLD); vsf_sysutil_install_async_sighandler(kVSFSysUtilSigCHLD, twoproc_handle_sigchld); } /* End Kitsune */ while(1) { if (tunable_setproctitle_enable) { vsf_sysutil_setproctitle("IDLE"); } /* Kitsune update point */ kitsune_update("postlogin.c"); /**DSU updatepoint */ /* Blocks */ vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str, &p_sess->ftp_arg_str, 1); if (tunable_setproctitle_enable) { struct mystr proctitle_str = INIT_MYSTR; str_copy(&proctitle_str, &p_sess->ftp_cmd_str); if (!str_isempty(&p_sess->ftp_arg_str)) { str_append_char(&proctitle_str, ' '); str_append_str(&proctitle_str, &p_sess->ftp_arg_str); } /* Suggestion from Solar */ str_replace_unprintable(&proctitle_str, '?'); vsf_sysutil_setproctitle_str(&proctitle_str); str_free(&proctitle_str); } if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT")) { vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye."); vsf_sysutil_exit(0); } else if (str_equal_text(&p_sess->ftp_cmd_str, "PWD") || str_equal_text(&p_sess->ftp_cmd_str, "XPWD")) { handle_pwd(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "CWD") || str_equal_text(&p_sess->ftp_cmd_str, "XCWD")) { handle_cwd(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "CDUP") || str_equal_text(&p_sess->ftp_cmd_str, "XCUP")) { handle_cdup(p_sess); } else if (tunable_pasv_enable && str_equal_text(&p_sess->ftp_cmd_str, "PASV")) { handle_pasv(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "RETR")) { handle_retr(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "NOOP")) { vsf_cmdio_write(p_sess, FTP_NOOPOK, "NOOP ok."); } else if (str_equal_text(&p_sess->ftp_cmd_str, "SYST")) { vsf_cmdio_write(p_sess, FTP_SYSTOK, "UNIX Type: L8"); } else if (str_equal_text(&p_sess->ftp_cmd_str, "HELP")) { vsf_cmdio_write(p_sess, FTP_BADHELP, "Sorry, I don't have help."); } else if (str_equal_text(&p_sess->ftp_cmd_str, "LIST")) { handle_list(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "TYPE")) { handle_type(p_sess); } else if (tunable_port_enable && str_equal_text(&p_sess->ftp_cmd_str, "PORT")) { handle_port(p_sess); } else if (tunable_write_enable && (tunable_anon_upload_enable || !p_sess->is_anonymous) && str_equal_text(&p_sess->ftp_cmd_str, "STOR")) { handle_stor(p_sess); } else if (tunable_write_enable && (tunable_anon_mkdir_write_enable || !p_sess->is_anonymous) && (str_equal_text(&p_sess->ftp_cmd_str, "MKD") || str_equal_text(&p_sess->ftp_cmd_str, "XMKD"))) { handle_mkd(p_sess); } else if (tunable_write_enable && (tunable_anon_other_write_enable || !p_sess->is_anonymous) && (str_equal_text(&p_sess->ftp_cmd_str, "RMD") || str_equal_text(&p_sess->ftp_cmd_str, "XRMD"))) { handle_rmd(p_sess); } else if (tunable_write_enable && (tunable_anon_other_write_enable || !p_sess->is_anonymous) && str_equal_text(&p_sess->ftp_cmd_str, "DELE")) { handle_dele(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "REST")) { handle_rest(p_sess); } else if (tunable_write_enable && (tunable_anon_other_write_enable || !p_sess->is_anonymous) && str_equal_text(&p_sess->ftp_cmd_str, "RNFR")) { handle_rnfr(p_sess); } else if (tunable_write_enable && (tunable_anon_other_write_enable || !p_sess->is_anonymous) && str_equal_text(&p_sess->ftp_cmd_str, "RNTO")) { handle_rnto(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "NLST")) { handle_nlst(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "SIZE")) { handle_size(p_sess); } else if (!p_sess->is_anonymous && str_equal_text(&p_sess->ftp_cmd_str, "SITE")) { handle_site(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "ABOR")) { vsf_cmdio_write(p_sess, FTP_ABOR_NOCONN, "No transfer to ABOR."); } else if (tunable_write_enable && (tunable_anon_other_write_enable || !p_sess->is_anonymous) && str_equal_text(&p_sess->ftp_cmd_str, "APPE")) { handle_appe(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "MDTM")) { handle_mdtm(p_sess); } else if (str_equal_text(&p_sess->ftp_cmd_str, "PASV") || str_equal_text(&p_sess->ftp_cmd_str, "PORT") || str_equal_text(&p_sess->ftp_cmd_str, "STOR") || str_equal_text(&p_sess->ftp_cmd_str, "MKD") || str_equal_text(&p_sess->ftp_cmd_str, "XMKD") || str_equal_text(&p_sess->ftp_cmd_str, "RMD") || str_equal_text(&p_sess->ftp_cmd_str, "XRMD") || str_equal_text(&p_sess->ftp_cmd_str, "DELE") || str_equal_text(&p_sess->ftp_cmd_str, "RNFR") || str_equal_text(&p_sess->ftp_cmd_str, "RNTO") || str_equal_text(&p_sess->ftp_cmd_str, "SITE") || str_equal_text(&p_sess->ftp_cmd_str, "APPE")) { vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); } else { vsf_cmdio_write(p_sess, FTP_BADCMD, "Unknown command."); } } }
time_t cook_mtime_newest(const opcode_context_ty *ocp, string_ty *path, long *depth_p, long max_fp_depth) { time_t result; trace(("cook_mtime_newest(path = \"%s\")\n{\n", path->str_text)); if (path->str_text[0] == '/') { result = os_mtime_newest(path); *depth_p = 0; } else { fp_value_ty *prv_fp; string_list_ty sl; size_t j; prv_fp = 0; result = 0; cook_search_list(ocp, &sl); *depth_p = sl.nstrings; for (j = 0; j < sl.nstrings; ++j) { fp_value_ty *fp; string_ty *s1; string_ty *s2; time_t t; s1 = sl.string[j]; s2 = os_path_cat(s1, path); /* * This allows the safe use of fp_search below, * since os_mtime_newest updates the fingerprint * cache for the file. */ t = os_mtime_newest(s2); if (!t) { /* File was not found */ str_free(s2); continue; } trace(("mtime(\"%s\") was %ld\n", s2->str_text, (long)t)); /* File found */ if (!prv_fp) { /* Shallowest file found */ result = t; *depth_p = j; trace(("is the first\n")); if (option_test(OPTION_FINGERPRINT)) { prv_fp = fp_search(s2); if (prv_fp) { /* Look for deeper copies */ str_free(s2); continue; } } str_free(s2); break; } /* Found a deeper version */ assert(option_test(OPTION_FINGERPRINT)); if ((long)j >= max_fp_depth) { str_free(s2); break; } fp = fp_search(s2); str_free(s2); if ( fp && str_equal ( fp->contents_fingerprint, prv_fp->contents_fingerprint ) ) { /* Deeper version is same as shallow one */ if (t > result) result = t; /* do not alter depth */ } else { trace(("was different\n")); break; } } string_list_destructor(&sl); } trace(("return %ld (%d);\n", (long)result, *depth_p)); trace(("}\n")); return result; }
void match_free(struct match *match) { str_free(match->str); free(match); }