]> Dogcows Code - chaz/tar/blobdiff - src/create.c
Lint cleanup.
[chaz/tar] / src / create.c
index 0d7e67e0a719cde68a42949e6ba28b4c958e9637..450da32d1f90013b893151d5457a588548255989 100644 (file)
@@ -14,7 +14,7 @@
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "system.h"
 
@@ -53,115 +53,248 @@ 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 */
 \f
-
-/*------------------------------------------------------------------------.
-| Convert VALUE (with substitute SUBSTITUTE if VALUE is out of range)    |
-| into a size-SIZE field at WHERE, including a                           |
-| trailing space.  For example, 3 for SIZE means two digits and a space.  |
-|                                                                         |
-| We assume the trailing NUL is already there and don't fill it in.  This |
-| fact is used by start_header and finish_header, so don't change it!     |
-`------------------------------------------------------------------------*/
-
-/* This should be equivalent to: sprintf (WHERE, "%*lo", SIZE, VALUE);
-   except that we don't assume VALUE fits in an unsigned long, and
-   except that sprintf fills in the trailing NUL and we don't.  */
+/* Base 64 digits; see Internet RFC 2045 Table 1.  */
+char const base_64_digits[64] =
+{
+  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+  'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+  'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+};
+#define base_8_digits (base_64_digits + 26 * 2)
+
+/* The maximum uintmax_t value that can be represented with DIGITS digits,
+   assuming that each digit is BITS_PER_DIGIT wide.  */
+#define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \
+   ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \
+    ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \
+    : (uintmax_t) -1)
+
+/* Convert VALUE to a representation suitable for tar headers,
+   using base 1 << BITS_PER_DIGIT.
+   Use the digits in DIGIT_CHAR[0] ... DIGIT_CHAR[base - 1].
+   Output to buffer WHERE with size SIZE.
+   The result is undefined if SIZE is 0 or if VALUE is too large to fit.  */
 
 static void
-to_oct (uintmax_t value, uintmax_t substitute, char *where, size_t size, const char *type)
+to_base (uintmax_t value, int bits_per_digit, char const *digit_char,
+        char *where, size_t size)
 {
   uintmax_t v = value;
   size_t i = size;
-
-  /* Produce the digits -- at least one.  */
+  unsigned digit_mask = (1 << bits_per_digit) - 1;
 
   do
     {
-      where[--i] = '0' + (int) (v & 7);        /* one octal digit */
-      v >>= 3;
+      where[--i] = digit_char[v & digit_mask];
+      v >>= bits_per_digit;
+    }
+  while (i);
+}
+
+/* NEGATIVE is nonzero if VALUE was negative before being cast to
+   uintmax_t; its original bitpattern can be deduced from VALSIZE, its
+   original size before casting.  Convert VALUE to external form,
+   using SUBSTITUTE (...)  if VALUE won't fit.  Output to buffer WHERE
+   with size SIZE.  TYPE is the kind of value being output (useful for
+   diagnostics).  Prefer the POSIX format of SIZE - 1 octal digits
+   (with leading zero digits), followed by '\0'.  If this won't work,
+   and if GNU format is allowed, use '+' or '-' followed by SIZE - 1
+   base-64 digits.  If neither format works, use SUBSTITUTE (...)
+   instead.  Pass to SUBSTITUTE the address of an 0-or-1 flag
+   recording whether the substitute value is negative.  */
+
+static void
+to_chars (int negative, uintmax_t value, size_t valsize,
+         uintmax_t (*substitute) PARAMS ((int *)),
+         char *where, size_t size, const char *type)
+{
+  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);
     }
-  while (i != 0 && v != 0);
 
-  /* Leading spaces, if necessary.  */
-  while (i != 0)
-    where[--i] = ' ';
+  /* 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 == OLDGNU_FORMAT))
+    {
+      where[0] = negative ? '-' : '+';
+      to_base (v, LG_64, base_64_digits, where + 1, size - 1);
+    }
 
-  if (v != 0)
+  /* 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)
     {
-      int bits = size * 3;
-      uintmax_t maxval = (bits < sizeof (uintmax_t) * CHAR_BIT
-                         ? ((uintmax_t) 1 << bits) - 1
-                         : (uintmax_t) -1);
-      char buf1[UINTMAX_STRSIZE_BOUND];
-      char buf2[UINTMAX_STRSIZE_BOUND];
-      char buf3[UINTMAX_STRSIZE_BOUND];
-      char *value_string = STRINGIFY_BIGINT (value, buf1);
-      char *maxval_string = STRINGIFY_BIGINT (maxval, buf2);
+      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
+                         ? MAX_VAL_WITH_DIGITS (size - 1, LG_64)
+                         : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
+      char buf1[UINTMAX_STRSIZE_BOUND + 1];
+      char buf2[UINTMAX_STRSIZE_BOUND + 1];
+      char buf3[UINTMAX_STRSIZE_BOUND + 1];
+      char *value_string = STRINGIFY_BIGINT (v, buf1 + 1);
+      char *maxval_string = STRINGIFY_BIGINT (maxval, buf2 + 1);
+      char const *minval_string =
+       (archive_format == GNU_FORMAT
+        ? "0"
+        : (maxval_string[-1] = '-', maxval_string - 1));
+      if (negative)
+       *--value_string = '-';
       if (substitute)
        {
-         substitute &= maxval;
-         WARN ((0, 0, _("%s value %s too large (max=%s); substituting %s"),
-                type, value_string, maxval_string,
-                STRINGIFY_BIGINT (substitute, buf3)));
-         to_oct (substitute, (uintmax_t) 0, where, size, type);
+         int negsub;
+         uintmax_t sub = substitute (&negsub) & maxval;
+         uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? -sub : sub;
+         char *sub_string = STRINGIFY_BIGINT (s, buf3 + 1);
+         if (negsub)
+           *--sub_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, 0, where, size, type);
        }
       else
-       ERROR ((0, 0, _("%s value %s too large (max=%s)"),
-               type, value_string, maxval_string));
+       ERROR ((0, 0, _("value %s out of %s range %s..%s"),
+               value_string, type, minval_string, maxval_string));
     }
 }
-#ifndef GID_NOBODY
-#define GID_NOBODY 0
+
+static uintmax_t
+gid_substitute (int *negative)
+{
+  gid_t r;
+#ifdef GID_NOBODY
+  r = GID_NOBODY;
+#else
+  static gid_t gid_nobody;
+  if (!gid_nobody && !gname_to_gid ("nobody", &gid_nobody))
+    gid_nobody = -2;
+  r = gid_nobody;
 #endif
+  *negative = r < 0;
+  return r;
+}
+
 void
-gid_to_oct (gid_t v, char *p, size_t s)
+gid_to_chars (gid_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) GID_NOBODY, p, s, "gid_t");
+  to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
 }
+
 void
-major_to_oct (major_t v, char *p, size_t s)
+major_to_chars (major_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "major_t");
+  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
 }
+
 void
-minor_to_oct (minor_t v, char *p, size_t s)
+minor_to_chars (minor_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "minor_t");
+  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
 }
+
 void
-mode_to_oct (mode_t v, char *p, size_t s)
+mode_to_chars (mode_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "mode_t");
+  /* In the common case where the internal and external mode bits are the same,
+     propagate all unknown bits to the external mode.
+     This matches historical practice.
+     Otherwise, just copy the bits we know about.  */
+  int negative;
+  uintmax_t u;
+  if (S_ISUID == TSUID && S_ISGID == TSGID && S_ISVTX == TSVTX
+      && S_IRUSR == TUREAD && S_IWUSR == TUWRITE && S_IXUSR == TUEXEC
+      && S_IRGRP == TGREAD && S_IWGRP == TGWRITE && S_IXGRP == TGEXEC
+      && S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC)
+    {
+      negative = v < 0;
+      u = v;
+    }
+  else
+    {
+      negative = 0;
+      u = ((v & S_ISUID ? TSUID : 0)
+          | (v & S_ISGID ? TSGID : 0)
+          | (v & S_ISVTX ? TSVTX : 0)
+          | (v & S_IRUSR ? TUREAD : 0)
+          | (v & S_IWUSR ? TUWRITE : 0)
+          | (v & S_IXUSR ? TUEXEC : 0)
+          | (v & S_IRGRP ? TGREAD : 0)
+          | (v & S_IWGRP ? TGWRITE : 0)
+          | (v & S_IXGRP ? TGEXEC : 0)
+          | (v & S_IROTH ? TOREAD : 0)
+          | (v & S_IWOTH ? TOWRITE : 0)
+          | (v & S_IXOTH ? TOEXEC : 0));
+    }
+  to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
 }
+
 void
-off_to_oct (off_t v, char *p, size_t s)
+off_to_chars (off_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "off_t");
+  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
 }
+
 void
-size_to_oct (size_t v, char *p, size_t s)
+size_to_chars (size_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "size_t");
+  to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
 }
+
 void
-time_to_oct (time_t v, char *p, size_t s)
+time_to_chars (time_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "time_t");
+  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
 }
-#ifndef UID_NOBODY
-#define UID_NOBODY 0
+
+static uintmax_t
+uid_substitute (int *negative)
+{
+  uid_t r;
+#ifdef UID_NOBODY
+  r = UID_NOBODY;
+#else
+  static uid_t uid_nobody;
+  if (!uid_nobody && !uname_to_uid ("nobody", &uid_nobody))
+    uid_nobody = -2;
+  r = uid_nobody;
 #endif
+  *negative = r < 0;
+  return r;
+}
+
 void
-uid_to_oct (uid_t v, char *p, size_t s)
+uid_to_chars (uid_t v, char *p, size_t s)
 {
-  to_oct ((uintmax_t) v, (uintmax_t) UID_NOBODY, p, s, "uid_t");
+  to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
 }
+
 void
-uintmax_to_oct (uintmax_t v, char *p, size_t s)
+uintmax_to_chars (uintmax_t v, char *p, size_t s)
 {
-  to_oct (v, (uintmax_t) 0, p, s, "uintmax_t");
+  to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
 }
 \f
 /* Writing routines.  */
@@ -178,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.                                        |
 `-------------------------------------------------------------------------*/
@@ -187,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);
 }
 
 /*-----------------------------------------------------.
@@ -242,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 *
@@ -252,35 +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 MSDOS
-      if (name[1] == ':')
+      if (prefix_len)
        {
-         name += 2;
+         static int warned_once;
          if (!warned_once)
            {
              warned_once = 1;
-             WARN ((0, 0, _("Removing drive spec from names in the archive")));
+             WARN ((0, 0, _("Removing `%.*s' prefix from archive names"),
+                    (int) prefix_len, name));
            }
+         name += prefix_len;
        }
-#endif
 
       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));
@@ -297,7 +427,7 @@ Removing leading `/' from absolute path names in the archive")));
   if (group_option != (gid_t) -1)
     st->st_gid = group_option;
   if (mode_option)
-    st->st_mode = ((st->st_mode & S_IFMT)
+    st->st_mode = ((st->st_mode & ~MODE_ALL)
                   | mode_adjust (st->st_mode, mode_option));
 
   /* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
@@ -324,27 +454,26 @@ Removing leading `/' from absolute path names in the archive")));
      acceptor for Paul's test.  */
 
   if (archive_format == V7_FORMAT)
-    MODE_TO_OCT (st->st_mode & 07777, header->header.mode);
+    MODE_TO_CHARS (st->st_mode & MODE_ALL, header->header.mode);
   else
-    MODE_TO_OCT (st->st_mode, header->header.mode);
+    MODE_TO_CHARS (st->st_mode, header->header.mode);
 
-  UID_TO_OCT (st->st_uid, header->header.uid);
-  GID_TO_OCT (st->st_gid, header->header.gid);
-  OFF_TO_OCT (st->st_size, header->header.size);
-  TIME_TO_OCT (st->st_mtime, header->header.mtime);
+  UID_TO_CHARS (st->st_uid, header->header.uid);
+  GID_TO_CHARS (st->st_gid, header->header.gid);
+  OFF_TO_CHARS (st->st_size, header->header.size);
+  TIME_TO_CHARS (st->st_mtime, header->header.mtime);
 
   if (incremental_option)
     if (archive_format == OLDGNU_FORMAT)
       {
-       TIME_TO_OCT (st->st_atime, header->oldgnu_header.atime);
-       TIME_TO_OCT (st->st_ctime, header->oldgnu_header.ctime);
+       TIME_TO_CHARS (st->st_atime, header->oldgnu_header.atime);
+       TIME_TO_CHARS (st->st_ctime, header->oldgnu_header.ctime);
       }
 
   header->header.typeflag = archive_format == V7_FORMAT ? AREGTYPE : REGTYPE;
 
   switch (archive_format)
     {
-    case DEFAULT_FORMAT:
     case V7_FORMAT:
       break;
 
@@ -358,6 +487,9 @@ Removing leading `/' from absolute path names in the archive")));
       strncpy (header->header.magic, TMAGIC, TMAGLEN);
       strncpy (header->header.version, TVERSION, TVERSLEN);
       break;
+
+    default:
+      abort ();
     }
 
   if (archive_format == V7_FORMAT || numeric_owner_option)
@@ -385,26 +517,25 @@ 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++;
 
   /* Fill in the checksum field.  It's formatted differently from the
      other fields: it has [6] digits, a null, then a space -- rather than
-     digits, then a null.  We use to_oct then write the null.
-     The final space is already there, from checksumming,
-     and to_oct doesn't modify it.
+     digits, then a null.  We use to_chars.
+     The final space is already there, from
+     checksumming, and to_chars doesn't modify it.
 
      This is a fast way to do:
 
      sprintf(header->header.chksum, "%6o", sum);  */
 
-  uintmax_to_oct ((uintmax_t) sum, header->header.chksum, 6);
-  header->header.chksum[6] = '\0';
+  uintmax_to_chars ((uintmax_t) sum, header->header.chksum, 7);
 
   set_next_block_after (header);
 
@@ -453,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;
@@ -511,15 +641,14 @@ deal_with_sparse (char *name, union block *header)
   init_sparsearray ();
   clear_buffer (buffer);
 
-  while (count = read (file, buffer, sizeof buffer), count != 0)
+  while (count = safe_read (file, buffer, sizeof buffer), count != 0)
     {
       /* Realloc the scratch area as necessary.  FIXME: should reallocate
         only at beginning of a new instance of non-zero data.  */
 
       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;
@@ -613,7 +742,7 @@ finish_sparse_file (int file, off_t *sizeleft, off_t fullsize, char *name)
          break;
        }
 
-      if (lseek (file, sparsearray[sparse_index++].offset, 0) < 0)
+      if (lseek (file, sparsearray[sparse_index++].offset, SEEK_SET) < 0)
        {
          char buf[UINTMAX_STRSIZE_BOUND];
          ERROR ((0, errno, _("lseek error at byte %s in file %s"),
@@ -630,8 +759,8 @@ finish_sparse_file (int file, off_t *sizeleft, off_t fullsize, char *name)
 #if 0
          if (amount_read)
            {
-             count = read (file, start->buffer + amount_read,
-                           BLOCKSIZE - amount_read);
+             count = safe_read (file, start->buffer + amount_read,
+                                BLOCKSIZE - amount_read);
              bufsize -= BLOCKSIZE - amount_read;
              amount_read = 0;
              set_next_block_after (start);
@@ -641,12 +770,12 @@ finish_sparse_file (int file, off_t *sizeleft, off_t fullsize, char *name)
 #endif
          /* Store the data.  */
 
-         count = read (file, start->buffer, BLOCKSIZE);
+         count = safe_read (file, start->buffer, BLOCKSIZE);
          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;
@@ -662,7 +791,7 @@ Read error at byte %s, reading %lu bytes, in file %s"),
        char buffer[BLOCKSIZE];
 
        clear_buffer (buffer);
-       count = read (file, buffer, bufsize);
+       count = safe_read (file, buffer, bufsize);
        memcpy (start->buffer, buffer, BLOCKSIZE);
       }
 
@@ -726,32 +855,33 @@ create_archive (void)
       collect_and_sort_names ();
 
       while (p = name_from_list (), p)
-       dump_file (p, (dev_t) -1, 1);
+       if (!excluded_name (p))
+         dump_file (p, (dev_t) -1, 1);
 
       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
     {
       while (p = name_next (1), p)
-       dump_file (p, (dev_t) -1, 1);
+       if (!excluded_name (p))
+         dump_file (p, (dev_t) -1, 1);
     }
 
   write_eot ();
@@ -813,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);
@@ -823,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;
@@ -854,19 +985,10 @@ dump_file (char *p, dev_t parent_device, int top_level)
 
   if (current_stat.st_nlink > 1
       && (S_ISREG (current_stat.st_mode)
-#ifdef S_ISCTG
          || S_ISCTG (current_stat.st_mode)
-#endif
-#ifdef S_ISCHR
          || S_ISCHR (current_stat.st_mode)
-#endif
-#ifdef S_ISBLK
          || S_ISBLK (current_stat.st_mode)
-#endif
-#ifdef S_ISFIFO
-         || S_ISFIFO (current_stat.st_mode)
-#endif
-      ))
+         || S_ISFIFO (current_stat.st_mode)))
     {
       struct link *lp;
 
@@ -881,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++;
              }
@@ -897,7 +1017,7 @@ Removing leading `/' from absolute links")));
 
            current_stat.st_size = 0;
            header = start_header (p, &current_stat);
-           if (header == NULL)
+           if (! header)
              {
                exit_status = TAREXIT_FAILURE;
                return;
@@ -924,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);
@@ -936,10 +1055,7 @@ Removing leading `/' from absolute links")));
   /* This is not a link to a previously dumped file, so dump it.  */
 
   if (S_ISREG (current_stat.st_mode)
-#ifdef S_ISCTG
-      || S_ISCTG (current_stat.st_mode)
-#endif
-      )
+      || S_ISCTG (current_stat.st_mode))
     {
       int f;                   /* file descriptor */
       size_t bufsize;
@@ -949,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;
 
@@ -996,7 +1109,7 @@ Removing leading `/' from absolute links")));
              int counter;
 
              header = start_header (p, &current_stat);
-             if (header == NULL)
+             if (! header)
                {
                  exit_status = TAREXIT_FAILURE;
                  return;
@@ -1021,8 +1134,8 @@ Removing leading `/' from absolute links")));
                 <file>.  It might be kind of disconcerting if the
                 shrunken file size was the one that showed up.  */
 
-             OFF_TO_OCT (current_stat.st_size,
-                         header->oldgnu_header.realsize);
+             OFF_TO_CHARS (current_stat.st_size,
+                           header->oldgnu_header.realsize);
 
              /* This will be the new "size" of the file, i.e., the size
                 of the file minus the blocks of holes that we're
@@ -1030,17 +1143,17 @@ Removing leading `/' from absolute links")));
 
              find_new_file_size (&filesize, upperbound);
              current_stat.st_size = filesize;
-             OFF_TO_OCT (filesize, header->header.size);
+             OFF_TO_CHARS (filesize, header->header.size);
 
              for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
                {
                  if (!sparsearray[counter].numbytes)
                    break;
 
-                 OFF_TO_OCT (sparsearray[counter].offset,
-                             header->oldgnu_header.sp[counter].offset);
-                 SIZE_TO_OCT (sparsearray[counter].numbytes,
-                              header->oldgnu_header.sp[counter].numbytes);
+                 OFF_TO_CHARS (sparsearray[counter].offset,
+                               header->oldgnu_header.sp[counter].offset);
+                 SIZE_TO_CHARS (sparsearray[counter].numbytes,
+                                header->oldgnu_header.sp[counter].numbytes);
                }
 
            }
@@ -1054,7 +1167,8 @@ Removing leading `/' from absolute links")));
         files when archive is meant for /dev/null.  */
 
       if (dev_null_output
-         || (sizeleft == 0 && 0444 == (0444 & current_stat.st_mode)))
+         || (sizeleft == 0
+             && MODE_R == (MODE_R & current_stat.st_mode)))
        f = -1;
       else
        {
@@ -1073,7 +1187,7 @@ Removing leading `/' from absolute links")));
       if (!header_moved)
        {
          header = start_header (p, &current_stat);
-         if (header == NULL)
+         if (! header)
            {
              if (f >= 0)
                close (f);
@@ -1081,12 +1195,12 @@ Removing leading `/' from absolute links")));
              return;
            }
        }
-#ifdef S_ISCTG
+
       /* Mark contiguous files, if we support them.  */
 
       if (archive_format != V7_FORMAT && S_ISCTG (current_stat.st_mode))
        header->header.typeflag = CONTTYPE;
-#endif
+
       isextended = header->oldgnu_header.isextended;
       save_typeflag = header->header.typeflag;
       finish_header (header);
@@ -1104,8 +1218,7 @@ Removing leading `/' from absolute links")));
 
        extend:
          exhdr = find_next_block ();
-
-         if (exhdr == NULL)
+         if (! exhdr)
            {
              exit_status = TAREXIT_FAILURE;
              return;
@@ -1116,10 +1229,10 @@ Removing leading `/' from absolute links")));
              if (counter + index_offset > upperbound)
                break;
 
-             SIZE_TO_OCT (sparsearray[counter + index_offset].numbytes,
-                          exhdr->sparse_header.sp[counter].numbytes);
-             OFF_TO_OCT (sparsearray[counter + index_offset].offset,
-                         exhdr->sparse_header.sp[counter].offset);
+             SIZE_TO_CHARS (sparsearray[counter + index_offset].numbytes,
+                            exhdr->sparse_header.sp[counter].numbytes);
+             OFF_TO_CHARS (sparsearray[counter + index_offset].offset,
+                           exhdr->sparse_header.sp[counter].offset);
            }
          set_next_block_after (exhdr);
 #if 0
@@ -1137,7 +1250,8 @@ Removing leading `/' from absolute links")));
        }
       if (save_typeflag == GNUTYPE_SPARSE)
        {
-         if (finish_sparse_file (f, &sizeleft, current_stat.st_size, p))
+         if (f < 0
+             || finish_sparse_file (f, &sizeleft, current_stat.st_size, p))
            goto padit;
        }
       else
@@ -1160,18 +1274,17 @@ 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;
            else
-             count = read (f, start->buffer, bufsize);
+             count = safe_read (f, start->buffer, bufsize);
            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));
@@ -1196,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)
        {
@@ -1231,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);
@@ -1241,11 +1354,11 @@ Read error at byte %s, reading %lu bytes, in file %s"),
       return;
     }
 
-#ifdef S_ISLNK
+#ifdef HAVE_READLINK
   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)
@@ -1262,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, &current_stat);
-      if (header == NULL)
+      if (! header)
        {
          exit_status = TAREXIT_FAILURE;
          return;
@@ -1278,7 +1391,7 @@ Read error at byte %s, reading %lu bytes, in file %s"),
        }
       return;
     }
-#endif /* S_ISLNK */
+#endif
 
   else if (S_ISDIR (current_stat.st_mode))
     {
@@ -1339,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, &current_stat);
-         if (header == NULL)
+         if (! header)
            {
              exit_status = TAREXIT_FAILURE;
              return;   /* eg name too long */
@@ -1376,7 +1489,7 @@ Read error at byte %s, reading %lu bytes, in file %s"),
              p_buffer += tmp;
            }
          totsize++;
-         OFF_TO_OCT (totsize, header->header.size);
+         OFF_TO_CHARS (totsize, header->header.size);
          finish_header (header);
          p_buffer = buffer;
          sizeleft = totsize;
@@ -1395,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;
@@ -1404,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;
@@ -1438,16 +1550,11 @@ 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)
        {
-         /* Skip `.' and `..'.  */
+         /* Skip `.', `..', and excluded file names.  */
 
          if (is_dot_or_dotdot (entry->d_name))
            continue;
@@ -1455,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"),
@@ -1464,9 +1571,8 @@ Read error at byte %s, reading %lu bytes, in file %s"),
 #endif
            }
          strcpy (namebuf + len, entry->d_name);
-         if (exclude_option && check_exclude (namebuf))
-           continue;
-         dump_file (namebuf, our_device, 0);
+         if (!excluded_name (namebuf))
+           dump_file (namebuf, our_device, 0);
        }
 
       closedir (directory);
@@ -1476,28 +1582,13 @@ Read error at byte %s, reading %lu bytes, in file %s"),
       return;
     }
 
-#ifdef S_ISCHR
   else if (S_ISCHR (current_stat.st_mode))
     type = CHRTYPE;
-#endif
-
-#ifdef S_ISBLK
   else if (S_ISBLK (current_stat.st_mode))
     type = BLKTYPE;
-#endif
-
-  /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK.  */
-
-#if (_ISP__M68K == 0) && (_ISP__A88K == 0) && defined(S_ISFIFO)
-  else if (S_ISFIFO (current_stat.st_mode))
-    type = FIFOTYPE;
-#endif
-
-#ifdef S_ISSOCK
-  else if (S_ISSOCK (current_stat.st_mode))
+  else if (S_ISFIFO (current_stat.st_mode)
+          || S_ISSOCK (current_stat.st_mode))
     type = FIFOTYPE;
-#endif
-
   else
     goto unknown;
 
@@ -1506,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, &current_stat);
-  if (header == NULL)
+  if (! header)
     {
       exit_status = TAREXIT_FAILURE;
       return;  /* eg name too long */
@@ -1514,13 +1605,11 @@ Read error at byte %s, reading %lu bytes, in file %s"),
 
   header->header.typeflag = type;
 
-#if defined(S_IFBLK) || defined(S_IFCHR)
   if (type != FIFOTYPE)
     {
-      MAJOR_TO_OCT (major (current_stat.st_rdev), header->header.devmajor);
-      MINOR_TO_OCT (minor (current_stat.st_rdev), header->header.devminor);
+      MAJOR_TO_CHARS (major (current_stat.st_rdev), header->header.devmajor);
+      MINOR_TO_CHARS (minor (current_stat.st_rdev), header->header.devminor);
     }
-#endif
 
   finish_header (header);
   if (remove_files_option)
This page took 0.048482 seconds and 4 git commands to generate.