static size_t parse_headers(void *ptr, size_t size, size_t nmemb, void *user) { size_t realsize = size * nmemb; const char *fptr, *endptr = NULL; const char * const cd_header = "Content-Disposition:"; const char * const fn_key = "filename="; struct dload_payload *payload = (struct dload_payload *)user; if(_alpm_raw_ncmp(cd_header, ptr, strlen(cd_header)) == 0) { if((fptr = strstr(ptr, fn_key))) { fptr += strlen(fn_key); /* find the end of the field, which is either a semi-colon, or the end of * the data. As per curl_easy_setopt(3), we cannot count on headers being * null terminated, so we look for the closing \r\n */ endptr = fptr + strcspn(fptr, ";\r\n") - 1; /* remove quotes */ if(*fptr == '"' && *endptr == '"') { fptr++; endptr--; } STRNDUP(payload->content_disp_name, fptr, endptr - fptr + 1, RET_ERR(payload->handle, ALPM_ERR_MEMORY, realsize)); } } return realsize; }
char * db_find_path_system(void) { char *b = NULL; char *p = NULL; CALLOC(b, PATH_MAX, sizeof(char)); snprintf(b, PATH_MAX, "%s/%s", DB_SYSTEM_PATH, DB_FILENAME); STRNDUP(p, b, PATH_MAX); FREE(b); return p; }
char * db_find_path_user(void) { char *b = NULL; char *p = NULL; CALLOC(b, PATH_MAX, sizeof(char)); if ((p = getenv("XDG_DATA_HOME")) != NULL); else if ((p = getenv("HOME")) != NULL); else msg(msg_error, MSG_U_HOMEUNSET); snprintf(b, PATH_MAX, "%s/%s/%s", p, DB_USER_PATH, DB_FILENAME); STRNDUP(p, b, PATH_MAX); FREE(b); return p; }
static char * _db_get_fts_query(const search_t *search) { char *query = NULL; size_t i = 0; if (search->substr.items != 0) { CALLOC(query, search->substr.len, sizeof(char)); memcpy(query, search->substr.buf, search->substr.len); for (i = 0; i < search->substr.len - 1; i++) if (query[i] == '\0') query[i] = ' '; } else { STRNDUP(query, "*", 2); } return query; }
PUBLIC DBnamescheme * DBMakeNamescheme(char const *fmt, ...) { va_list ap; int i, j, k, n, pass, ncspecs, done, saved_narrefs; DBnamescheme *rv = 0; DBfile *dbfile = 0; char const *relpath = 0; /* We have nothing to do for a null or empty format string */ if (fmt == 0 || *fmt == '\0') return 0; /* Start by allocating an empty name scheme */ rv = DBAllocNamescheme(); // set the delimeter character n = 0; while (fmt[n] != '\0') { if (fmt[n] == '%' && fmt[n+1] != '%') break; n++; } if (fmt[n] == '%') // have at least one conversion spec rv->delim = fmt[0]; else rv->delim = '\0'; /* compute length up to max of 4096 of initial segment of fmt representing the printf-style format string. */ n = 1; while (n < 4096 && fmt[n] != '\0' && fmt[n] != rv->delim) n++; if (n == 4096) /* we pick arb. upper bound in length of 4096 */ { DBFreeNamescheme(rv); return 0; } /* grab just the part of fmt that is the printf-style format string */ rv->fmt = STRNDUP(&fmt[1],n-1); rv->fmtlen = n-1; /* In 2 passes, count conversion specs. and then setup pointers to each */ for (pass = 0; pass < 2; pass++) { if (pass == 1) { rv->fmtptrs = (const char **) calloc(rv->ncspecs+1, sizeof(char*)); rv->ncspecs = 0; } for (i = 0; i < rv->fmtlen-1; i++) { if (rv->fmt[i] == '%' && rv->fmt[i+1] != '%') { if (pass == 1) rv->fmtptrs[rv->ncspecs] = &(rv->fmt[i]); rv->ncspecs++; } } } rv->fmtptrs[rv->ncspecs] = &(rv->fmt[n+1]); /* If there are no conversion specs., we have nothing to do */ /* However, in this case, assume the first char is a real char. */ if (rv->ncspecs == 0) { free(rv->fmt); rv->fmt = STRNDUP(&fmt[0],n); rv->fmtlen = n; return rv; } /* Make a pass through rest of fmt string to count array refs in the expression substrings. */ i = n+1; while (i < 4096 && fmt[i] != '\0') { if (fmt[i] == '$' || fmt[i] == '#') rv->narrefs++; i++; } if (i == 4096) { DBFreeNamescheme(rv); return 0; } /* allocate various arrays needed by the naming scheme */ rv->exprstrs = (char **) calloc(rv->ncspecs, sizeof(char*)); if (rv->narrefs > 0) { void *dummy; rv->arrnames = (char **) calloc(rv->narrefs, sizeof(char*)); rv->arrvals = (void **) calloc(rv->narrefs, sizeof(void*)); rv->arrsizes = (int *) calloc(rv->narrefs, sizeof(int)); /* If we have non-zero ext. array references, then we may have the case of '0, DBfile*'. So, check for that now */ va_start(ap, fmt); dummy = va_arg(ap, void *); if (dummy == 0) { dbfile = va_arg(ap, DBfile *); relpath = va_arg(ap, char const *); rv->arralloc = 1; }
PUBLIC DBnamescheme * DBMakeNamescheme(const char *fmt, ...) { va_list ap; int i, j, k, n, pass, ncspecs, done; DBnamescheme *rv = 0; /* We have nothing to do for a null or empty format string */ if (fmt == 0 || *fmt == '\0') return 0; /* Start by allocating an empty name scheme */ rv = DBAllocNamescheme(); /* set the delimeter character */ rv->delim = fmt[0]; /* compute length up to max of 4096 of initial segment of fmt representing the printf-style format string. */ n = 1; while (n < 4096 && fmt[n] != '\0' && fmt[n] != rv->delim) n++; if (n == 4096) /* we pick arb. upper bound in length of 4096 */ { DBFreeNamescheme(rv); return 0; } /* grab just the part of fmt that is the printf-style format string */ rv->fmt = STRNDUP(&fmt[1],n-1); rv->fmtlen = n-1; /* In 2 passes, count conversion specs. and then setup pointers to each */ for (pass = 0; pass < 2; pass++) { if (pass == 1) { rv->fmtptrs = (const char **) calloc(rv->ncspecs+1, sizeof(char*)); rv->ncspecs = 0; } for (i = 0; i < rv->fmtlen-1; i++) { if (rv->fmt[i] == '%' && rv->fmt[i+1] != '%') { if (pass == 1) rv->fmtptrs[rv->ncspecs] = &(rv->fmt[i]); rv->ncspecs++; } } } rv->fmtptrs[rv->ncspecs] = &(rv->fmt[n+1]); /* If there are no conversion specs., we have nothing to do */ if (rv->ncspecs == 0) return rv; /* Make a pass through rest of fmt string to count array refs in the expression substrings. */ i = n+1; while (i < 4096 && fmt[i] != '\0') { if (fmt[i] == '$' || fmt[i] == '#') rv->narrefs++; i++; } if (i == 4096) { DBFreeNamescheme(rv); return 0; } /* allocate various arrays needed by the naming scheme */ rv->exprstrs = (char **) calloc(rv->ncspecs, sizeof(char*)); if (rv->narrefs > 0) { rv->arrnames = (char **) calloc(rv->narrefs, sizeof(char*)); rv->arrvals = (const int **) calloc(rv->narrefs, sizeof(int*)); } /* Ok, now go through rest of fmt string a second time and grab each expression that goes with each conversion spec. Also, handle array refs */ i = n+1; rv->narrefs = 0; ncspecs = 0; va_start(ap, fmt); done = 0; while (!done) { if (fmt[i] == '$' || fmt[i] == '#') { for (j = 1; fmt[i+j] != '['; j++) ; for (k = 0; k < rv->narrefs; k++) { if (strncmp(&fmt[i+1],rv->arrnames[k],j-1) == 0) break; } if (k == rv->narrefs) { rv->arrnames[k] = STRNDUP(&fmt[i+1], j-1); rv->arrvals[k] = va_arg(ap, const int *); rv->narrefs++; } } else if (fmt[i] == rv->delim || fmt[i] == '\0')
; for (k = 0; k < rv->narrefs; k++) { if (strncmp(&fmt[i+1],rv->arrnames[k],j-1) == 0) break; } if (k == rv->narrefs) { rv->arrnames[k] = STRNDUP(&fmt[i+1], j-1); rv->arrvals[k] = va_arg(ap, const int *); rv->narrefs++; } } else if (fmt[i] == rv->delim || fmt[i] == '\0') { rv->exprstrs[ncspecs] = STRNDUP(&fmt[n+1],i-(n+1)); ncspecs++; if (fmt[i] == '\0' || (fmt[i] == rv->delim && fmt[i] == '\0')) done = 1; n = i; } i++; } va_end(ap); return rv; } PUBLIC const char * DBGetName(DBnamescheme *ns, int natnum)
boolean_t iosocket_wait(io_desc *iod, int4 timepar) { struct timeval utimeout; ABS_TIME cur_time, end_time; struct sockaddr_storage peer; /* socket address + port */ fd_set tcp_fd; d_socket_struct *dsocketptr; socket_struct *socketptr, *newsocketptr; socket_interrupt *sockintr; char *errptr; int4 errlen, ii, msec_timeout; int rv, max_fd, len; GTM_SOCKLEN_TYPE size; boolean_t zint_restart; mv_stent *mv_zintdev; int retry_num; struct sockaddr *peer_sa_ptr; char port_buffer[NI_MAXSERV], ipaddr[SA_MAXLEN + 1]; int errcode; /* check for validity */ assert(iod->type == gtmsocket); dsocketptr = (d_socket_struct *)iod->dev_sp; sockintr = &dsocketptr->sock_save_state; peer_sa_ptr = ((struct sockaddr *)(&peer)); /* Check for restart */ if (!dsocketptr->mupintr) /* Simple path, no worries*/ zint_restart = FALSE; else { /* We have a pending wait restart of some sort - check we aren't recursing on this device */ if (sockwhich_invalid == sockintr->who_saved) GTMASSERT; /* Interrupt should never have an invalid save state */ if (dollar_zininterrupt) rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZINTRECURSEIO); if (sockwhich_wait != sockintr->who_saved) GTMASSERT; /* ZINTRECURSEIO should have caught */ DBGSOCK((stdout, "socwait: *#*#*#*#*#*#*# Restarted interrupted wait\n")); mv_zintdev = io_find_mvstent(iod, FALSE); if (mv_zintdev) { if (sockintr->end_time_valid) /* Restore end_time for timeout */ end_time = sockintr->end_time; /* Done with this mv_stent. Pop it off if we can, else mark it inactive. */ if (mv_chain == mv_zintdev) POP_MV_STENT(); /* pop if top of stack */ else { /* else mark it unused */ mv_zintdev->mv_st_cont.mvs_zintdev.buffer_valid = FALSE; mv_zintdev->mv_st_cont.mvs_zintdev.io_ptr = NULL; } zint_restart = TRUE; DBGSOCK((stdout, "socwait: mv_stent found - endtime: %d/%d\n", end_time.at_sec, end_time.at_usec)); } else DBGSOCK((stdout, "socwait: no mv_stent found !!\n")); dsocketptr->mupintr = FALSE; sockintr->who_saved = sockwhich_invalid; } /* check for events */ FD_ZERO(&tcp_fd); while (TRUE) { max_fd = 0; for (ii = 0; ii < dsocketptr->n_socket; ii++) { socketptr = dsocketptr->socket[ii]; if ((socket_listening == socketptr->state) || (socket_connected == socketptr->state)) { FD_SET(socketptr->sd, &tcp_fd); max_fd = MAX(max_fd, socketptr->sd); } } utimeout.tv_sec = timepar; utimeout.tv_usec = 0; msec_timeout = timeout2msec(timepar); sys_get_curr_time(&cur_time); if (!zint_restart || !sockintr->end_time_valid) add_int_to_abs_time(&cur_time, msec_timeout, &end_time); else { /* end_time taken from restart data. Compute what msec_timeout should be so timeout timer gets set correctly below. */ DBGSOCK((stdout, "socwait: Taking timeout end time from wait restart data\n")); cur_time = sub_abs_time(&end_time, &cur_time); if (0 > cur_time.at_sec) { msec_timeout = -1; utimeout.tv_sec = 0; utimeout.tv_usec = 0; } else { msec_timeout = (int4)(cur_time.at_sec * 1000 + cur_time.at_usec / 1000); utimeout.tv_sec = cur_time.at_sec; utimeout.tv_usec = (gtm_tv_usec_t)cur_time.at_usec; } } sockintr->end_time_valid = FALSE; for ( ; ; ) { rv = select(max_fd + 1, (void *)&tcp_fd, (void *)0, (void *)0, (timepar == NO_M_TIMEOUT ? (struct timeval *)0 : &utimeout)); if (0 > rv && EINTR == errno) { if (0 != outofband) { DBGSOCK((stdout, "socwait: outofband interrupt received (%d) -- " "queueing mv_stent for wait intr\n", outofband)); PUSH_MV_STENT(MVST_ZINTDEV); mv_chain->mv_st_cont.mvs_zintdev.io_ptr = iod; mv_chain->mv_st_cont.mvs_zintdev.buffer_valid = FALSE; sockintr->who_saved = sockwhich_wait; sockintr->end_time = end_time; sockintr->end_time_valid = TRUE; dsocketptr->mupintr = TRUE; socketus_interruptus++; DBGSOCK((stdout, "socwait: mv_stent queued - endtime: %d/%d interrupts: %d\n", end_time.at_sec, end_time.at_usec, socketus_interruptus)); outofband_action(FALSE); GTMASSERT; /* Should *never* return from outofband_action */ return FALSE; /* For the compiler.. */ } sys_get_curr_time(&cur_time); cur_time = sub_abs_time(&end_time, &cur_time); if (0 > cur_time.at_sec) { rv = 0; /* time out */ break; } utimeout.tv_sec = cur_time.at_sec; utimeout.tv_usec = (gtm_tv_usec_t)cur_time.at_usec; } else break; /* either other error or done */ } if (rv == 0) { iod->dollar.key[0] = '\0'; return FALSE; } else if (rv < 0) { errptr = (char *)STRERROR(errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKWAIT, 0, ERR_TEXT, 2, errlen, errptr); return FALSE; } /* find out which socket is ready */ for (ii = 0; ii < dsocketptr->n_socket; ii++) { socketptr = dsocketptr->socket[ii]; if (0 != FD_ISSET(socketptr->sd, &tcp_fd)) break; } assert(ii < dsocketptr->n_socket); if (socket_listening == socketptr->state) { if (gtm_max_sockets <= dsocketptr->n_socket) { rts_error_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_SOCKMAX, 1, gtm_max_sockets); return FALSE; } size = SIZEOF(struct sockaddr_storage); rv = tcp_routines.aa_accept(socketptr->sd, peer_sa_ptr, &size); if (-1 == rv) { # ifdef __hpux if (ENOBUFS == errno) continue; /* On HP-UX, ENOBUFS may indicate a transient condition; retry */ # endif errptr = (char *)STRERROR(errno); errlen = STRLEN(errptr); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_SOCKACPT, 0, ERR_TEXT, 2, errlen, errptr); return FALSE; } SOCKET_DUP(socketptr, newsocketptr); newsocketptr->sd = rv; SOCKET_ADDR_COPY(newsocketptr->remote, peer_sa_ptr, size); /* translate internal address to numeric ip address */ GETNAMEINFO(peer_sa_ptr, size, ipaddr, SA_MAXLEN, NULL, 0, NI_NUMERICHOST, errcode); if (0 != errcode) { SOCKET_FREE(newsocketptr); RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return FALSE; } if (NULL != newsocketptr->remote.saddr_ip) free(newsocketptr->remote.saddr_ip); STRNDUP(ipaddr, SA_MAXLEN, newsocketptr->remote.saddr_ip); /* translate internal address to port number*/ GETNAMEINFO(peer_sa_ptr, size, NULL, 0, port_buffer, NI_MAXSERV, NI_NUMERICSERV, errcode); if (0 != errcode) { SOCKET_FREE(newsocketptr); RTS_ERROR_ADDRINFO(NULL, ERR_GETNAMEINFO, errcode); return FALSE; } newsocketptr->remote.port = ATOI(port_buffer); newsocketptr->state = socket_connected; newsocketptr->passive = FALSE; newsocketptr->first_read = newsocketptr->first_write = TRUE; /* put the new-born socket to the list and create a handle for it */ iosocket_handle(newsocketptr->handle, &newsocketptr->handle_len, TRUE, dsocketptr); dsocketptr->socket[dsocketptr->n_socket++] = newsocketptr; dsocketptr->current_socket = dsocketptr->n_socket - 1; len = SIZEOF(CONNECTED) - 1; memcpy(&iod->dollar.key[0], CONNECTED, len); iod->dollar.key[len++] = '|'; memcpy(&iod->dollar.key[len], newsocketptr->handle, newsocketptr->handle_len); len += newsocketptr->handle_len; iod->dollar.key[len++] = '|'; strncpy(&iod->dollar.key[len], newsocketptr->remote.saddr_ip, DD_BUFLEN - 1 - len); iod->dollar.key[DD_BUFLEN-1] = '\0'; /* In case we fill the buffer */ } else { assert(socket_connected == socketptr->state); dsocketptr->current_socket = ii; len = SIZEOF(READ) - 1; memcpy(&iod->dollar.key[0], READ, len); iod->dollar.key[len++] = '|'; memcpy(&iod->dollar.key[len], socketptr->handle, socketptr->handle_len); len += socketptr->handle_len; iod->dollar.key[len++] = '|'; if (NULL != socketptr->remote.saddr_ip) { strncpy(&iod->dollar.key[len], socketptr->remote.saddr_ip, DD_BUFLEN - 1 - len); iod->dollar.key[DD_BUFLEN-1] = '\0'; } else iod->dollar.key[len] = '\0'; } break; }
/** Helper function: read the next token from *s, advance *s to the end of the * token, and return the parsed token. Parse *<b>s</b> according to the list * of tokens in <b>table</b>. */ directory_token_t * get_next_token(memarea_t *area, const char **s, const char *eos, token_rule_t *table) { /** Reject any object at least this big; it is probably an overflow, an * attack, a bug, or some other nonsense. */ #define MAX_UNPARSED_OBJECT_SIZE (128*1024) /** Reject any line at least this big; it is probably an overflow, an * attack, a bug, or some other nonsense. */ #define MAX_LINE_LENGTH (128*1024) const char *next, *eol, *obstart; size_t obname_len; int i; directory_token_t *tok; obj_syntax o_syn = NO_OBJ; char ebuf[128]; const char *kwd = ""; tor_assert(area); tok = ALLOC_ZERO(sizeof(directory_token_t)); tok->tp = ERR_; /* Set *s to first token, eol to end-of-line, next to after first token */ *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */ tor_assert(eos >= *s); eol = memchr(*s, '\n', eos-*s); if (!eol) eol = eos; if (eol - *s > MAX_LINE_LENGTH) { RET_ERR("Line far too long"); } next = find_whitespace_eos(*s, eol); if (!strcmp_len(*s, "opt", next-*s)) { /* Skip past an "opt" at the start of the line. */ *s = eat_whitespace_eos_no_nl(next, eol); next = find_whitespace_eos(*s, eol); } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */ RET_ERR("Unexpected EOF"); } /* Search the table for the appropriate entry. (I tried a binary search * instead, but it wasn't any faster.) */ for (i = 0; table[i].t ; ++i) { if (!strcmp_len(*s, table[i].t, next-*s)) { /* We've found the keyword. */ kwd = table[i].t; tok->tp = table[i].v; o_syn = table[i].os; *s = eat_whitespace_eos_no_nl(next, eol); /* We go ahead whether there are arguments or not, so that tok->args is * always set if we want arguments. */ if (table[i].concat_args) { /* The keyword takes the line as a single argument */ tok->args = ALLOC(sizeof(char*)); tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */ tok->n_args = 1; } else { /* This keyword takes multiple arguments. */ if (get_token_arguments(area, tok, *s, eol)<0) { tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd); RET_ERR(ebuf); } *s = eol; } if (tok->n_args < table[i].min_args) { tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd); RET_ERR(ebuf); } else if (tok->n_args > table[i].max_args) { tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd); RET_ERR(ebuf); } break; } } if (tok->tp == ERR_) { /* No keyword matched; call it an "K_opt" or "A_unrecognized" */ if (**s == '@') tok->tp = A_UNKNOWN_; else tok->tp = K_OPT; tok->args = ALLOC(sizeof(char*)); tok->args[0] = STRNDUP(*s, eol-*s); tok->n_args = 1; o_syn = OBJ_OK; } /* Check whether there's an object present */ *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */ tor_assert(eos >= *s); eol = memchr(*s, '\n', eos-*s); if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */ goto check_object; obstart = *s; /* Set obstart to start of object spec */ if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */ strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */ (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */ RET_ERR("Malformed object: bad begin line"); } tok->object_type = STRNDUP(*s+11, eol-*s-16); obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */ *s = eol+1; /* Set *s to possible start of object data (could be eos) */ /* Go to the end of the object */ next = tor_memstr(*s, eos-*s, "-----END "); if (!next) { RET_ERR("Malformed object: missing object end line"); } tor_assert(eos >= next); eol = memchr(next, '\n', eos-next); if (!eol) /* end-of-line marker, or eos if there's no '\n' */ eol = eos; /* Validate the ending tag, which should be 9 + NAME + 5 + eol */ if ((size_t)(eol-next) != 9+obname_len+5 || strcmp_len(next+9, tok->object_type, obname_len) || strcmp_len(eol-5, "-----", 5)) { tor_snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s", tok->object_type); ebuf[sizeof(ebuf)-1] = '\0'; RET_ERR(ebuf); } if (next - *s > MAX_UNPARSED_OBJECT_SIZE) RET_ERR("Couldn't parse object: missing footer or object much too big."); if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */ tok->key = crypto_pk_new(); if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart)) RET_ERR("Couldn't parse public key."); } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */ tok->key = crypto_pk_new(); if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart)) RET_ERR("Couldn't parse private key."); } else { /* If it's something else, try to base64-decode it */ int r; tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */ r = base64_decode(tok->object_body, next-*s, *s, next-*s); if (r<0) RET_ERR("Malformed object: bad base64-encoded data"); tok->object_size = r; } *s = eol; check_object: tok = token_check_object(area, kwd, tok, o_syn); done_tokenizing: return tok; #undef RET_ERR #undef ALLOC #undef ALLOC_ZERO #undef STRDUP #undef STRNDUP }