]> Dogcows Code - chaz/tar/blobdiff - src/incremen.c
Implement the --show-snapshot-field-ranges option
[chaz/tar] / src / incremen.c
index 1d20c4465cab872f08816aa6d463bda41b81f61c..07e757adfa4f97a9313cceb9b4f31ea376d735bf 100644 (file)
@@ -609,6 +609,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st,
          exclusion_tag_warning (name_buffer, tag_file_name,
                                 _("contents not dumped"));
          directory->children = NO_CHILDREN;
+         directory->tagfile = tag_file_name;
          break;
 
        case exclusion_tag_under:
@@ -680,15 +681,13 @@ makedumpdir (struct directory *directory, const char *dir)
       if (loc)
        {
          if (directory->tagfile)
-           *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
-                               ' ' : 'I';
+           *new_dump_ptr = 'I';
          else
            *new_dump_ptr = ' ';
          new_dump_ptr++;
        }
       else if (directory->tagfile)
-       *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
-                              ' ' : 'I';
+       *new_dump_ptr++ = 'I';
       else
        *new_dump_ptr++ = 'Y'; /* New entry */
 
@@ -699,9 +698,26 @@ makedumpdir (struct directory *directory, const char *dir)
   *new_dump_ptr = 0;
   directory->idump = directory->dump;
   directory->dump = dumpdir_create0 (new_dump, NULL);
+  free (new_dump);
   free (array);
 }
 
+/* Create a dumpdir containing only one entry: that for the
+   tagfile. */
+static void
+maketagdumpdir (struct directory *directory)
+{
+  size_t len = strlen (directory->tagfile) + 1;
+  char *new_dump = xmalloc (len + 2);
+  new_dump[0] = 'Y';
+  memcpy (new_dump + 1, directory->tagfile, len);
+  new_dump[len + 1] = 0;
+
+  directory->idump = directory->dump;
+  directory->dump = dumpdir_create0 (new_dump, NULL);
+  free (new_dump);
+}
+
 /* Recursively scan the directory identified by ST.  */
 struct directory *
 scan_directory (struct tar_stat_info *st)
@@ -729,86 +745,94 @@ scan_directory (struct tar_stat_info *st)
 
   nbuf = namebuf_create (dir);
 
-  if (dirp && directory->children != NO_CHILDREN)
+  if (dirp)
     {
-      char *entry;     /* directory entry being scanned */
-      struct dumpdir_iter *itr;
-
-      makedumpdir (directory, dirp);
-
-      for (entry = dumpdir_first (directory->dump, 1, &itr);
-          entry;
-          entry = dumpdir_next (itr))
+      if (directory->children != NO_CHILDREN)
        {
-         char *full_name = namebuf_name (nbuf, entry + 1);
+         char *entry;  /* directory entry being scanned */
+         struct dumpdir_iter *itr;
 
-         if (*entry == 'I') /* Ignored entry */
-           *entry = 'N';
-         else if (excluded_name (full_name))
-           *entry = 'N';
-         else
-           {
-             int fd = st->fd;
-             void (*diag) (char const *) = 0;
-             struct tar_stat_info stsub;
-             tar_stat_init (&stsub);
+         makedumpdir (directory, dirp);
 
-             if (fd < 0)
-               {
-                 errno = - fd;
-                 diag = open_diag;
-               }
-             else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0)
-               diag = stat_diag;
-             else if (S_ISDIR (stsub.stat.st_mode))
-               {
-                 int subfd = subfile_open (st, entry + 1, open_read_flags);
-                 if (subfd < 0)
-                   diag = open_diag;
-                 else
-                   {
-                     stsub.fd = subfd;
-                     if (fstat (subfd, &stsub.stat) != 0)
-                       diag = stat_diag;
-                   }
-               }
-
-             if (diag)
-               {
-                 file_removed_diag (full_name, false, diag);
-                 *entry = 'N';
-               }
-             else if (S_ISDIR (stsub.stat.st_mode))
-               {
-                 int pd_flag = 0;
-                 if (!recursion_option)
-                   pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
-                 else if (directory->children == ALL_CHILDREN)
-                   pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
-                 *entry = 'D';
-
-                 stsub.parent = st;
-                 procdir (full_name, &stsub, pd_flag, entry);
-                 restore_parent_fd (&stsub);
-               }
-             else if (one_file_system_option && device != stsub.stat.st_dev)
+         for (entry = dumpdir_first (directory->dump, 1, &itr);
+              entry;
+              entry = dumpdir_next (itr))
+           {
+             char *full_name = namebuf_name (nbuf, entry + 1);
+             
+             if (*entry == 'I') /* Ignored entry */
                *entry = 'N';
-             else if (*entry == 'Y')
-               /* New entry, skip further checks */;
-             /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
-             else if (OLDER_STAT_TIME (stsub.stat, m)
-                      && (!after_date_option
-                          || OLDER_STAT_TIME (stsub.stat, c)))
+             else if (excluded_name (full_name))
                *entry = 'N';
              else
-               *entry = 'Y';
+               {
+                 int fd = st->fd;
+                 void (*diag) (char const *) = 0;
+                 struct tar_stat_info stsub;
+                 tar_stat_init (&stsub);
 
-             tar_stat_destroy (&stsub);
+                 if (fd < 0)
+                   {
+                     errno = - fd;
+                     diag = open_diag;
+                   }
+                 else if (fstatat (fd, entry + 1, &stsub.stat,
+                                   fstatat_flags) != 0)
+                   diag = stat_diag;
+                 else if (S_ISDIR (stsub.stat.st_mode))
+                   {
+                     int subfd = subfile_open (st, entry + 1,
+                                               open_read_flags);
+                     if (subfd < 0)
+                       diag = open_diag;
+                     else
+                       {
+                         stsub.fd = subfd;
+                         if (fstat (subfd, &stsub.stat) != 0)
+                           diag = stat_diag;
+                       }
+                   }
+                 
+                 if (diag)
+                   {
+                     file_removed_diag (full_name, false, diag);
+                     *entry = 'N';
+                   }
+                 else if (S_ISDIR (stsub.stat.st_mode))
+                   {
+                     int pd_flag = 0;
+                     if (!recursion_option)
+                       pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
+                     else if (directory->children == ALL_CHILDREN)
+                       pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
+                     *entry = 'D';
+                     
+                     stsub.parent = st;
+                     procdir (full_name, &stsub, pd_flag, entry);
+                     restore_parent_fd (&stsub);
+                   }
+                 else if (one_file_system_option &&
+                          device != stsub.stat.st_dev)
+                   *entry = 'N';
+                 else if (*entry == 'Y')
+                   /* New entry, skip further checks */;
+                 /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
+                 else if (OLDER_STAT_TIME (stsub.stat, m)
+                          && (!after_date_option
+                              || OLDER_STAT_TIME (stsub.stat, c)))
+                   *entry = 'N';
+                 else
+                   *entry = 'Y';
+                 
+                 tar_stat_destroy (&stsub);
+               }
            }
+         free (itr);
        }
-      free (itr);
+      else if (directory->tagfile)
+       maketagdumpdir (directory);
     }
-
+  
   namebuf_free (nbuf);
 
   free (dirp);
@@ -1244,6 +1268,51 @@ read_incr_db_2 (void)
                _("Unexpected EOF in snapshot file")));
 }
 
+/* Display (to stdout) the range of allowed values for each field
+   in the snapshot file.  The array below should be kept in sync
+   with any changes made to the read_num() calls in the parsing
+   loop inside read_incr_db_2().
+
+   (This function is invoked via the --show-snapshot-field-ranges
+   command line option.) */
+
+struct field_range
+{
+  char const *fieldname;
+  intmax_t min_val;
+  uintmax_t max_val;
+};
+
+static struct field_range const field_ranges[] = {
+  { "nfs", 0, 1 },
+  { "timestamp_sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t) },
+  { "timestamp_nsec", 0, BILLION - 1 },
+  { "dev", TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t) },
+  { "ino", TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t) },
+  { NULL, 0, 0 }
+};
+
+void
+show_snapshot_field_ranges (void)
+{
+  struct field_range const *p;
+  char minbuf[max (SYSINT_BUFSIZE, INT_BUFSIZE_BOUND (intmax_t))];
+  char maxbuf[max (SYSINT_BUFSIZE, INT_BUFSIZE_BOUND (uintmax_t))];
+
+  printf("This tar's snapshot file field ranges are\n");
+  printf ("   (%-15s => [ %s, %s ]):\n\n", "field name", "min", "max");
+
+  for (p=field_ranges; p->fieldname != NULL; p++)
+    {
+      printf ("    %-15s => [ %s, %s ],\n", p->fieldname,
+             sysinttostr (p->min_val, p->min_val, p->max_val, minbuf),
+             sysinttostr (p->max_val, p->min_val, p->max_val, maxbuf));
+
+    }
+
+  printf("\n");
+}
+
 /* Read incremental snapshot file (directory file).
    If the file has older incremental version, make sure that it is processed
    correctly and that tar will use the most conservative backup method among
@@ -1558,7 +1627,7 @@ try_purge_directory (char const *directory_name)
   if (!is_dumpdir (&current_stat_info))
     return false;
 
-  current_dir = savedir (directory_name);
+  current_dir = tar_savedir (directory_name, 0);
 
   if (!current_dir)
     /* The directory doesn't exist now.  It'll be created.  In any
This page took 0.025715 seconds and 4 git commands to generate.