]> Dogcows Code - chaz/tar/blobdiff - src/create.c
(make_directories): Do not chown intermediate directories, even
[chaz/tar] / src / create.c
index 3a7e56a4645dfb694d753f9fd49af4ab3e2a111f..9bd4dead7b940c5904f8b7e7efaf6f9303e104cc 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"
 
@@ -55,121 +55,233 @@ struct link
 
 struct link *linklist = NULL;  /* 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!     |
-`------------------------------------------------------------------------*/
-
-/* Output VALUE in octal, using SUBSTITUTE if value won't fit.
+/* 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.
-   TYPE is the kind of value being output (useful for diagnostics).
-   Prefer SIZE - 1 octal digits (with leading '0's), followed by '\0';
-   but if SIZE octal digits would fit, omit the '\0'.  */
+   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;
-
-# define MAX_OCTAL_VAL_WITH_DIGITS(digits) \
-    ((digits) * 3 < sizeof (uintmax_t) * CHAR_BIT \
-     ? ((uintmax_t) 1 << ((digits) * 3)) - 1 \
-     : (uintmax_t) -1)
-
-  /* Output a trailing NUL unless the value is too large.  */
-  if (value <= MAX_OCTAL_VAL_WITH_DIGITS (size - 1))
-    where[--i] = '\0';
-
-  /* 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 != 0 && v != 0);
+  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.  */
 
-  /* Leading zeros, if necessary.  */
-  while (i != 0)
-    where[--i] = '0';
+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;
 
-  if (v != 0)
+  if (! negative && v <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
     {
-      uintmax_t maxval = MAX_OCTAL_VAL_WITH_DIGITS (size);
-      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 (v, LG_8, base_8_digits, where, size - 1);
+    }
+  else if (v <= MAX_VAL_WITH_DIGITS (size - 1, LG_64)
+          && archive_format == GNU_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)
+    {
+      where[size - 1] = '\0';
+      to_base (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
+              LG_8, base_8_digits, where, size - 1);
+    }
+  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, _("%s value %s out of range %s..%s; substituting %s"),
+                type, value_string, minval_string, maxval_string,
+                sub_string));
+         to_chars (negsub, s, valsize, NULL, where, size, type);
        }
       else
-       ERROR ((0, 0, _("%s value %s too large (max=%s)"),
-               type, value_string, maxval_string));
+       ERROR ((0, 0, _("%s value %s out of range %s..%s"),
+               type, value_string, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, 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, NULL, p, s, "uintmax_t");
 }
 \f
 /* Writing routines.  */
@@ -260,29 +372,29 @@ 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++;
        }
     }
 
@@ -305,7 +417,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)
@@ -332,27 +444,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;
 
@@ -366,6 +477,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)
@@ -403,15 +517,15 @@ finish_header (union block *header)
 
   /* 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.
-     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, 7);
+  uintmax_to_chars ((uintmax_t) sum, header->header.chksum, 7);
 
   set_next_block_after (header);
 
@@ -518,7 +632,7 @@ 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.  */
@@ -620,7 +734,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"),
@@ -637,8 +751,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);
@@ -648,7 +762,7 @@ 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];
@@ -669,7 +783,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);
       }
 
@@ -733,32 +847,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 ();
@@ -830,14 +945,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;
@@ -861,19 +977,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;
 
@@ -888,13 +995,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++;
              }
@@ -943,10 +1048,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;
@@ -1028,8 +1130,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
@@ -1037,17 +1139,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);
                }
 
            }
@@ -1061,7 +1163,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
        {
@@ -1088,12 +1191,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);
@@ -1123,10 +1226,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
@@ -1144,7 +1247,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
@@ -1173,7 +1277,7 @@ Removing leading `/' from absolute links")));
            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];
@@ -1248,7 +1352,7 @@ 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;
@@ -1285,7 +1389,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))
     {
@@ -1383,7 +1487,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;
@@ -1445,16 +1549,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;
@@ -1471,9 +1570,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);
@@ -1483,28 +1581,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))
+  else if (S_ISFIFO (current_stat.st_mode)
+          || S_ISSOCK (current_stat.st_mode))
     type = FIFOTYPE;
-#endif
-
-#ifdef S_ISSOCK
-  else if (S_ISSOCK (current_stat.st_mode))
-    type = FIFOTYPE;
-#endif
-
   else
     goto unknown;
 
@@ -1521,13 +1604,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.046271 seconds and 4 git commands to generate.