]> Dogcows Code - chaz/tar/blobdiff - src/incremen.c
maint: update copyrights for 2013 and as per current GNU standards
[chaz/tar] / src / incremen.c
index b2ab5bf0557e6331e9a612e010e5410cabe0dfdb..7130bc22773b40dc7317036278c3407d533f0b0d 100644 (file)
@@ -1,21 +1,22 @@
 /* GNU dump extensions to tar.
 
-   Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2009, 2013
+   Free Software Foundation, Inc.
 
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 3, or (at your option) any later
-   version.
+   This file is part of GNU tar.
 
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
-   Public License for more details.
+   GNU tar is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
-   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.,
-   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   GNU tar is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <system.h>
 #include <hash.h>
@@ -300,6 +301,24 @@ dirlist_replace_prefix (const char *pref, const char *repl)
     replace_prefix (&dp->name, pref, pref_len, repl, repl_len);
 }
 
+void
+clear_directory_table (void)
+{
+  struct directory *dp;
+
+  if (directory_table)
+    hash_clear (directory_table);
+  if (directory_meta_table)
+    hash_clear (directory_meta_table);
+  for (dp = dirhead; dp; )
+    {
+      struct directory *next = dp->next;
+      free_directory (dp);
+      dp = next;
+    }
+  dirhead = dirtail = NULL;
+}
+
 /* Create and link a new directory entry for directory NAME, having a
    device number DEV and an inode number INO, with NFS indicating
    whether it is an NFS device and FOUND indicating whether we have
@@ -327,7 +346,8 @@ note_directory (char const *name, struct timespec mtime,
   if (! ((directory_table
          || (directory_table = hash_initialize (0, 0,
                                                 hash_directory_canonical_name,
-                                                compare_directory_canonical_names, 0)))
+                                                compare_directory_canonical_names,
+                                                0)))
         && hash_insert (directory_table, directory)))
     xalloc_die ();
 
@@ -427,6 +447,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
   struct directory *directory;
   struct stat *stat_data = &st->stat;
   bool nfs = NFS_FILE_STAT (*stat_data);
+  bool perhaps_renamed = false;
 
   if ((directory = find_directory (name_buffer)) != NULL)
     {
@@ -481,9 +502,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
            }
          else
            {
-             WARNOPT (WARN_RENAME_DIRECTORY,
-                      (0, 0, _("%s: Directory has been renamed"),
-                       quotearg_colon (name_buffer)));
+             perhaps_renamed = true;
              directory->children = ALL_CHILDREN;
              directory->device_number = stat_data->st_dev;
              directory->inode_number = stat_data->st_ino;
@@ -502,7 +521,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
                                                 stat_data->st_ino);
 
       directory = note_directory (name_buffer,
-                                 get_stat_mtime(stat_data),
+                                 get_stat_mtime (stat_data),
                                  stat_data->st_dev,
                                  stat_data->st_ino,
                                  nfs,
@@ -541,13 +560,21 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
 
   if (one_file_system_option && st->parent
       && stat_data->st_dev != st->parent->stat.st_dev)
-    /* FIXME:
-       WARNOPT (WARN_XDEV,
-                (0, 0,
-                 _("%s: directory is on a different filesystem; not dumped"),
-                 quotearg_colon (directory->name)));
-    */
-    directory->children = NO_CHILDREN;
+    {
+      WARNOPT (WARN_XDEV,
+              (0, 0,
+               _("%s: directory is on a different filesystem; not dumped"),
+               quotearg_colon (directory->name)));
+      directory->children = NO_CHILDREN;
+      /* If there is any dumpdir info in that directory, remove it */
+      if (directory->dump)
+       {
+         dumpdir_free (directory->dump);
+         directory->dump = NULL;
+       }
+      perhaps_renamed = false;
+    }
+
   else if (flag & PD_FORCE_CHILDREN)
     {
       directory->children = PD_CHILDREN(flag);
@@ -555,6 +582,11 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
        *entry = 'N';
     }
 
+  if (perhaps_renamed)
+    WARNOPT (WARN_RENAME_DIRECTORY,
+            (0, 0, _("%s: Directory has been renamed"),
+             quotearg_colon (name_buffer)));
+
   DIR_SET_FLAG (directory, DIRF_INIT);
 
   if (directory->children != NO_CHILDREN)
@@ -829,7 +861,7 @@ store_rename (struct directory *dir, struct obstack *stk)
         are ignored when hit by this function next time.
         If the chain forms a cycle, prev points to the entry DIR is renamed
         from. In this case it still retains DIRF_RENAMED flag, which will be
-        cleared in the `else' branch below */
+        cleared in the 'else' branch below */
       for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
        DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
 
@@ -915,8 +947,6 @@ read_incr_db_01 (int version, const char *initbuf)
 {
   int n;
   uintmax_t u;
-  time_t sec;
-  long int nsec;
   char *buf = NULL;
   size_t bufsize = 0;
   char *ebuf;
@@ -938,21 +968,15 @@ read_incr_db_01 (int version, const char *initbuf)
       bufsize = strlen (buf) + 1;
     }
 
-  sec = TYPE_MINIMUM (time_t);
-  nsec = -1;
-  errno = 0;
-  u = strtoumax (buf, &ebuf, 10);
-  if (!errno && TYPE_MAXIMUM (time_t) < u)
-    errno = ERANGE;
-  if (errno || buf == ebuf)
+  newer_mtime_option = decode_timespec (buf, &ebuf, false);
+
+  if (! valid_timespec (newer_mtime_option))
     ERROR ((0, errno, "%s:%ld: %s",
            quotearg_colon (listed_incremental_option),
            lineno,
            _("Invalid time stamp")));
   else
     {
-      sec = u;
-
       if (version == 1 && *ebuf)
        {
          char const *buf_ns = ebuf + 1;
@@ -966,20 +990,13 @@ read_incr_db_01 (int version, const char *initbuf)
                      quotearg_colon (listed_incremental_option),
                      lineno,
                      _("Invalid time stamp")));
-             sec = TYPE_MINIMUM (time_t);
+             newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
+             newer_mtime_option.tv_nsec = -1;
            }
          else
-           nsec = u;
-       }
-      else
-       {
-         /* pre-1 incremental format does not contain nanoseconds */
-         nsec = 0;
+           newer_mtime_option.tv_nsec = u;
        }
     }
-  newer_mtime_option.tv_sec = sec;
-  newer_mtime_option.tv_nsec = nsec;
-
 
   while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
     {
@@ -996,20 +1013,12 @@ read_incr_db_01 (int version, const char *initbuf)
 
       if (version == 1)
        {
-         errno = 0;
-         u = strtoumax (strp, &ebuf, 10);
-         if (!errno && TYPE_MAXIMUM (time_t) < u)
-           errno = ERANGE;
-         if (errno || strp == ebuf || *ebuf != ' ')
-           {
-             ERROR ((0, errno, "%s:%ld: %s",
-                     quotearg_colon (listed_incremental_option), lineno,
-                     _("Invalid modification time (seconds)")));
-             sec = (time_t) -1;
-           }
-         else
-           sec = u;
+         mtime = decode_timespec (strp, &ebuf, false);
          strp = ebuf;
+         if (!valid_timespec (mtime) || *strp != ' ')
+           ERROR ((0, errno, "%s:%ld: %s",
+                   quotearg_colon (listed_incremental_option), lineno,
+                   _("Invalid modification time")));
 
          errno = 0;
          u = strtoumax (strp, &ebuf, 10);
@@ -1020,46 +1029,30 @@ read_incr_db_01 (int version, const char *initbuf)
              ERROR ((0, errno, "%s:%ld: %s",
                      quotearg_colon (listed_incremental_option), lineno,
                      _("Invalid modification time (nanoseconds)")));
-             nsec = -1;
+             mtime.tv_nsec = -1;
            }
          else
-           nsec = u;
-         mtime.tv_sec = sec;
-         mtime.tv_nsec = nsec;
+           mtime.tv_nsec = u;
          strp = ebuf;
        }
       else
-       memset (&mtime, 0, sizeof mtime);
+       mtime.tv_sec = mtime.tv_nsec = 0;
 
-      errno = 0;
-      u = strtoumax (strp, &ebuf, 10);
-      if (!errno && TYPE_MAXIMUM (dev_t) < u)
-       errno = ERANGE;
-      if (errno || strp == ebuf || *ebuf != ' ')
-       {
-         ERROR ((0, errno, "%s:%ld: %s",
-                 quotearg_colon (listed_incremental_option), lineno,
-                 _("Invalid device number")));
-         dev = (dev_t) -1;
-       }
-      else
-       dev = u;
+      dev = strtosysint (strp, &ebuf,
+                        TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t));
       strp = ebuf;
+      if (errno || *strp != ' ')
+       ERROR ((0, errno, "%s:%ld: %s",
+               quotearg_colon (listed_incremental_option), lineno,
+               _("Invalid device number")));
 
-      errno = 0;
-      u = strtoumax (strp, &ebuf, 10);
-      if (!errno && TYPE_MAXIMUM (ino_t) < u)
-       errno = ERANGE;
-      if (errno || strp == ebuf || *ebuf != ' ')
-       {
-         ERROR ((0, errno, "%s:%ld: %s",
-                 quotearg_colon (listed_incremental_option), lineno,
-                 _("Invalid inode number")));
-         ino = (ino_t) -1;
-       }
-      else
-       ino = u;
+      ino = strtosysint (strp, &ebuf,
+                        TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t));
       strp = ebuf;
+      if (errno || *strp != ' ')
+       ERROR ((0, errno, "%s:%ld: %s",
+               quotearg_colon (listed_incremental_option), lineno,
+               _("Invalid inode number")));
 
       strp++;
       unquote_string (strp);
@@ -1125,8 +1118,8 @@ read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
 }
 
 /* Read from file FP a nul-terminated string and convert it to
-   uintmax_t.  Return the resulting value in PVAL.  Assume C has
-   already been read.
+   uintmax_t.  Return an intmax_t representation of the resulting
+   value in PVAL.  Assume C has already been read.
 
    Throw a fatal error if the string cannot be converted or if the
    converted value exceeds MAX_VAL.
@@ -1134,9 +1127,10 @@ read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
    Return the last character read or EOF on end of file. */
 
 static int
-read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
+read_unsigned_num (int c, FILE *fp, uintmax_t max_val, intmax_t *pval)
 {
   size_t i;
+  uintmax_t u;
   char buf[UINTMAX_STRSIZE_BOUND], *ep;
 
   for (i = 0; ISDIGIT (c); i++)
@@ -1159,24 +1153,32 @@ read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
 
   buf[i] = 0;
   errno = 0;
-  *pval = strtoumax (buf, &ep, 10);
-  if (c || errno || max_val < *pval)
+  u = strtoumax (buf, &ep, 10);
+  if (c || errno || max_val < u)
     FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
+  *pval = represent_uintmax (u);
   return c;
 }
 
 /* Read from file FP a nul-terminated string and convert it to
-   uintmax_t.  Return the resulting value in PVAL.
+   an integer in the range MIN_VAL..MAXVAL.  Return the resulting
+   value, converted to intmax_t, in PVAL.  MINVAL must be nonpositive.
 
    Throw a fatal error if the string cannot be converted or if the
-   converted value exceeds MAX_VAL.
+   converted value is out of range.
 
    Return the last character read or EOF on end of file. */
 
 static int
-read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
+read_num (FILE *fp, intmax_t min_val, uintmax_t max_val, intmax_t *pval)
 {
-  return read_unsigned_num (getc (fp), fp, max_val, pval);
+  int c = getc (fp);
+  if (c == '-')
+    {
+      read_negative_num (fp, min_val, pval);
+      return 0;
+    }
+  return read_unsigned_num (c, fp, max_val, pval);
 }
 
 /* Read from FP two NUL-terminated strings representing a struct
@@ -1187,34 +1189,21 @@ read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
 static void
 read_timespec (FILE *fp, struct timespec *pval)
 {
-  int c = getc (fp);
   intmax_t i;
-  uintmax_t u;
-
-  if (c == '-')
-    {
-      read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
-      c = 0;
-      pval->tv_sec = i;
-    }
-  else
-    {
-      c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
-      pval->tv_sec = u;
-    }
+  int c = read_num (fp, TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &i);
+  pval->tv_sec = i;
 
-  if (c || read_num (fp, BILLION - 1, &u))
+  if (c || read_num (fp, 0, BILLION - 1, &i))
     FATAL_ERROR ((0, 0, "%s: %s",
                  quotearg_colon (listed_incremental_option),
                  _("Unexpected EOF in snapshot file")));
-  pval->tv_nsec = u;
+  pval->tv_nsec = i;
 }
 
 /* Read incremental snapshot format 2 */
 static void
 read_incr_db_2 (void)
 {
-  uintmax_t u;
   struct obstack stk;
 
   obstack_init (&stk);
@@ -1223,6 +1212,7 @@ read_incr_db_2 (void)
 
   for (;;)
     {
+      intmax_t i;
       struct timespec mtime;
       dev_t dev;
       ino_t ino;
@@ -1231,20 +1221,22 @@ read_incr_db_2 (void)
       char *content;
       size_t s;
 
-      if (read_num (listed_incremental_stream, 1, &u))
+      if (read_num (listed_incremental_stream, 0, 1, &i))
        return; /* Normal return */
 
-      nfs = u;
+      nfs = i;
 
       read_timespec (listed_incremental_stream, &mtime);
 
-      if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
+      if (read_num (listed_incremental_stream,
+                   TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i))
        break;
-      dev = u;
+      dev = i;
 
-      if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
+      if (read_num (listed_incremental_stream,
+                   TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i))
        break;
-      ino = u;
+      ino = i;
 
       if (read_obstack (listed_incremental_stream, &stk, &s))
        break;
@@ -1360,20 +1352,21 @@ write_directory_file_entry (void *entry, void *data)
 
   if (DIR_IS_FOUND (directory))
     {
-      char buf[UINTMAX_STRSIZE_BOUND];
+      char buf[max (SYSINT_BUFSIZE, INT_BUFSIZE_BOUND (intmax_t))];
       char const *s;
 
       s = DIR_IS_NFS (directory) ? "1" : "0";
       fwrite (s, 2, 1, fp);
-      s = (TYPE_SIGNED (time_t)
-          ? imaxtostr (directory->mtime.tv_sec, buf)
-          : umaxtostr (directory->mtime.tv_sec, buf));
+      s = sysinttostr (directory->mtime.tv_sec, TYPE_MINIMUM (time_t),
+                      TYPE_MAXIMUM (time_t), buf);
       fwrite (s, strlen (s) + 1, 1, fp);
-      s = umaxtostr (directory->mtime.tv_nsec, buf);
+      s = imaxtostr (directory->mtime.tv_nsec, buf);
       fwrite (s, strlen (s) + 1, 1, fp);
-      s = umaxtostr (directory->device_number, buf);
+      s = sysinttostr (directory->device_number,
+                      TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf);
       fwrite (s, strlen (s) + 1, 1, fp);
-      s = umaxtostr (directory->inode_number, buf);
+      s = sysinttostr (directory->inode_number,
+                      TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), buf);
       fwrite (s, strlen (s) + 1, 1, fp);
 
       fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
This page took 0.032269 seconds and 4 git commands to generate.