static int foreach_proc(void *rock, const char *key, size_t keylen, const char *data, size_t datalen) { struct seendata sd = SEENDATA_INITIALIZER; struct seendata_rock *sr = (struct seendata_rock *)rock; char *name = xstrndup(key, keylen); int r; parse_data(data, datalen, &sd); r = (sr->f)(name, &sd, sr->rock); seen_freedata(&sd); free(name); return r; }
char *xstrdup_between(const char *src, const char *open, const char *close) { const char *start = strstr(src, open); if (start == NULL) { log_debug("Open tag not found: '%s'", open); return NULL; } start += strlen(open); const char *stop = strstr(start, close); if (stop == NULL) { log_debug("Close tag not found: '%s'", close); return NULL; } return xstrndup(start, stop - start); }
VarRef *VarRefParseFromScope(const char *var_ref_string, const char *scope) { if (!scope) { return VarRefParseFromNamespaceAndScope(var_ref_string, NULL, NULL, CF_NS, '.'); } const char *scope_start = strchr(scope, CF_NS); if (scope_start) { char *ns = xstrndup(scope, scope_start - scope); VarRef *ref = VarRefParseFromNamespaceAndScope(var_ref_string, ns, scope_start + 1, CF_NS, '.'); free(ns); return ref; } else { return VarRefParseFromNamespaceAndScope(var_ref_string, NULL, scope, CF_NS, '.'); } }
static long ff_regexp(const char *line, long len, char *buffer, long buffer_size, void *priv) { char *line_buffer; struct ff_regs *regs = priv; regmatch_t pmatch[2]; int i; int result = -1; /* Exclude terminating newline (and cr) from matching */ if (len > 0 && line[len-1] == '\n') { if (len > 1 && line[len-2] == '\r') len -= 2; else len--; } line_buffer = xstrndup(line, len); /* make NUL terminated */ for (i = 0; i < regs->nr; i++) { struct ff_reg *reg = regs->array + i; if (!regexec(®->re, line_buffer, 2, pmatch, 0)) { if (reg->negate) goto fail; break; } } if (regs->nr <= i) goto fail; i = pmatch[1].rm_so >= 0 ? 1 : 0; line += pmatch[i].rm_so; result = pmatch[i].rm_eo - pmatch[i].rm_so; if (result > buffer_size) result = buffer_size; while (result > 0 && (isspace(line[result - 1]))) result--; memcpy(buffer, line, result); fail: free(line_buffer); return result; }
rewritetoken * rewriteURLCompile(const char *urlfmt) { rewritetoken *head = NULL; rewritetoken **tail = &head; rewritetoken *_new = NULL; const char *stt = urlfmt; debug(85, 3) ("rewriteURLCompile(%s)\n", urlfmt); while (*urlfmt != '\0') { int urlEncode = 0; while (*urlfmt != '\0' && *urlfmt != '%') ++urlfmt; if (urlfmt != stt) { _new = newRedirectTokenStr(RFT_STRING, xstrndup(stt, urlfmt - stt + 1), urlfmt - stt, 0); *tail = _new; tail = &_new->next; if (*urlfmt == '\0') break; stt = ++urlfmt; } switch (urlfmt[0]) { case '#': stt = ++urlfmt; urlEncode = 1; break; case '%': stt = ++urlfmt; _new = newRedirectTokenStr(RFT_STRING, xstrdup("%"), 1, 0); *tail = _new; tail = &_new->next; continue; break; } _new = newRedirectToken(&urlfmt, urlEncode); *tail = _new; tail = &_new->next; stt = urlfmt; } return head; }
/* * For local mounts, add heartbeat=none. * For userspace clusterstack, add cluster_stack=xxxx. * For o2cb with local heartbeat, add heartbeat=local. * For o2cb with global heartbeat, add heartbeat=global. */ static errcode_t add_mount_options(ocfs2_filesys *fs, struct o2cb_cluster_desc *cluster, char **optstr) { char *add, *extra = NULL; char stackstr[strlen(OCFS2_CLUSTER_STACK_ARG) + OCFS2_STACK_LABEL_LEN + 1]; struct ocfs2_super_block *sb = OCFS2_RAW_SB(fs->fs_super); if (ocfs2_mount_local(fs) || ocfs2_is_hard_readonly(fs)) { add = OCFS2_HB_NONE; goto addit; } if (cluster->c_stack && strcmp(cluster->c_stack, OCFS2_CLASSIC_CLUSTER_STACK)) { snprintf(stackstr, sizeof(stackstr), "%s%s", OCFS2_CLUSTER_STACK_ARG, cluster->c_stack); add = stackstr; goto addit; } if (ocfs2_cluster_o2cb_global_heartbeat(sb)) { add = OCFS2_HB_GLOBAL; goto addit; } add = OCFS2_HB_LOCAL; addit: if (*optstr && *(*optstr)) extra = xstrconcat3(*optstr, ",", add); else extra = xstrndup(add, strlen(add)); if (!extra) return OCFS2_ET_NO_MEMORY; *optstr = extra; return 0; }
/*! \brief PASS command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = password * - parv[2] = unused * - parv[3] = TS protocol version * - parv[4] = server ID (SID) */ static int mr_pass(struct Client *source_p, int parc, char *parv[]) { assert(MyConnect(source_p)); if (EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "PASS"); return 0; } MyFree(source_p->connection->password); source_p->connection->password = xstrndup(parv[1], IRCD_MIN(strlen(parv[1]), PASSWDLEN)); /* Only do this stuff if we are doing ts6 */ if (parc > 4) if (atoi(parv[3]) >= 6 && valid_sid(parv[4])) strlcpy(source_p->id, parv[4], sizeof(source_p->id)); return 0; }
/* if num = 1, it returns the want status, 2 returns flag, 3 returns status */ unsigned int get_status(const unsigned int status_node, const int num) { char *status_string = name_hashtable[status_hashtable[status_node]->status]; char *state_sub_string; unsigned int state_sub_num; int len; int i; /* set tmp_string to point to the start of the word number */ for (i = 1; i < num; i++) { /* skip past a word */ status_string += strcspn(status_string, " "); /* skip past the seperating spaces */ status_string += strspn(status_string, " "); } len = strcspn(status_string, " \n\0"); state_sub_string = xstrndup(status_string, len); state_sub_num = search_name_hashtable(state_sub_string); free(state_sub_string); return(state_sub_num); }
static struct remote *make_remote(const char *name, int len) { struct remote *ret; int i; for (i = 0; i < remotes_nr; i++) { if (len ? (!strncmp(name, remotes[i]->name, len) && !remotes[i]->name[len]) : !strcmp(name, remotes[i]->name)) return remotes[i]; } ret = xcalloc(1, sizeof(struct remote)); ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc); remotes[remotes_nr++] = ret; if (len) ret->name = xstrndup(name, len); else ret->name = xstrdup(name); return ret; }
/* Same as statusline_addstr(), but hilight "<str>" sequences if the terminal * supports it */ static void statusline_addhlstr(const char *str) { #if defined(A_BOLD) && defined(A_NORMAL) && defined(A_DIM) const char *p = str, *start = str; char *tmp; int pos = 0; while(1) { if(!*p || strchr("<>", *p)) { if(p - start > 0) { wattrset(bottom, (*p == '>') ? A_BOLD : A_NORMAL); tmp = xstrndup(start, p - start); mvwaddstr(bottom, 1, pos, tmp); pos += strwidth(tmp); free(tmp); } if(*p) { start = p + 1; /* show tag markers */ wattrset(bottom, A_DIM); mvwaddch(bottom, 1, pos++, *p); } } if(!*p) { wattrset(bottom, A_NORMAL); break; } p++; } #else mvwaddstr(bottom, 1, 0, str); #endif refresh(); wrefresh(bottom); }
/* "save headers" callback */ static size_t save_headers(void *buffer_pv, size_t count, size_t nmemb, void *ptr) { abrt_post_state_t* state = (abrt_post_state_t*)ptr; size_t size = count * nmemb; char *h = xstrndup((char*)buffer_pv, size); strchrnul(h, '\r')[0] = '\0'; strchrnul(h, '\n')[0] = '\0'; unsigned cnt = state->header_cnt; /* Check for the case when curl follows a redirect: * header 0: 'HTTP/1.1 301 Moved Permanently' * header 1: 'Connection: close' * header 2: 'Location: NEW_URL' * header 3: '' * header 0: 'HTTP/1.1 200 OK' <-- we need to forget all hdrs and start anew */ if (cnt != 0 && strncmp(h, "HTTP/", 5) == 0 && state->headers[cnt-1][0] == '\0' /* prev header is an empty string */ ) { char **headers = state->headers; if (headers) { while (*headers) free(*headers++); } cnt = 0; } VERB3 log("save_headers: header %d: '%s'", cnt, h); state->headers = (char**)xrealloc(state->headers, (cnt+2) * sizeof(state->headers[0])); state->headers[cnt] = h; state->header_cnt = ++cnt; state->headers[cnt] = NULL; return size; }
/* list the scripts user has available */ int listscripts(struct protstream *conn) { DIR *dp; struct dirent *dir; size_t length; /* open the directory */ dp=opendir("."); if (dp==NULL) { prot_printf(conn,"NO \"Error opening directory\"\r\n"); return TIMSIEVE_FAIL; } while ((dir=readdir(dp)) != NULL) /* while there are files here */ { length=strlen(dir->d_name); if (length >= strlen(".script")) /* if ends in .script */ { if (strcmp(dir->d_name + (length - 7), ".script")==0) { char *namewo = xstrndup(dir->d_name, length-7); if (isactive(namewo)) prot_printf(conn,"\"%s\" ACTIVE\r\n", namewo); else prot_printf(conn,"\"%s\"\r\n", namewo); free(namewo); } } } closedir(dp); prot_printf(conn,"OK\r\n"); return TIMSIEVE_OK; }
/*! \brief PASS command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = password * - parv[2] = optional extra version information * - parv[3] = TS protocol version * - parv[4] = server ID (SID) */ static int mr_pass(struct Client *source_p, int parc, char *parv[]) { assert(MyConnect(source_p)); if (EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "PASS"); return 0; } MyFree(source_p->connection->password); source_p->connection->password = xstrndup(parv[1], IRCD_MIN(strlen(parv[1]), PASSWDLEN)); if (parc > 2) { /* * It looks to me as if orabidoo wanted to have more * than one set of option strings possible here... * i.e. ":AABBTS" as long as TS was the last two chars * however, as we are now using CAPAB, I think we can * safely assume if there is a ":TS" then it's a TS server * -Dianora */ if (!irccmp(parv[2], "TS") && source_p->tsinfo == 0) source_p->tsinfo = TS_DOESTS; } /* Only do this stuff if we are doing ts6 */ if (parc > 4) { if (atoi(parv[3]) >= 6 && valid_sid(parv[4])) { strlcpy(source_p->id, parv[4], sizeof(source_p->id)); SetCapable(source_p, CAP_TS6); } } return 0; }
void select_match(const char *expr) { const char *ptr; union arg *args; int rc, operator; char buffer[128]; for(ptr = expr; *ptr && *ptr != '=' && *ptr != '~' && *ptr != '<' && *ptr != '>' && *ptr != '!'; ++ptr) ; if(!*ptr) fatal(0, "invalid match expression '%s'", expr); args = xmalloc(3 * sizeof *args); args[0].string = xstrndup(expr, ptr - expr); ptr = get_operator(ptr, &operator); if(!ptr) fatal(0, "%s: unrecognized match operator\n", expr); if(*ptr == ':') ++ptr; switch(operator) { case '~': rc = regcomp(&args[1].regex, ptr, REG_ICASE|REG_NOSUB); if(rc) { regerror(rc, &args[1].regex, buffer, sizeof buffer); fatal(0, "regexec: %s", buffer); } select_add(select_regex_match, args, 2); break; case IDENTICAL: args[1].string = xstrdup(ptr); select_add(select_string_match, args, 2); break; default: args[1].operator = operator; args[2].string = xstrdup(ptr); select_add(select_compare, args, 3); break; } }
static int do_onequota(void *rock, const char *key, size_t keylen, const char *data, size_t datalen) { int r = 0; struct quota quota; struct quota_foreach_t *fd = (struct quota_foreach_t *)rock; char *root = xstrndup(key, keylen); int iswrite = fd->tid ? 1 : 0; quota_init("a, root); /* XXX - error if not parsable? */ if (datalen && !quota_parseval(data, datalen, "a, iswrite)) { r = fd->proc("a, fd->rock); } quota_free("a); free(root); return r; }
/* * m_pass() - Added Sat, 4 March 1989 * * * mr_pass - PASS message handler * parv[0] = sender prefix * parv[1] = password * parv[2] = optional extra version information */ static void mr_pass(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { assert(client_p == source_p); if (EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name[0] ? source_p->name : "*", "PASS"); return; } MyFree(source_p->localClient->passwd); source_p->localClient->passwd = xstrndup(parv[1], IRCD_MIN(strlen(parv[1]), PASSWDLEN)); if (parc > 2) { /* It looks to me as if orabidoo wanted to have more * than one set of option strings possible here... * i.e. ":AABBTS" as long as TS was the last two chars * however, as we are now using CAPAB, I think we can * safely assume if there is a ":TS" then its a TS server * -Dianora */ if (!irccmp(parv[2], "TS") && source_p->tsinfo == 0) source_p->tsinfo = TS_DOESTS; } /* only do this stuff if we are doing ts6 */ if (parc > 4) { if (atoi(parv[3]) >= 6 && valid_sid(parv[4])) { strlcpy(source_p->id, parv[4], sizeof(source_p->id)); SetCapable(source_p, CAP_TS6); } } }
/* * If path ends with suffix (complete path components), returns the * part before suffix (sans trailing directory separators). * Otherwise returns NULL. */ char *strip_path_suffix(const char *path, const char *suffix) { int path_len = strlen(path), suffix_len = strlen(suffix); while (suffix_len) { if (!path_len) return NULL; if (is_dir_sep(path[path_len - 1])) { if (!is_dir_sep(suffix[suffix_len - 1])) return NULL; path_len = chomp_trailing_dir_sep(path, path_len); suffix_len = chomp_trailing_dir_sep(suffix, suffix_len); } else if (path[--path_len] != suffix[--suffix_len]) return NULL; } if (path_len && !is_dir_sep(path[path_len - 1])) return NULL; return xstrndup(path, chomp_trailing_dir_sep(path, path_len)); }
/* * Process the data that server sent due to IMAP STATUS client request. */ int response_status(session *ssn, int tag, unsigned int *exist, unsigned int *recent, unsigned int *unseen, unsigned int *uidnext) { int r; char *s; regexp *re; r = response_generic(ssn, tag); if (r == -1 || r == STATUS_BYE) return r; re = &responses[RESPONSE_STATUS]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[RESPONSE_STATUS_MESSAGES]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *exist = strtol(s + re->pmatch[1].rm_so, NULL, 10); re = &responses[RESPONSE_STATUS_RECENT]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *recent = strtol(s + re->pmatch[1].rm_so, NULL, 10); re = &responses[RESPONSE_STATUS_UNSEEN]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *unseen = strtol(s + re->pmatch[1].rm_so, NULL, 10); re = &responses[RESPONSE_STATUS_UIDNEXT]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *uidnext = strtol(s + re->pmatch[1].rm_so, NULL, 10); xfree(s); } return r; }
/* Grab a filename. Whitespace at start is skipped, then goes to EOL. */ static int parse_file_cmd(/*sed_cmd_t *sed_cmd,*/ const char *filecmdstr, char **retval) { int start = 0, idx, hack = 0; /* Skip whitespace, then grab filename to end of line */ while (isspace(filecmdstr[start])) start++; idx = start; while (filecmdstr[idx] && filecmdstr[idx] != '\n') idx++; /* If lines glued together, put backslash back. */ if (filecmdstr[idx] == '\n') hack = 1; if (idx == start) bb_error_msg_and_die("empty filename"); *retval = xstrndup(filecmdstr+start, idx-start+hack+1); if (hack) (*retval)[idx] = '\\'; return idx; }
static int xmlParseTag(void* Pool,PXMLNode x,PXMLNode* p,pchar src,int i) { int st,j,q; for(;;) { i=xmlSkipSpace(src,i);CHK; if(src[i]=='/') { if(src[i+1]!='>')return 0; x->eType=xmlEmpty; return i+2; } if(src[i]=='>') { *p=x; return i+1; } st=i; i=xmlGetWordEnd(src,i);CHK; if(src[i]!='=')return 0; if(src[i+1]!='"' && src[i+1]!='\'')return 0; q=src[i+1]; src[i]=0; i+=2; j=i; i=xmlSkipTill(src,i,(xchar)q); if(i==-1) { src[j-2]='='; return 0; } if(x->tAttrs==NULL)x->tAttrs=tableNew(Pool,TABLE_FLAG_ALLOCNAME); tableAdd(x->tAttrs,src+st,xmlSubst(xstrndup(Pool,src+j,i-j))); src[j-2]='='; i++; } // return i; }
/* * extract_version tries to find the kernel version in given data */ static char *extract_version(const char *linepointer) { if (strstr(linepointer, "Pid") || strstr(linepointer, "comm") || strstr(linepointer, "CPU") || strstr(linepointer, "REGS") || strstr(linepointer, "EFLAGS") ) { char* start; char* end; start = strstr((char*)linepointer, "2.6."); if (start) { end = strchr(start, ')'); if (!end) end = strchrnul(start, ' '); return xstrndup(start, end-start); } } return NULL; }
static StringParseResult ParseToken(const char *expr, int start, int end) { int endlit = start; while (endlit < end && ValidTokenCharacter(expr[endlit])) { endlit++; } if (endlit > start) { StringExpression *ret = xcalloc(1, sizeof(StringExpression)); ret->op = LITERAL; ret->val.literal.literal = xstrndup(expr + start, endlit - start); return (StringParseResult) {ret, endlit}; } else { return (StringParseResult) {NULL, endlit}; } }
/* Record a file prefix mapping in the specified map. ARG is the argument to -f*-prefix-map and must be of the form OLD=NEW. OPT is the option name for diagnostics. */ static void add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt) { file_prefix_map *map; const char *p; /* Note: looking for the last '='. The thinking is we can control the paths inside our projects but not where the users build them. */ p = strrchr (arg, '='); if (!p) { error ("invalid argument %qs to %qs", arg, opt); return; } map = XNEW (file_prefix_map); map->old_prefix = xstrndup (arg, p - arg); map->old_len = p - arg; p++; map->new_prefix = xstrdup (p); map->new_len = strlen (p); map->next = maps; maps = map; }
static char * fix_notes(const char *name, char *notes) { char *cleft, *cright, *cback, *ctmp; if ((! name) || (! notes)) return notes; /* do we have a BACKSLASH in shortname ? */ cback = strchr(name, '\\'); if ((! cback) || (cback == name)) return notes; /* do we have left, but no right parenthesis in notes ? */ if (! (cleft = strchr(notes, '('))) return notes; cright = strchr(notes, ')'); if (cright && (cright > cleft)) return notes; /* now contruct the new name */ ctmp = lrtrim(xstrndup(notes, cleft - notes)); xfree(notes); xasprintf(¬es, "%s (%*.*s)", ctmp, cback - name, cback - name, name); xfree(ctmp); return notes; }
/// This differs from the non-unique version in that we expect the filename /// to be something like a pattern for mkstemp(), so the resulting path can /// reside in a system-wide directory with no risk of a conflict. static char * resolve_relative_runtime_unique_filename (const char *filename) { struct str path; str_init (&path); const char *runtime_dir = getenv ("XDG_RUNTIME_DIR"); if (runtime_dir && *runtime_dir == '/') str_append (&path, runtime_dir); else str_append (&path, "/tmp"); str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename); // Try to create the file's ancestors; // typically the user will want to immediately create a file in there const char *last_slash = strrchr (path.str, '/'); if (last_slash && last_slash != path.str) { char *copy = xstrndup (path.str, last_slash - path.str); (void) mkdir_with_parents (copy, NULL); free (copy); } return str_steal (&path); }
/* Test 'buffer' to see if it contains a .so include. If so and it's not an * absolute filename, return newly allocated string whose contents are the * include. */ static char *test_for_include (const char *buffer) { if (!buffer) return NULL; /* strip out any leading whitespace (if any) */ while (CTYPE (isspace, *buffer)) buffer++; /* see if the `command' is a .so */ if (strncmp (buffer, ".so", 3) == 0) { buffer += 3; /* strip out any whitespace between the command and it's argumant */ while (CTYPE (isspace, *buffer)) buffer++; /* If .so's argument is an absolute filename, it could be * either (i) a macro inclusion, (ii) a non local manual page * or (iii) a (somewhat bogus) reference to a local manual * page. * * If (i) or (ii), we must not follow the reference. (iii) is * a problem with the manual page, thus we don't want to * follow any absolute inclusions in our quest for the * ultimate source file */ if (*buffer != '/') { const char *end = buffer; while (*end && !CTYPE (isspace, *end)) ++end; return xstrndup (buffer, end - buffer); } } return NULL; }
void process_options(int argc, char *argv[]) { int opt; opterr = 0; while (-1 != (opt = getopt(argc, argv, "D:Gcdh"))) { switch (opt) { case 'D': DefaultDomain = xstrndup(optarg, DNLEN + 1); strlwr(DefaultDomain); break; case 'G': use_global = 1; break; case 'c': use_case_insensitive_compare = 1; break; case 'd': debug_enabled = 1; break; case 'h': usage(argv[0]); exit(0); case '?': opt = optopt; /* fall thru to default */ default: fprintf(stderr, "%s Unknown option: -%c. Exiting\n", myname, opt); usage(argv[0]); exit(1); break; /* not reached */ } } return; }
static file_header_t *get_header_tar(struct gzip_handle *tar_stream) { union { unsigned char raw[512]; struct { char name[100]; /* 0-99 */ char mode[8]; /* 100-107 */ char uid[8]; /* 108-115 */ char gid[8]; /* 116-123 */ char size[12]; /* 124-135 */ char mtime[12]; /* 136-147 */ char chksum[8]; /* 148-155 */ char typeflag; /* 156-156 */ char linkname[100]; /* 157-256 */ char magic[6]; /* 257-262 */ char version[2]; /* 263-264 */ char uname[32]; /* 265-296 */ char gname[32]; /* 297-328 */ char devmajor[8]; /* 329-336 */ char devminor[8]; /* 337-344 */ char prefix[155]; /* 345-499 */ char padding[12]; /* 500-512 */ } formated; } tar; file_header_t *tar_entry = NULL; long i; long sum = 0; if (archive_offset % 512 != 0) { seek_forward(tar_stream, 512 - (archive_offset % 512)); } if (gzip_read(tar_stream, tar.raw, 512) != 512) { /* Unfortunately its common for tar files to have all sorts of * trailing garbage, fail silently */ // error_msg("Couldnt read header"); return (NULL); } archive_offset += 512; /* Check header has valid magic, unfortunately some tar files * have empty (0'ed) tar entries at the end, which will * cause this to fail, so fail silently for now */ if (strncmp(tar.formated.magic, "ustar", 5) != 0) { #ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY if (strncmp(tar.formated.magic, "\0\0\0\0\0", 5) != 0) #endif return (NULL); } /* Do checksum on headers */ for (i = 0; i < 148; i++) { sum += tar.raw[i]; } sum += ' ' * 8; for (i = 156; i < 512; i++) { sum += tar.raw[i]; } if (sum != strtol(tar.formated.chksum, NULL, 8)) { if (strtol(tar.formated.chksum, NULL, 8) != 0) error_msg("Invalid tar header checksum"); return (NULL); } /* convert to type'ed variables */ tar_entry = xcalloc(1, sizeof(file_header_t)); // tar_entry->name = xstrdup(tar.formated.name); /* parse_mode(tar.formated.mode, &tar_entry->mode); */ tar_entry->mode = 07777 & strtol(tar.formated.mode, NULL, 8); tar_entry->uid = strtol(tar.formated.uid, NULL, 8); tar_entry->gid = strtol(tar.formated.gid, NULL, 8); tar_entry->size = strtol(tar.formated.size, NULL, 8); tar_entry->mtime = strtol(tar.formated.mtime, NULL, 8); tar_entry->device = (strtol(tar.formated.devmajor, NULL, 8) << 8) + strtol(tar.formated.devminor, NULL, 8); /* Fix mode, used by the old format */ switch (tar.formated.typeflag) { /* hard links are detected as regular files with 0 size and a link name */ case '1': tar_entry->mode |= S_IFREG; break; case 0: case '0': #ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY if (last_char_is(tar_entry->name, '/')) { tar_entry->mode |= S_IFDIR; } else #endif tar_entry->mode |= S_IFREG; break; case '2': tar_entry->mode |= S_IFLNK; break; case '3': tar_entry->mode |= S_IFCHR; break; case '4': tar_entry->mode |= S_IFBLK; break; case '5': tar_entry->mode |= S_IFDIR; break; case '6': tar_entry->mode |= S_IFIFO; break; #ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS case 'L':{ longname = xmalloc(tar_entry->size + 1); if (gzip_read(tar_stream, longname, tar_entry->size) != tar_entry->size) return NULL; longname[tar_entry->size] = '\0'; archive_offset += tar_entry->size; return (get_header_tar(tar_stream)); } case 'K':{ linkname = xmalloc(tar_entry->size + 1); if (gzip_read(tar_stream, linkname, tar_entry->size) != tar_entry->size) return NULL; linkname[tar_entry->size] = '\0'; archive_offset += tar_entry->size; return (get_header_tar(tar_stream)); } case 'D': case 'M': case 'N': case 'S': case 'V': perror_msg("Ignoring GNU extension type %c", tar.formated.typeflag); #endif default: perror_msg("Unknown typeflag: 0x%x", tar.formated.typeflag); break; } #ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS if (longname) { tar_entry->name = longname; longname = NULL; } else #endif { tar_entry->name = xstrndup(tar.formated.name, 100); if (tar.formated.prefix[0]) { char *temp = tar_entry->name; char *prefixTemp = xstrndup(tar.formated.prefix, 155); tar_entry->name = concat_path_file(prefixTemp, temp); free(temp); free(prefixTemp); } } if (linkname) { tar_entry->link_name = linkname; linkname = NULL; } else { tar_entry->link_name = *tar.formated.linkname != '\0' ? xstrndup(tar.formated.linkname, 100) : NULL; } return (tar_entry); }
char *xstrdup(const char *s) { return xstrndup(s, strlen(s)); }
/* * We cannot decide in this function whether we are in the work tree or * not, since the config can only be read _after_ this function was called. */ const char *setup_git_directory_gently(int *nongit_ok) { const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT); const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT); static char cwd[PATH_MAX+1]; const char *gitdirenv; const char *gitfile_dir; int len, offset, ceil_offset; /* * Let's assume that we are in a git repository. * If it turns out later that we are somewhere else, the value will be * updated accordingly. */ if (nongit_ok) *nongit_ok = 0; /* * If GIT_DIR is set explicitly, we're not going * to do any discovery, but we still do repository * validation. */ gitdirenv = getenv(GIT_DIR_ENVIRONMENT); if (gitdirenv) { if (PATH_MAX - 40 < strlen(gitdirenv)) die("'$%s' too big", GIT_DIR_ENVIRONMENT); if (is_git_directory(gitdirenv)) { static char buffer[1024 + 1]; const char *retval; if (!work_tree_env) { retval = set_work_tree(gitdirenv); /* config may override worktree */ if (check_repository_format_gently(nongit_ok)) return NULL; return retval; } if (check_repository_format_gently(nongit_ok)) return NULL; retval = get_relative_cwd(buffer, sizeof(buffer) - 1, get_git_work_tree()); if (!retval || !*retval) return NULL; set_git_dir(make_absolute_path(gitdirenv)); if (chdir(work_tree_env) < 0) die_errno ("Could not chdir to '%s'", work_tree_env); strcat(buffer, "/"); return retval; } if (nongit_ok) { *nongit_ok = 1; return NULL; } die("Not a git repository: '%s'", gitdirenv); } if (!getcwd(cwd, sizeof(cwd)-1)) die_errno("Unable to read current working directory"); ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs); if (ceil_offset < 0 && has_dos_drive_prefix(cwd)) ceil_offset = 1; /* * Test in the following order (relative to the cwd): * - .git (file containing "gitdir: <path>") * - .git/ * - ./ (bare) * - ../.git * - ../.git/ * - ../ (bare) * - ../../.git/ * etc. */ offset = len = strlen(cwd); for (;;) { gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT); if (gitfile_dir) { if (set_git_dir(gitfile_dir)) die("Repository setup failed"); break; } if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) break; if (is_git_directory(".")) { inside_git_dir = 1; if (!work_tree_env) inside_work_tree = 0; if (offset != len) { cwd[offset] = '\0'; setenv(GIT_DIR_ENVIRONMENT, cwd, 1); } else setenv(GIT_DIR_ENVIRONMENT, ".", 1); check_repository_format_gently(nongit_ok); return NULL; } while (--offset > ceil_offset && cwd[offset] != '/'); if (offset <= ceil_offset) { if (nongit_ok) { if (chdir(cwd)) die_errno("Cannot come back to cwd"); *nongit_ok = 1; return NULL; } die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT); } if (chdir("..")) die_errno("Cannot change to '%s/..'", cwd); } inside_git_dir = 0; if (!work_tree_env) inside_work_tree = 1; git_work_tree_cfg = xstrndup(cwd, offset); if (check_repository_format_gently(nongit_ok)) return NULL; if (offset == len) return NULL; /* Make "offset" point to past the '/', and add a '/' at the end */ offset++; cwd[len++] = '/'; cwd[len] = 0; return cwd + offset; }