]> Dogcows Code - chaz/tar/commitdiff
Version 1.20.
authorSergey Poznyakoff <gray@gnu.org.ua>
Mon, 5 May 2008 21:30:57 +0000 (21:30 +0000)
committerSergey Poznyakoff <gray@gnu.org.ua>
Mon, 5 May 2008 21:30:57 +0000 (21:30 +0000)
* configure.ac: Raise version number to 1.20
* src/compare.c (diff_dumpdir): const.
* src/common.h (dumpdir_t,dumpdir_iter_t): New data types.
(dumpdir_create0,dumpdir_create,dumpdir_free,dumpdir_locate)
(dumpdir_first,dumpdir_next): New functions.
* src/incremen.c (dumpdir_create0,dumpdir_create,dumpdir_free)
(dumpdir_first,dumpdir_next): New functions.
(dumpdir_locate): Rewrite using binary search.
(struct directory): Change members char *contents, *icontents to
struct dumpdir *dump, *idump. All references updated.
(note_directory): Last arg is const.
* src/names.c (add_hierarchy_to_namelist): buffer is const.
* tests/incr03.at, tests/incr04.at, tests/rename02.at,
tests/rename03.at: Insert calls to sleep between creation of files
and adding them to the archive.

configure.ac
src/common.h
src/compare.c
src/incremen.c
src/names.c
tests/incr03.at
tests/incr04.at
tests/rename02.at
tests/rename03.at

index fd4b2fad849713a47864bc13844e12f002755dd2..27d2e32372ad42d815e8635ca348e668c9162b79 100644 (file)
@@ -18,7 +18,7 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 
-AC_INIT([GNU tar], [1.19.90], [bug-tar@gnu.org])
+AC_INIT([GNU tar], [1.20], [bug-tar@gnu.org])
 AC_CONFIG_SRCDIR([src/tar.c])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_HEADERS([config.h:config.hin])
index 9e0a3fbd3ba70b88c4ffb51f3ac26b37e1bee4e2..f43673b328978f26bc8ea893ef7c4b94552f3fdc 100644 (file)
@@ -1,7 +1,7 @@
 /* Common declarations for the tar program.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008 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
@@ -489,8 +489,18 @@ bool rename_directory (char *src, char *dst);
 void delete_archive_members (void);
 
 /* Module incremen.c.  */
+typedef struct dumpdir *dumpdir_t;
+typedef struct dumpdir_iter *dumpdir_iter_t;
 
-char *get_directory_contents (char *dir_name, dev_t device);
+dumpdir_t dumpdir_create0 (const char *contents, const char *cmask);
+dumpdir_t dumpdir_create (const char *contents);
+void dumpdir_free (dumpdir_t);
+char *dumpdir_locate (dumpdir_t dump, const char *name);
+char *dumpdir_next (dumpdir_iter_t itr);
+char *dumpdir_first (dumpdir_t dump, int all, dumpdir_iter_t *pitr);
+
+
+const char *get_directory_contents (char *dir_name, dev_t device);
 const char *append_incremental_renames (const char *dump);
 void read_directory_file (void);
 void write_directory_file (void);
index f3723049ed055b3b4ef7d96c5d5c23914b0ab9d8..66205cb7e34fb63416179da0937fd755b3249e85 100644 (file)
@@ -366,7 +366,7 @@ dumpdir_cmp (const char *a, const char *b)
 static void
 diff_dumpdir (void)
 {
-  char *dumpdir_buffer;
+  const char *dumpdir_buffer;
   dev_t dev = 0;
   struct stat stat_data;
 
index d75b844c979b0871c47a13757246a171eb806ac4..372061dd12a3aadb4f51524482e7066107dd6df9 100644 (file)
@@ -1,7 +1,7 @@
 /* GNU dump extensions to tar.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007, 2008 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
@@ -49,14 +49,22 @@ enum children
 #define DIR_SET_FLAG(d,f) (d)->flags |= (f)
 #define DIR_CLEAR_FLAG(d,f) (d)->flags &= ~(f)
 
+struct dumpdir                 /* Dump directory listing */
+{
+  char *contents;              /* Actual contents */
+  size_t total;                /* Total number of elements */
+  size_t elc;                  /* Number of D/N/Y elements. */
+  char **elv;                  /* Array of D/N/Y elements */
+};
+
 /* Directory attributes.  */
 struct directory
   {
     struct timespec mtime;      /* Modification time */
     dev_t device_number;       /* device number for directory */
     ino_t inode_number;                /* inode number for directory */
-    char *contents;             /* Directory contents */
-    char *icontents;            /* Initial contents if the directory was
+    struct dumpdir *dump;       /* Directory contents */
+    struct dumpdir *idump;      /* Initial contents if the directory was
                                   rescanned */
     enum children children;     /* What to save under this directory */
     unsigned flags;             /* See DIRF_ macros above */
@@ -67,6 +75,127 @@ struct directory
     char name[1];              /* file name of directory */
   };
 
+struct dumpdir *
+dumpdir_create0 (const char *contents, const char *cmask)
+{
+  struct dumpdir *dump;
+  size_t i, total, ctsize, len;
+  const char *p;
+  
+  for (i = 0, total = 0, ctsize = 1, p = contents; *p; total++, p += len)
+    {
+      len = strlen (p) + 1;
+      ctsize += len;
+      if (!cmask || strchr (cmask, *p))
+       i++;
+    }
+  dump = xmalloc (sizeof (*dump) + ctsize);
+  dump->contents = (char*)(dump + 1);
+  memcpy (dump->contents, contents, ctsize);
+  dump->total = total;
+  dump->elc = i;
+  dump->elv = xcalloc (i + 1, sizeof (dump->elv[0]));
+
+  for (i = 0, p = dump->contents; *p; p += strlen (p) + 1)
+    {
+      if (!cmask || strchr (cmask, *p))
+       dump->elv[i++] = p + 1;
+    }
+  dump->elv[i] = NULL;
+  return dump;
+}
+
+struct dumpdir *
+dumpdir_create (const char *contents)
+{
+  return dumpdir_create0 (contents, "YND");
+}
+
+void
+dumpdir_free (struct dumpdir *dump)
+{
+  free (dump->elv);
+  free (dump);
+}
+
+static int
+compare_dirnames (const void *first, const void *second)
+{
+  char const *const *name1 = first;
+  char const *const *name2 = second;
+  return strcmp (*name1, *name2);
+}
+
+/* Locate NAME in the dumpdir array DUMP.
+   Return pointer to the slot in DUMP->contents, or NULL if not found */
+char *
+dumpdir_locate (struct dumpdir *dump, const char *name)
+{
+  char **ptr;
+  if (!dump)
+    return NULL;
+
+  ptr = bsearch (&name, dump->elv, dump->elc, sizeof (dump->elv[0]),
+                compare_dirnames);
+  return ptr ? *ptr - 1: NULL;
+}
+
+struct dumpdir_iter
+{
+  struct dumpdir *dump; /* Dumpdir being iterated */
+  int all;              /* Iterate over all entries, not only D/N/Y */ 
+  size_t next;          /* Index of the next element */
+};
+
+char *
+dumpdir_next (struct dumpdir_iter *itr)
+{
+  size_t cur = itr->next;
+  char *ret = NULL;
+  
+  if (itr->all)
+    {
+      ret = itr->dump->contents + cur;
+      if (*ret == 0)
+       return NULL;
+      itr->next += strlen (ret) + 1;
+    }
+  else if (cur < itr->dump->elc)
+    {
+      ret = itr->dump->elv[cur] - 1;
+      itr->next++;
+    }
+
+  return ret;
+}
+
+char *
+dumpdir_first (struct dumpdir *dump, int all, struct dumpdir_iter **pitr)
+{
+  struct dumpdir_iter *itr = xmalloc (sizeof (*itr));
+  itr->dump = dump;
+  itr->all = all;
+  itr->next = 0;
+  *pitr = itr;
+  return dumpdir_next (itr);
+}
+
+/* Return size in bytes of the dumpdir array P */
+size_t
+dumpdir_size (const char *p)
+{
+  size_t totsize = 0;
+
+  while (*p)
+    {
+      size_t size = strlen (p) + 1;
+      totsize += size;
+      p += size;
+    }
+  return totsize + 1;
+}
+
+\f
 static Hash_table *directory_table;
 static Hash_table *directory_meta_table;
 
@@ -120,7 +249,7 @@ make_directory (const char *name)
   size_t namelen = strlen (name);
   size_t size = offsetof (struct directory, name) + namelen + 1;
   struct directory *directory = xmalloc (size);
-  directory->contents = directory->icontents = NULL;
+  directory->dump = directory->idump = NULL;
   directory->orig = NULL;
   directory->flags = false;
   strcpy (directory->name, name);
@@ -136,7 +265,8 @@ make_directory (const char *name)
    found that the directory exists.  */
 static struct directory *
 note_directory (char const *name, struct timespec mtime,
-               dev_t dev, ino_t ino, bool nfs, bool found, char *contents)
+               dev_t dev, ino_t ino, bool nfs, bool found,
+               const char *contents)
 {
   struct directory *directory = make_directory (name);
 
@@ -149,13 +279,9 @@ note_directory (char const *name, struct timespec mtime,
   if (found)
     DIR_SET_FLAG (directory, DIRF_FOUND);
   if (contents)
-    {
-      size_t size = dumpdir_size (contents);
-      directory->contents = xmalloc (size);
-      memcpy (directory->contents, contents, size);
-    }
+    directory->dump = dumpdir_create (contents);
   else
-    directory->contents = NULL;
+    directory->dump = NULL;
 
   if (! ((directory_table
          || (directory_table = hash_initialize (0, 0,
@@ -371,64 +497,15 @@ procdir (char *name_buffer, struct stat *stat_data,
   return directory;
 }
 
-/* Locate NAME in the dumpdir array DUMP.
-   Return pointer to the slot in the array, or NULL if not found */
-const char *
-dumpdir_locate (const char *dump, const char *name)
-{
-  if (dump)
-    while (*dump)
-      {
-       /* Ignore 'R' (rename) and 'X' (tempname) entries, since they break
-          alphabetical ordering.
-          They normally do not occur in dumpdirs from the snapshot files,
-          but this function is also used by purge_directory, which operates
-          on a dumpdir from the archive, hence the need for this test. */
-       if (!strchr ("RX", *dump))
-         {
-           int rc = strcmp (dump + 1, name);
-           if (rc == 0)
-             return dump;
-           if (rc > 1)
-             break;
-         }
-       dump += strlen (dump) + 1;
-      }
-  return NULL;
-}
-
-/* Return size in bytes of the dumpdir array P */
-size_t
-dumpdir_size (const char *p)
-{
-  size_t totsize = 0;
-
-  while (*p)
-    {
-      size_t size = strlen (p) + 1;
-      totsize += size;
-      p += size;
-    }
-  return totsize + 1;
-}
-
-static int
-compare_dirnames (const void *first, const void *second)
-{
-  char const *const *name1 = first;
-  char const *const *name2 = second;
-  return strcmp (*name1, *name2);
-}
-
 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
    build a new dumpdir template.
 
    DIR must be returned by a previous call to savedir().
 
-   File names in DIRECTORY->contents must be sorted
+   File names in DIRECTORY->dump->contents must be sorted
    alphabetically.
 
-   DIRECTORY->contents is replaced with the created template. Each entry is
+   DIRECTORY->dump is replaced with the created template. Each entry is
    prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
 
 void
@@ -440,15 +517,15 @@ makedumpdir (struct directory *directory, const char *dir)
   const char *p;
   char const **array;
   char *new_dump, *new_dump_ptr;
-  const char *dump;
+  struct dumpdir *dump;
 
   if (directory->children == ALL_CHILDREN)
     dump = NULL;
   else if (DIR_IS_RENAMED (directory))
-    dump = directory->orig->icontents ?
-              directory->orig->icontents : directory->orig->contents;
+    dump = directory->orig->idump ?
+           directory->orig->idump : directory->orig->dump;
   else
-    dump = directory->contents;
+    dump = directory->dump;
 
   /* Count the size of DIR and the number of elements it contains */
   dirsize = 0;
@@ -476,11 +553,10 @@ makedumpdir (struct directory *directory, const char *dir)
        {
          if (directory->tagfile)
            *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
-                              ' ' : 'I';
+                               ' ' : 'I';
          else
            *new_dump_ptr = ' ';
          new_dump_ptr++;
-         dump = loc + strlen (loc) + 1;
        }
       else if (directory->tagfile)
        *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
@@ -493,13 +569,13 @@ makedumpdir (struct directory *directory, const char *dir)
        ;
     }
   *new_dump_ptr = 0;
-  directory->icontents = directory->contents;
-  directory->contents = new_dump;
+  directory->idump = directory->dump;
+  directory->dump = dumpdir_create0 (new_dump, NULL);
   free (array);
 }
 
 /* Recursively scan the given directory. */
-static char *
+static const char *
 scan_directory (char *dir, dev_t device)
 {
   char *dirp = savedir (dir);  /* for scanning directory */
@@ -535,15 +611,17 @@ scan_directory (char *dir, dev_t device)
 
   if (dirp && directory->children != NO_CHILDREN)
     {
-      char  *entry;    /* directory entry being scanned */
+      char *entry;     /* directory entry being scanned */
       size_t entrylen; /* length of directory entry */
+      dumpdir_iter_t itr;
 
       makedumpdir (directory, dirp);
 
-      for (entry = directory->contents;
-          (entrylen = strlen (entry)) != 0;
-          entry += entrylen + 1)
+      for (entry = dumpdir_first (directory->dump, 1, &itr);
+          entry;
+          entry = dumpdir_next (itr))
        {
+         entrylen = strlen (entry);
          if (name_buffer_size <= entrylen - 1 + name_length)
            {
              do
@@ -590,16 +668,17 @@ scan_directory (char *dir, dev_t device)
                *entry = 'Y';
            }
        }
+      free (itr);
     }
 
   free (name_buffer);
   if (dirp)
     free (dirp);
 
-  return directory->contents;
+  return directory->dump ? directory->dump->contents : NULL;
 }
 
-char *
+const char *
 get_directory_contents (char *dir, dev_t device)
 {
   return scan_directory (dir, device);
@@ -1171,14 +1250,16 @@ write_directory_file_entry (void *entry, void *data)
       fwrite (s, strlen (s) + 1, 1, fp);
 
       fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
-      if (directory->contents)
+      if (directory->dump)
        {
-         char *p;
-         for (p = directory->contents; *p; p += strlen (p) + 1)
-           {
-             if (strchr ("YND", *p))
-               fwrite (p, strlen (p) + 1, 1, fp);
-           }
+         const char *p;
+         dumpdir_iter_t itr;
+
+         for (p = dumpdir_first (directory->dump, 0, &itr);
+              p;
+              p = dumpdir_next (itr))
+           fwrite (p, strlen (p) + 1, 1, fp);
+         free (itr);
        }
       fwrite ("\0\0", 2, 1, fp);
     }
@@ -1366,6 +1447,7 @@ try_purge_directory (char const *directory_name)
   char *current_dir;
   char *cur, *arc, *p;
   char *temp_stub = NULL;
+  struct dumpdir *dump;
 
   if (!is_dumpdir (&current_stat_info))
     return false;
@@ -1442,6 +1524,7 @@ try_purge_directory (char const *directory_name)
   free (temp_stub);
 
   /* Process deletes */
+  dump = dumpdir_create (current_stat_info.dumpdir);
   p = NULL;
   for (cur = current_dir; *cur; cur += strlen (cur) + 1)
     {
@@ -1463,7 +1546,7 @@ try_purge_directory (char const *directory_name)
          continue;
        }
 
-      if (!(entry = dumpdir_locate (current_stat_info.dumpdir, cur))
+      if (!(entry = dumpdir_locate (dump, cur))
          || (*entry == 'D' && !S_ISDIR (st.st_mode))
          || (*entry == 'Y' && S_ISDIR (st.st_mode)))
        {
@@ -1489,7 +1572,8 @@ try_purge_directory (char const *directory_name)
        }
     }
   free (p);
-
+  dumpdir_free (dump);
+  
   free (current_dir);
   return true;
 }
index 585ad39ba7238ff6e7583a6afe89c08c6da35923..73b8741858e70335c0d99c211919143cf78b1cff 100644 (file)
@@ -734,7 +734,7 @@ static void
 add_hierarchy_to_namelist (struct name *name, dev_t device)
 {
   char *file_name = name->name;
-  char *buffer = get_directory_contents (file_name, device);
+  const char *buffer = get_directory_contents (file_name, device);
 
   if (! buffer)
     name->dir_contents = "\0\0\0\0";
@@ -746,7 +746,7 @@ add_hierarchy_to_namelist (struct name *name, dev_t device)
                                 : NAME_FIELD_SIZE);
       char *namebuf = xmalloc (allocated_length + 1);
                                /* FIXME: + 2 above?  */
-      char *string;
+      const char *string;
       size_t string_length;
       int change_dir = name->change_dir;
 
index 50b440fb78072669ed974e5e1f415e25bcaf2db6..08421bbcfcf68744444974a2ace7216f29b52245 100644 (file)
@@ -34,6 +34,8 @@ mkdir directory
 genfile --file=directory/x
 genfile --file=directory/y
 
+sleep 1
+
 tar -cf archive.1 -g db directory
 
 mv directory/x directory/z
index 279d3bbc8d7ff05f2c390ae290988d878fb8da31..885b0ef6894b1e019ef76a27849b0d53edbb0e22 100644 (file)
@@ -38,6 +38,8 @@ awk 'BEGIN {
     printf("NAME_PREFIX[%03d]\n", i);
   }' < /dev/null | genfile --files-from -
 
+sleep 1
+
 echo "Initial dump"
 tar cvf a0.tar -g a.sna a
 mv a/b a/c
index 7feada03944653caaab424c5c00a659989546b63..2c8ca0d555f33608b301d90d671123ae442e4920 100644 (file)
@@ -34,6 +34,8 @@ genfile --file foo/bar/file.r
 mkdir foo/bar/baz
 genfile --file foo/bar/baz/file.z
 
+sleep 1
+
 echo "Creating base archive"
 tar -g incr -cf arch.1 -v foo
 
index bbddea36304d763ad249219c5974d1acc6bb1941..d08c9fc86ac1c83c8cf2f229a4cd3924a75d27ca 100644 (file)
@@ -39,6 +39,8 @@ genfile --file foo/b/fileb
 mkdir foo/c
 genfile --file foo/c/filec
 
+sleep 1
+
 echo "First dump"
 echo "First dump">&2
 tar -g incr -cf arch.1 -v foo 2>tmperr
This page took 0.040583 seconds and 4 git commands to generate.