From: Paul Eggert Date: Sat, 13 Jan 2001 05:59:29 +0000 (+0000) Subject: (relativize): New function. X-Git-Url: https://git.dogcows.com/gitweb?a=commitdiff_plain;h=a6d27a4aa40c4e9abef94627c772fa7869910a9d;p=chaz%2Ftar (relativize): New function. > (relativize): New function, with much of old start_header's guts. Handle filesystem prefixes. (start_header): Use this new function. (init_sparsearray): Don't bother to zero out the new array; it's not needed. (deal_with_sparse): Fix array allocation bug. (create_archive): Don't assume '/' is the only separator. (dump_file): Likewise. Don't worry about leading / in symlink targets. --- diff --git a/src/create.c b/src/create.c index 2a54665..98b1639 100644 --- a/src/create.c +++ b/src/create.c @@ -1,5 +1,5 @@ /* Create a tar archive. - Copyright 1985, 92, 93, 94, 96, 97, 99, 2000 Free Software Foundation, Inc. + Copyright 1985,92,93,94,96,97,99,2000, 2001 Free Software Foundation, Inc. Written by John Gilmore, on 1985-08-25. This program is free software; you can redistribute it and/or modify it @@ -390,43 +390,14 @@ write_long (const char *p, char type) set_next_block_after (header + (size - 1) / BLOCKSIZE); } -/* Header handling. */ - -/* Make a header block for the file whose stat info is st, - and return its address. */ - -static union block * -start_header (const char *name, struct stat *st) +/* Return a suffix of the file NAME that is a relative file name. + Warn about `..' in file names. But return NAME if the user wants + absolute file names. */ +static char const * +relativize (char const *name) { - union block *header; - - if (!absolute_names_option) + if (! absolute_names_option) { - size_t prefix_len = FILESYSTEM_PREFIX_LEN (name); - - if (prefix_len) - { - static int warned_once; - if (!warned_once) - { - warned_once = 1; - WARN ((0, 0, _("Removing leading `%.*s' from member names"), - (int) prefix_len, name)); - } - name += prefix_len; - } - - while (*name == '/') - { - static int warned_once; - if (!warned_once) - { - warned_once = 1; - WARN ((0, 0, _("Removing leading `/' from member names"))); - } - name++; - } - { static int warned_once; if (! warned_once && contains_dot_dot (name)) @@ -435,8 +406,42 @@ start_header (const char *name, struct stat *st) WARN ((0, 0, _("Member names contain `..'"))); } } + + { + size_t prefix_len = FILESYSTEM_PREFIX_LEN (name); + + while (ISSLASH (name[prefix_len])) + prefix_len++; + + if (prefix_len) + { + static int warned_once; + if (!warned_once) + { + warned_once = 1; + WARN ((0, 0, _("Removing leading `%.*s' from member names"), + (int) prefix_len, name)); + } + name += prefix_len; + } + } } + return name; +} + +/* Header handling. */ + +/* Make a header block for the file whose stat info is st, + and return its address. */ + +static union block * +start_header (const char *name, struct stat *st) +{ + union block *header; + + name = relativize (name); + if (sizeof header->header.name <= strlen (name)) write_long (name, GNUTYPE_LONGNAME); header = find_next_block (); @@ -595,18 +600,11 @@ zero_block_p (char *buffer) static void init_sparsearray (void) { - int counter; - sp_array_size = 10; /* Make room for our scratch space -- initially is 10 elts long. */ sparsearray = xmalloc (sp_array_size * sizeof (struct sp_array)); - for (counter = 0; counter < sp_array_size; counter++) - { - sparsearray[counter].offset = 0; - sparsearray[counter].numbytes = 0; - } } static off_t @@ -651,7 +649,7 @@ deal_with_sparse (char *name, union block *header) init_sparsearray (); clear_buffer (buffer); - while (0 < (count = safe_read (file, buffer, sizeof buffer))) + for (;;) { /* Realloc the scratch area as necessary. FIXME: should reallocate only at beginning of a new instance of non-zero data. */ @@ -663,6 +661,10 @@ deal_with_sparse (char *name, union block *header) 2 * sp_array_size * sizeof (struct sp_array)); sp_array_size *= 2; } + + count = safe_read (file, buffer, sizeof buffer); + if (count <= 0) + break; /* Process one block. */ @@ -825,7 +827,7 @@ create_archive (void) buffer = xrealloc (buffer, buffer_size); } memcpy (buffer, p, plen); - if (buffer[plen - 1] != '/') + if (! ISSLASH (buffer[plen - 1])) buffer[plen++] = '/'; q = gnu_list_name->dir_contents; if (q) @@ -971,7 +973,7 @@ dump_file (char *p, int top_level, dev_t parent_device) errno = 0; - directory = savedir (p, current_stat.st_size); + directory = savedir (p); if (! directory) { if (ignore_failed_read_option) @@ -987,7 +989,7 @@ dump_file (char *p, int top_level, dev_t parent_device) buflen = len + NAME_FIELD_SIZE; namebuf = xmalloc (buflen + 1); memcpy (namebuf, p, len); - while (len >= 1 && namebuf[len - 1] == '/') + while (len >= 1 && ISSLASH (namebuf[len - 1])) len--; namebuf[len++] = '/'; namebuf[len] = '\0'; @@ -1156,18 +1158,6 @@ dump_file (char *p, int top_level, dev_t parent_device) free (lp); - if (! absolute_names_option) - for (; *link_name == '/'; link_name++) - { - static int warned_once; - if (!warned_once) - { - warned_once = 1; - WARN ((0, 0, - _("Removing leading `/' from link names"))); - } - } - if (NAME_FIELD_SIZE <= strlen (link_name)) write_long (link_name, GNUTYPE_LONGLINK); assign_string (¤t_link_name, link_name);