X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fcreate.c;h=450da32d1f90013b893151d5457a588548255989;hb=4732e8a4daa502ac15bd811fef84473deb3d516e;hp=c6d78b280e9399f45881a8ac93e4230c62670b93;hpb=36682e50ccd859bb82bff444c4c68ff587966dc8;p=chaz%2Ftar diff --git a/src/create.c b/src/create.c index c6d78b2..450da32 100644 --- a/src/create.c +++ b/src/create.c @@ -53,7 +53,7 @@ struct link char name[1]; }; -struct link *linklist = NULL; /* points to first link in list */ +static struct link *linklist; /* points to first link in list */ /* Base 64 digits; see Internet RFC 2045 Table 1. */ char const base_64_digits[64] = @@ -114,25 +114,38 @@ to_chars (int negative, uintmax_t value, size_t valsize, { uintmax_t v = negative ? -value : value; + /* Generate the POSIX octal representation if the number fits. */ if (! negative && v <= MAX_VAL_WITH_DIGITS (size - 1, LG_8)) { where[size - 1] = '\0'; to_base (v, LG_8, base_8_digits, where, size - 1); } + + /* Otherwise, generate the GNU base-64 representation if we are + generating an old or new GNU format and if the number fits. */ else if (v <= MAX_VAL_WITH_DIGITS (size - 1, LG_64) - && archive_format == GNU_FORMAT) + && (archive_format == GNU_FORMAT + || archive_format == OLDGNU_FORMAT)) { where[0] = negative ? '-' : '+'; to_base (v, LG_64, base_64_digits, where + 1, size - 1); } - else if (negative - && archive_format != GNU_FORMAT - && valsize * CHAR_BIT <= (size - 1) * LG_8) + + /* Otherwise, if the number is negative, and if it would not cause + ambiguity on this host by confusing positive with negative + values, then generate the POSIX octal representation of the value + modulo 2**(field bits). The resulting tar file is + machine-dependent, since it depends on the host word size. Yuck! + But this is the traditional behavior. */ + else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8) { where[size - 1] = '\0'; to_base (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1), LG_8, base_8_digits, where, size - 1); } + + /* Otherwise, output a substitute value if possible (with a + warning), and an error message if not. */ else { uintmax_t maxval = (archive_format == GNU_FORMAT @@ -157,14 +170,14 @@ to_chars (int negative, uintmax_t value, size_t valsize, char *sub_string = STRINGIFY_BIGINT (s, buf3 + 1); if (negsub) *--sub_string = '-'; - WARN ((0, 0, _("%s value %s out of range %s..%s; substituting %s"), - type, value_string, minval_string, maxval_string, + WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"), + value_string, type, minval_string, maxval_string, sub_string)); - to_chars (negsub, s, valsize, NULL, where, size, type); + to_chars (negsub, s, valsize, 0, where, size, type); } else - ERROR ((0, 0, _("%s value %s out of range %s..%s"), - type, value_string, minval_string, maxval_string)); + ERROR ((0, 0, _("value %s out of %s range %s..%s"), + value_string, type, minval_string, maxval_string)); } } @@ -193,13 +206,13 @@ gid_to_chars (gid_t v, char *p, size_t s) void major_to_chars (major_t v, char *p, size_t s) { - to_chars (v < 0, (uintmax_t) v, sizeof v, NULL, p, s, "major_t"); + to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t"); } void minor_to_chars (minor_t v, char *p, size_t s) { - to_chars (v < 0, (uintmax_t) v, sizeof v, NULL, p, s, "minor_t"); + to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t"); } void @@ -235,25 +248,25 @@ mode_to_chars (mode_t v, char *p, size_t s) | (v & S_IWOTH ? TOWRITE : 0) | (v & S_IXOTH ? TOEXEC : 0)); } - to_chars (negative, u, sizeof v, NULL, p, s, "mode_t"); + to_chars (negative, u, sizeof v, 0, p, s, "mode_t"); } void off_to_chars (off_t v, char *p, size_t s) { - to_chars (v < 0, (uintmax_t) v, sizeof v, NULL, p, s, "off_t"); + to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t"); } void size_to_chars (size_t v, char *p, size_t s) { - to_chars (0, (uintmax_t) v, sizeof v, NULL, p, s, "size_t"); + to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t"); } void time_to_chars (time_t v, char *p, size_t s) { - to_chars (v < 0, (uintmax_t) v, sizeof v, NULL, p, s, "time_t"); + to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t"); } static uintmax_t @@ -281,7 +294,7 @@ uid_to_chars (uid_t v, char *p, size_t s) void uintmax_to_chars (uintmax_t v, char *p, size_t s) { - to_chars (0, v, sizeof v, NULL, p, s, "uintmax_t"); + to_chars (0, v, sizeof v, 0, p, s, "uintmax_t"); } /* Writing routines. */ @@ -298,7 +311,7 @@ clear_buffer (char *buffer) } /*-------------------------------------------------------------------------. -| Write the EOT block(s). We actually zero at least one block, through | +| Write the EOT block(s). We zero at least two blocks, through | | the end of the record. Old tar, as previous versions of GNU tar, writes | | garbage after two zeroed blocks. | `-------------------------------------------------------------------------*/ @@ -307,14 +320,11 @@ void write_eot (void) { union block *pointer = find_next_block (); - - if (pointer) - { - size_t space = available_space_after (pointer); - - memset (pointer->buffer, 0, space); - set_next_block_after (pointer); - } + memset (pointer->buffer, 0, BLOCKSIZE); + set_next_block_after (pointer); + pointer = find_next_block (); + memset (pointer->buffer, 0, available_space_after (pointer)); + set_next_block_after (pointer); } /*-----------------------------------------------------. @@ -362,7 +372,7 @@ write_long (const char *p, char type) /*---------------------------------------------------------------------. | Make a header block for the file name whose stat info is st. Return | -| header pointer for success, NULL if the name is too long. | +| header pointer for success, zero if the name is too long. | `---------------------------------------------------------------------*/ static union block * @@ -372,34 +382,35 @@ start_header (const char *name, struct stat *st) if (!absolute_names_option) { - static int warned_once = 0; size_t prefix_len = FILESYSTEM_PREFIX_LEN (name); if (prefix_len) { - name += prefix_len; + static int warned_once; if (!warned_once) { warned_once = 1; - WARN ((0, 0, _("Removing filesystem prefix from names in the archive"))); + WARN ((0, 0, _("Removing `%.*s' prefix from archive names"), + (int) prefix_len, name)); } + name += prefix_len; } while (*name == '/') { - name++; /* force relative path */ + static int warned_once; if (!warned_once) { warned_once = 1; - WARN ((0, 0, _("\ -Removing leading `/' from absolute path names in the archive"))); + WARN ((0, 0, _("Removing leading `/' from archive names"))); } + name++; } } /* Check the file name and put it in the block. */ - if (strlen (name) >= (size_t) NAME_FIELD_SIZE) + if (sizeof header->header.name <= strlen (name)) write_long (name, GNUTYPE_LONGNAME); header = find_next_block (); memset (header->buffer, 0, sizeof (union block)); @@ -506,11 +517,11 @@ finish_header (union block *header) int sum; char *p; - memcpy (header->header.chksum, CHKBLANKS, sizeof (header->header.chksum)); + memcpy (header->header.chksum, CHKBLANKS, sizeof header->header.chksum); sum = 0; p = header->buffer; - for (i = sizeof (*header); i-- != 0; ) + for (i = sizeof *header; i-- != 0; ) /* We can't use unsigned char here because of old compilers, e.g. V7. */ sum += 0xFF & *p++; @@ -573,8 +584,7 @@ init_sparsearray (void) /* Make room for our scratch space -- initially is 10 elts long. */ - sparsearray = (struct sp_array *) - xmalloc (sp_array_size * sizeof (struct sp_array)); + sparsearray = xmalloc (sp_array_size * sizeof (struct sp_array)); for (counter = 0; counter < sp_array_size; counter++) { sparsearray[counter].offset = 0; @@ -638,8 +648,7 @@ deal_with_sparse (char *name, union block *header) if (sparse_index > sp_array_size - 1) { - - sparsearray = (struct sp_array *) + sparsearray = xrealloc (sparsearray, 2 * sp_array_size * sizeof (struct sp_array)); sp_array_size *= 2; @@ -765,8 +774,8 @@ finish_sparse_file (int file, off_t *sizeleft, off_t fullsize, char *name) if (count < 0) { char buf[UINTMAX_STRSIZE_BOUND]; - ERROR ((0, errno, _("\ -Read error at byte %s, reading %lu bytes, in file %s"), + ERROR ((0, errno, + _("Read error at byte %s, reading %lu bytes, in file %s"), STRINGIFY_BIGINT (fullsize - *sizeleft, buf), (unsigned long) bufsize, name)); return 1; @@ -851,22 +860,21 @@ create_archive (void) blank_name_list (); while (p = name_from_list (), p) - { - strcpy (buffer, p); - if (p[strlen (p) - 1] != '/') - strcat (buffer, "/"); - bufp = buffer + strlen (buffer); - for (q = gnu_list_name->dir_contents; - q && *q; - q += strlen (q) + 1) - { - if (*q == 'Y') - { - strcpy (bufp, q + 1); - dump_file (buffer, (dev_t) -1, 1); - } - } - } + if (!excluded_name (p)) + { + strcpy (buffer, p); + if (p[strlen (p) - 1] != '/') + strcat (buffer, "/"); + bufp = buffer + strlen (buffer); + q = gnu_list_name->dir_contents; + if (q) + for (; *q; q += strlen (q) + 1) + if (*q == 'Y') + { + strcpy (bufp, q + 1); + dump_file (buffer, (dev_t) -1, 1); + } + } free (buffer); } else @@ -935,7 +943,7 @@ dump_file (char *p, dev_t parent_device, int top_level) #ifdef S_ISHIDDEN if (S_ISHIDDEN (current_stat.st_mode)) { - char *new = (char *) alloca (strlen (p) + 2); + char *new = alloca (strlen (p) + 2); if (new) { strcpy (new, p); @@ -945,14 +953,15 @@ dump_file (char *p, dev_t parent_device, int top_level) } #endif - /* See if we only want new files, and check if this one is too old to + /* See if we want only new files, and check if this one is too old to put in the archive. */ - if (!incremental_option && !S_ISDIR (current_stat.st_mode) + if ((!incremental_option || listed_incremental_option) + && !S_ISDIR (current_stat.st_mode) && current_stat.st_mtime < newer_mtime_option && (!after_date_option || current_stat.st_ctime < newer_ctime_option)) { - if (parent_device == (dev_t) -1) + if (!listed_incremental_option && parent_device == (dev_t) -1) WARN ((0, 0, _("%s: is unchanged; not dumped"), p)); /* FIXME: recheck this return. */ return; @@ -994,13 +1003,11 @@ dump_file (char *p, dev_t parent_device, int top_level) while (!absolute_names_option && *link_name == '/') { - static int warned_once = 0; - + static int warned_once; if (!warned_once) { warned_once = 1; - WARN ((0, 0, _("\ -Removing leading `/' from absolute links"))); + WARN ((0, 0, _("Removing leading `/' from link names"))); } link_name++; } @@ -1010,7 +1017,7 @@ Removing leading `/' from absolute links"))); current_stat.st_size = 0; header = start_header (p, ¤t_stat); - if (header == NULL) + if (! header) { exit_status = TAREXIT_FAILURE; return; @@ -1037,8 +1044,7 @@ Removing leading `/' from absolute links"))); /* Not found. Add it to the list of possible links. */ - lp = (struct link *) - xmalloc ((size_t) (sizeof (struct link) + strlen (p))); + lp = xmalloc (sizeof (struct link) + strlen (p)); lp->ino = current_stat.st_ino; lp->dev = current_stat.st_dev; strcpy (lp->name, p); @@ -1059,9 +1065,6 @@ Removing leading `/' from absolute links"))); int header_moved; char isextended = 0; int upperbound; -#if 0 - static int cried_once = 0; -#endif header_moved = 0; @@ -1106,7 +1109,7 @@ Removing leading `/' from absolute links"))); int counter; header = start_header (p, ¤t_stat); - if (header == NULL) + if (! header) { exit_status = TAREXIT_FAILURE; return; @@ -1184,7 +1187,7 @@ Removing leading `/' from absolute links"))); if (!header_moved) { header = start_header (p, ¤t_stat); - if (header == NULL) + if (! header) { if (f >= 0) close (f); @@ -1215,8 +1218,7 @@ Removing leading `/' from absolute links"))); extend: exhdr = find_next_block (); - - if (exhdr == NULL) + if (! exhdr) { exit_status = TAREXIT_FAILURE; return; @@ -1272,8 +1274,7 @@ Removing leading `/' from absolute links"))); bufsize = sizeleft; count = bufsize % BLOCKSIZE; if (count) - memset (start->buffer + sizeleft, 0, - (size_t) (BLOCKSIZE - count)); + memset (start->buffer + sizeleft, 0, BLOCKSIZE - count); } if (f < 0) count = bufsize; @@ -1282,8 +1283,8 @@ Removing leading `/' from absolute links"))); if (count < 0) { char buf[UINTMAX_STRSIZE_BOUND]; - ERROR ((0, errno, _("\ -Read error at byte %s, reading %lu bytes, in file %s"), + ERROR ((0, errno, + _("Read error at byte %s, reading %lu bytes, in file %s"), STRINGIFY_BIGINT (current_stat.st_size - sizeleft, buf), (unsigned long) bufsize, p)); @@ -1308,7 +1309,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), } if (multi_volume_option) - assign_string (&save_name, NULL); + assign_string (&save_name, 0); if (f >= 0) { @@ -1343,7 +1344,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), sizeleft -= BLOCKSIZE; } if (multi_volume_option) - assign_string (&save_name, NULL); + assign_string (&save_name, 0); if (f >= 0) { close (f); @@ -1357,7 +1358,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), else if (S_ISLNK (current_stat.st_mode)) { int size; - char *buffer = (char *) alloca (PATH_MAX + 1); + char *buffer = alloca (PATH_MAX + 1); size = readlink (p, buffer, PATH_MAX + 1); if (size < 0) @@ -1374,7 +1375,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), current_stat.st_size = 0; /* force 0 size on symlink */ header = start_header (p, ¤t_stat); - if (header == NULL) + if (! header) { exit_status = TAREXIT_FAILURE; return; @@ -1451,7 +1452,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), files, we'd better put the / on the name. */ header = start_header (namebuf, ¤t_stat); - if (header == NULL) + if (! header) { exit_status = TAREXIT_FAILURE; return; /* eg name too long */ @@ -1507,8 +1508,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), bufsize = sizeleft; count = bufsize % BLOCKSIZE; if (count) - memset (start->buffer + sizeleft, 0, - (size_t) (BLOCKSIZE - count)); + memset (start->buffer + sizeleft, 0, BLOCKSIZE - count); } memcpy (start->buffer, p_buffer, bufsize); sizeleft -= bufsize; @@ -1516,7 +1516,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), set_next_block_after (start + (bufsize - 1) / BLOCKSIZE); } if (multi_volume_option) - assign_string (&save_name, NULL); + assign_string (&save_name, 0); if (atime_preserve_option) utime (p, &restore_times); return; @@ -1550,11 +1550,6 @@ Read error at byte %s, reading %lu bytes, in file %s"), return; } - /* Hack to remove "./" from the front of all the file names. */ - - if (len == 2 && namebuf[0] == '.' && namebuf[1] == '/') - len = 0; - /* FIXME: Should speed this up by cd-ing into the dir. */ while (entry = readdir (directory), entry) @@ -1567,7 +1562,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), if ((int) NAMLEN (entry) + len >= buflen) { buflen = len + NAMLEN (entry); - namebuf = (char *) xrealloc (namebuf, buflen + 1); + namebuf = xrealloc (namebuf, buflen + 1); #if 0 namebuf[len] = '\0'; ERROR ((0, 0, _("File name %s%s too long"), @@ -1602,7 +1597,7 @@ Read error at byte %s, reading %lu bytes, in file %s"), current_stat.st_size = 0; /* force 0 size */ header = start_header (p, ¤t_stat); - if (header == NULL) + if (! header) { exit_status = TAREXIT_FAILURE; return; /* eg name too long */