]> Dogcows Code - chaz/tar/blobdiff - src/create.c
Adjust to recent gnulib changes.
[chaz/tar] / src / create.c
index 087cacd678e04cacec6107a634a0fc39a6888e57..eb528be25626e9db921a1012ed5608821888a51a 100644 (file)
@@ -1,7 +1,7 @@
 /* Create a tar archive.
 
    Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
@@ -108,6 +108,68 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
   while (i);
 }
 
+
+static bool
+to_chars (int negative, uintmax_t value, size_t valsize,
+         uintmax_t (*substitute) (int *),
+         char *where, size_t size, const char *type);
+
+static bool
+to_chars_subst (int negative, int gnu_format, uintmax_t value, size_t valsize,
+               uintmax_t (*substitute) (int *),
+               char *where, size_t size, const char *type)
+{
+  uintmax_t maxval = (gnu_format
+                     ? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
+                     : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
+  char valbuf[UINTMAX_STRSIZE_BOUND + 1];
+  char maxbuf[UINTMAX_STRSIZE_BOUND];
+  char minbuf[UINTMAX_STRSIZE_BOUND + 1];
+  char const *minval_string;
+  char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
+  char const *value_string;
+
+  if (gnu_format)
+    {
+      uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
+      char *p = STRINGIFY_BIGINT (m, minbuf + 1);
+      *--p = '-';
+      minval_string = p;
+    }
+  else
+    minval_string = "0";
+
+  if (negative)
+    {
+      char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
+      *--p = '-';
+      value_string = p;
+    }
+  else
+    value_string = STRINGIFY_BIGINT (value, valbuf);
+
+  if (substitute)
+    {
+      int negsub;
+      uintmax_t sub = substitute (&negsub) & maxval;
+      /* FIXME: This is the only place where GNU_FORMAT differs from
+        OLDGNU_FORMAT. Apart from this they are completely identical. */
+      uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
+      char subbuf[UINTMAX_STRSIZE_BOUND + 1];
+      char *sub_string = STRINGIFY_BIGINT (s, subbuf + 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));
+      return to_chars (negsub, s, valsize, 0, where, size, type);
+    }
+  else
+    ERROR ((0, 0, _("value %s out of %s range %s..%s"),
+           value_string, type, minval_string, maxval_string));
+  return false;
+}
+
 /* Convert NEGATIVE VALUE (which was originally of size VALSIZE) to
    external form, using SUBSTITUTE (...) if VALUE won't fit.  Output
    to buffer WHERE with size SIZE.  NEGATIVE is 1 iff VALUE was
@@ -122,103 +184,61 @@ to_base256 (int negative, uintmax_t value, char *where, size_t size)
    SUBSTITUTE the address of an 0-or-1 flag recording whether the
    substitute value is negative.  */
 
-static void
+static bool
 to_chars (int negative, uintmax_t value, size_t valsize,
          uintmax_t (*substitute) (int *),
          char *where, size_t size, const char *type)
 {
-  int base256_allowed = (archive_format == GNU_FORMAT
-                        || archive_format == OLDGNU_FORMAT);
+  int gnu_format = (archive_format == GNU_FORMAT
+                   || archive_format == OLDGNU_FORMAT);
 
   /* Generate the POSIX octal representation if the number fits.  */
   if (! negative && value <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
     {
       where[size - 1] = '\0';
       to_octal (value, where, size - 1);
+      return true;
     }
-
-  /* Otherwise, generate the base-256 representation if we are
-     generating an old or new GNU format and if the number fits.  */
-  else if (((negative ? -1 - value : value)
-           <= MAX_VAL_WITH_DIGITS (size - 1, LG_256))
-          && base256_allowed)
-    {
-      where[0] = negative ? -1 : 1 << (LG_256 - 1);
-      to_base256 (negative, value, where + 1, size - 1);
-    }
-
-  /* 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)
+  else if (gnu_format)
     {
-      static int warned_once;
-      if (! warned_once)
-       {
-         warned_once = 1;
-         WARN ((0, 0, _("Generating negative octal headers")));
-       }
-      where[size - 1] = '\0';
-      to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
-               where, size - 1);
-    }
-
-  /* Otherwise, output a substitute value if possible (with a
-     warning), and an error message if not.  */
-  else
-    {
-      uintmax_t maxval = (base256_allowed
-                         ? MAX_VAL_WITH_DIGITS (size - 1, LG_256)
-                         : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
-      char valbuf[UINTMAX_STRSIZE_BOUND + 1];
-      char maxbuf[UINTMAX_STRSIZE_BOUND];
-      char minbuf[UINTMAX_STRSIZE_BOUND + 1];
-      char const *minval_string;
-      char const *maxval_string = STRINGIFY_BIGINT (maxval, maxbuf);
-      char const *value_string;
-
-      if (base256_allowed)
-       {
-         uintmax_t m = maxval + 1 ? maxval + 1 : maxval / 2 + 1;
-         char *p = STRINGIFY_BIGINT (m, minbuf + 1);
-         *--p = '-';
-         minval_string = p;
-       }
-      else
-       minval_string = "0";
+      /* Try to cope with the number by using traditional GNU format
+        methods */
 
-      if (negative)
+      /* Generate the base-256 representation if the number fits.  */
+      if (((negative ? -1 - value : value)
+          <= MAX_VAL_WITH_DIGITS (size - 1, LG_256)))
        {
-         char *p = STRINGIFY_BIGINT (- value, valbuf + 1);
-         *--p = '-';
-         value_string = p;
+         where[0] = negative ? -1 : 1 << (LG_256 - 1);
+         to_base256 (negative, value, where + 1, size - 1);
+         return true;
        }
-      else
-       value_string = STRINGIFY_BIGINT (value, valbuf);
 
-      if (substitute)
+      /* 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 negsub;
-         uintmax_t sub = substitute (&negsub) & maxval;
-         /* FIXME: This is the only place where GNU_FORMAT differs from
-             OLDGNU_FORMAT. Apart from this they are completely identical. */
-         uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? - sub : sub;
-         char subbuf[UINTMAX_STRSIZE_BOUND + 1];
-         char *sub_string = STRINGIFY_BIGINT (s, subbuf + 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);
+         static int warned_once;
+         if (! warned_once)
+           {
+             warned_once = 1;
+             WARN ((0, 0, _("Generating negative octal headers")));
+           }
+         where[size - 1] = '\0';
+         to_octal (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
+                   where, size - 1);
+         return true;
        }
-      else
-       ERROR ((0, 0, _("value %s out of %s range %s..%s"),
-               value_string, type, minval_string, maxval_string));
+      /* Otherwise fall back to substitution, if possible: */
     }
+  else
+    substitute = NULL; /* No substitution for formats, other than GNU */
+
+  return to_chars_subst (negative, gnu_format, value, valsize, substitute,
+                        where, size, type);
 }
 
 static uintmax_t
@@ -237,25 +257,25 @@ gid_substitute (int *negative)
   return r;
 }
 
-void
+bool
 gid_to_chars (gid_t v, char *p, size_t s)
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
 }
 
-void
+bool
 major_to_chars (major_t v, char *p, size_t s)
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
 }
 
-void
+bool
 minor_to_chars (minor_t v, char *p, size_t s)
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
 }
 
-void
+bool
 mode_to_chars (mode_t v, char *p, size_t s)
 {
   /* In the common case where the internal and external mode bits are the same,
@@ -292,25 +312,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, 0, p, s, "mode_t");
+  return to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
 }
 
-void
+bool
 off_to_chars (off_t v, char *p, size_t s)
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
 }
 
-void
+bool
 size_to_chars (size_t v, char *p, size_t s)
 {
-  to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
+  return to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
 }
 
-void
+bool
 time_to_chars (time_t v, char *p, size_t s)
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
 }
 
 static uintmax_t
@@ -329,16 +349,16 @@ uid_substitute (int *negative)
   return r;
 }
 
-void
+bool
 uid_to_chars (uid_t v, char *p, size_t s)
 {
-  to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
+  return to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
 }
 
-void
+bool
 uintmax_to_chars (uintmax_t v, char *p, size_t s)
 {
-  to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
+  return to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
 }
 
 void
@@ -360,7 +380,7 @@ bool
 file_dumpable_p (struct tar_stat_info *st)
 {
   if (dev_null_output)
-    return totals_option && sparse_option && sparse_file_p (st);
+    return totals_option && sparse_option && ST_IS_SPARSE (st->stat);
   return !(st->archive_file_size == 0
           && (st->stat.st_mode & MODE_R) == MODE_R);
 }
@@ -474,7 +494,7 @@ split_long_name (const char *name, size_t length)
   size_t i;
 
   if (length > PREFIX_FIELD_SIZE)
-    length = PREFIX_FIELD_SIZE+2;
+    length = PREFIX_FIELD_SIZE + 1;
   for (i = length - 1; i > 0; i--)
     if (ISSLASH (name[i]))
       break;
@@ -643,7 +663,8 @@ start_header (struct tar_stat_info *st)
   if (mode_option)
     st->stat.st_mode =
       ((st->stat.st_mode & ~MODE_ALL)
-       | mode_adjust (st->stat.st_mode, mode_option, initial_umask));
+       | mode_adjust (st->stat.st_mode, S_ISDIR (st->stat.st_mode) != 0,
+                     initial_umask, mode_option, NULL));
 
   /* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
      for a few tars and came up with the following interoperability
@@ -681,7 +702,8 @@ start_header (struct tar_stat_info *st)
        xheader_store ("uid", st, NULL);
        uid = 0;
       }
-    UID_TO_CHARS (uid, header->header.uid);
+    if (!UID_TO_CHARS (uid, header->header.uid))
+      return NULL;
   }
 
   {
@@ -692,7 +714,8 @@ start_header (struct tar_stat_info *st)
        xheader_store ("gid", st, NULL);
        gid = 0;
       }
-    GID_TO_CHARS (gid, header->header.gid);
+    if (!GID_TO_CHARS (gid, header->header.gid))
+      return NULL;
   }
 
   {
@@ -703,11 +726,12 @@ start_header (struct tar_stat_info *st)
        xheader_store ("size", st, NULL);
        size = 0;
       }
-    OFF_TO_CHARS (size, header->header.size);
+    if (!OFF_TO_CHARS (size, header->header.size))
+      return NULL;
   }
 
   {
-    struct timespec mtime = st->mtime;
+    struct timespec mtime = set_mtime_option ? mtime_option : st->mtime;
     if (archive_format == POSIX_FORMAT)
       {
        if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec
@@ -716,7 +740,8 @@ start_header (struct tar_stat_info *st)
        if (MAX_OCTAL_VAL (header->header.mtime) < mtime.tv_sec)
          mtime.tv_sec = 0;
       }
-    TIME_TO_CHARS (mtime.tv_sec, header->header.mtime);
+    if (!TIME_TO_CHARS (mtime.tv_sec, header->header.mtime))
+      return NULL;
   }
 
   /* FIXME */
@@ -732,7 +757,8 @@ start_header (struct tar_stat_info *st)
          xheader_store ("devmajor", st, NULL);
          devmajor = 0;
        }
-      MAJOR_TO_CHARS (devmajor, header->header.devmajor);
+      if (!MAJOR_TO_CHARS (devmajor, header->header.devmajor))
+       return NULL;
 
       if (archive_format == POSIX_FORMAT
          && MAX_OCTAL_VAL (header->header.devminor) < devminor)
@@ -740,12 +766,14 @@ start_header (struct tar_stat_info *st)
          xheader_store ("devminor", st, NULL);
          devminor = 0;
        }
-      MINOR_TO_CHARS (devminor, header->header.devminor);
+      if (!MINOR_TO_CHARS (devminor, header->header.devminor))
+       return NULL;
     }
   else if (archive_format != GNU_FORMAT && archive_format != OLDGNU_FORMAT)
     {
-      MAJOR_TO_CHARS (0, header->header.devmajor);
-      MINOR_TO_CHARS (0, header->header.devminor);
+      if (!(MAJOR_TO_CHARS (0, header->header.devmajor)
+           && MINOR_TO_CHARS (0, header->header.devminor)))
+       return NULL;
     }
 
   if (archive_format == POSIX_FORMAT)
@@ -1155,7 +1183,7 @@ dump_dir (int fd, struct tar_stat_info *st, int top_level, dev_t parent_device)
 void
 create_archive (void)
 {
-  char *p;
+  const char *p;
 
   open_archive (ACCESS_WRITE);
   xheader_write_global ();
@@ -1289,7 +1317,7 @@ dump_hard_link (struct tar_stat_info *st)
          st->stat.st_size = 0;
          blk = start_header (st);
          if (!blk)
-           return true;
+           return false;
          tar_copy_str (blk->header.linkname, link_name, NAME_FIELD_SIZE);
 
          blk->header.typeflag = LNKTYPE;
@@ -1360,7 +1388,7 @@ check_links (void)
    exit_status to failure, a clear diagnostic has been issued.  */
 
 static void
-dump_file0 (struct tar_stat_info *st, char const *p,
+dump_file0 (struct tar_stat_info *st, const char *p,
            int top_level, dev_t parent_device)
 {
   union block *header;
@@ -1377,6 +1405,8 @@ dump_file0 (struct tar_stat_info *st, char const *p,
   assign_string (&st->file_name,
                  safer_name_suffix (p, false, absolute_names_option));
 
+  transform_name (&st->file_name);
+
   if (deref_stat (dereference_option, p, &st->stat) != 0)
     {
       stat_diag (p);
@@ -1470,7 +1500,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
        {
          enum dump_status status;
 
-         if (fd != -1 && sparse_option && sparse_file_p (st))
+         if (fd != -1 && sparse_option && ST_IS_SPARSE (st->stat))
            {
              status = sparse_dump_file (fd, st);
              if (status == dump_status_not_implemented)
@@ -1493,6 +1523,8 @@ dump_file0 (struct tar_stat_info *st, char const *p,
              abort ();
            }
 
+         file_count_links (st);
+
          ok = status == dump_status_ok;
        }
 
@@ -1638,7 +1670,7 @@ dump_file0 (struct tar_stat_info *st, char const *p,
 }
 
 void
-dump_file (char *p, int top_level, dev_t parent_device)
+dump_file (const char *p, int top_level, dev_t parent_device)
 {
   struct tar_stat_info st;
   tar_stat_init (&st);
This page took 0.032065 seconds and 4 git commands to generate.