]> Dogcows Code - chaz/tar/blobdiff - src/incremen.c
Rewrite update algorithm.
[chaz/tar] / src / incremen.c
index 564121796d7b2e8023c44580373e44c4f982fb63..59be617b0d7c0dfe3bbb1d3d08ebd1853d2f20db 100644 (file)
@@ -290,24 +290,6 @@ attach_directory (const char *name)
 }
                 
 \f
-static void
-replace_prefix (char **pname, const char *samp, size_t slen,
-               const char *repl, size_t rlen)
-{
-  char *name = *pname;
-  size_t nlen = strlen (name);
-  if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
-    {
-      if (rlen > slen)
-       {
-         name = xrealloc (name, nlen - slen + rlen + 1);
-         *pname = name;
-       }
-      memmove (name + rlen, name + slen, nlen - slen + 1);
-      memcpy (name, repl, rlen);
-    }
-}
-
 void
 dirlist_replace_prefix (const char *pref, const char *repl)
 {
@@ -389,28 +371,15 @@ remove_directory (const char *caname)
 }
 #endif
 
-/* Find a directory entry for NAME.  If first OLD_PREFIX_LEN
-   bytes of its name match OLD_PREFIX, replace them with
-   NEW_PREFIX. */
+/* If first OLD_PREFIX_LEN bytes of DIR->NAME name match OLD_PREFIX,
+   replace them with NEW_PREFIX. */
 void
-rebase_directory (const char *name, size_t old_prefix_len,
-                 const char *old_prefix,
-                 const char *new_prefix)
+rebase_directory (struct directory *dir,
+                 const char *old_prefix, size_t old_prefix_len,
+                 const char *new_prefix, size_t new_prefix_len)
 {
-  struct directory *dir = find_directory (name);
-  if (dir)
-    {
-      size_t len = strlen (dir->name);
-      if (len > old_prefix_len
-         && memcmp (dir->name, old_prefix, old_prefix_len) == 0)
-       {
-         char *newp = xmalloc (len - old_prefix_len + strlen (new_prefix));
-         strcpy (newp, new_prefix);
-         strcat (newp, dir->name + old_prefix_len);
-         free (dir->name);
-         dir->name = newp;
-       }
-    }
+  replace_prefix (&dir->name, old_prefix, old_prefix_len,
+                 new_prefix, new_prefix_len);
 }
 
 /* Return a directory entry for a given combination of device and inode
@@ -444,7 +413,11 @@ update_parent_directory (const char *name)
     {
       struct stat st;
       if (deref_stat (dereference_option, p, &st) != 0)
-       stat_diag (name);
+       {
+         if (errno != ENOENT) 
+           stat_diag (directory->name);
+         /* else: should have been already reported */
+       }
       else
        directory->mtime = get_stat_mtime (&st);
     }
@@ -580,6 +553,12 @@ procdir (const char *name_buffer, struct stat *stat_data,
   if (one_file_system_option && device != stat_data->st_dev
       /* ... except if it was explicitely given in the command line */
       && !is_individual_file (name_buffer))
+    /* FIXME: 
+       WARNOPT (WARN_XDEV,
+                (0, 0,
+                 _("%s: directory is on a different filesystem; not dumped"),
+                 quotearg_colon (directory->name)));
+    */
     directory->children = NO_CHILDREN;
   else if (flag & PD_FORCE_CHILDREN)
     {
@@ -706,14 +685,15 @@ makedumpdir (struct directory *directory, const char *dir)
 /* Recursively scan the given directory DIR.
    DEVICE is the device number where DIR resides (for --one-file-system).
    If CMDLINE is true, the directory name was explicitly listed in the
-   command line. */
-const char *
+   command line.
+   Unless *PDIR is NULL, store there a pointer to the struct directory
+   describing DIR. */
+struct directory *
 scan_directory (char *dir, dev_t device, bool cmdline)
 {
   char *dirp = savedir (dir);  /* for scanning directory */
-  char *name_buffer;           /* directory, `/', and directory member */
-  size_t name_buffer_size;     /* allocated size of name_buffer, minus 2 */
-  size_t name_length;          /* used length in name_buffer */
+  namebuf_t nbuf;
+  char *tmp;
   struct stat stat_data;
   struct directory *directory;
   char ch;
@@ -721,38 +701,28 @@ scan_directory (char *dir, dev_t device, bool cmdline)
   if (! dirp)
     savedir_error (dir);
 
-  name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
-  name_buffer = xmalloc (name_buffer_size + 2);
-  strcpy (name_buffer, dir);
-  zap_slashes (name_buffer);
+  tmp = xstrdup (dir);
+  zap_slashes (tmp);
   
-  if (deref_stat (dereference_option, name_buffer, &stat_data))
+  if (deref_stat (dereference_option, tmp, &stat_data))
     {
-      stat_diag (name_buffer);
-      /* FIXME: used to be
-           children = CHANGED_CHILDREN;
-        but changed to: */
-      free (name_buffer);
+      dir_removed_diag (tmp, cmdline, stat_diag);
+      free (tmp);
       free (dirp);
       return NULL;
     }
 
-  directory = procdir (name_buffer, &stat_data, device,
+  directory = procdir (tmp, &stat_data, device,
                       (cmdline ? PD_FORCE_INIT : 0),
                       &ch);
-      
-  name_length = strlen (name_buffer); 
-  if (! ISSLASH (name_buffer[name_length - 1]))
-    {
-      name_buffer[name_length] = DIRECTORY_SEPARATOR;
-      /* name_buffer has been allocated an extra slot */
-      name_buffer[++name_length] = 0;
-    }
+  
+  free (tmp);
+
+  nbuf = namebuf_create (dir);
 
   if (dirp && directory->children != NO_CHILDREN)
     {
       char *entry;     /* directory entry being scanned */
-      size_t entrylen; /* length of directory entry */
       dumpdir_iter_t itr;
 
       makedumpdir (directory, dirp);
@@ -761,25 +731,17 @@ scan_directory (char *dir, dev_t device, bool cmdline)
           entry;
           entry = dumpdir_next (itr))
        {
-         entrylen = strlen (entry);
-         if (name_buffer_size <= entrylen - 1 + name_length)
-           {
-             do
-               name_buffer_size += NAME_FIELD_SIZE;
-             while (name_buffer_size <= entrylen - 1 + name_length);
-             name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
-           }
-         strcpy (name_buffer + name_length, entry + 1);
+         char *full_name = namebuf_name (nbuf, entry + 1);
 
          if (*entry == 'I') /* Ignored entry */
            *entry = 'N';
-         else if (excluded_name (name_buffer))
+         else if (excluded_name (full_name))
            *entry = 'N';
          else
            {
-             if (deref_stat (dereference_option, name_buffer, &stat_data))
+             if (deref_stat (dereference_option, full_name, &stat_data))
                {
-                 stat_diag (name_buffer);
+                 file_removed_diag (full_name, false, stat_diag);
                  *entry = 'N';
                  continue;
                }
@@ -792,7 +754,7 @@ scan_directory (char *dir, dev_t device, bool cmdline)
                  else if (directory->children == ALL_CHILDREN)
                    pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
                  *entry = 'D';
-                 procdir (name_buffer, &stat_data, device, pd_flag, entry);
+                 procdir (full_name, &stat_data, device, pd_flag, entry);
                }
 
              else if (one_file_system_option && device != stat_data.st_dev)
@@ -814,17 +776,35 @@ scan_directory (char *dir, dev_t device, bool cmdline)
       free (itr);
     }
 
-  free (name_buffer);
+  namebuf_free (nbuf);
+
   if (dirp)
     free (dirp);
 
-  return directory->dump ? directory->dump->contents : NULL;
+  return directory;
+}
+
+/* Return pointer to the contents of the directory DIR */
+const char *
+directory_contents (struct directory *dir)
+{
+  if (!dir)
+    return NULL;
+  return dir->dump ? dir->dump->contents : NULL;
 }
 
+/* A "safe" version of directory_contents, which never returns NULL. */
 const char *
-get_directory_contents (char *dir, dev_t device, bool force)
+safe_directory_contents (struct directory *dir)
 {
-  return scan_directory (dir, device, force);
+  const char *ret = directory_contents (dir);
+  return ret ? ret : "\0\0\0\0";
+}
+
+void
+name_fill_directory (struct name *name, dev_t device, bool cmdline)
+{
+  name->directory = scan_directory (name->name, device, cmdline);
 }
 
 \f
@@ -887,17 +867,19 @@ store_rename (struct directory *dir, struct obstack *stk)
     }
 }
 
-const char *
-append_incremental_renames (const char *dump)
+void
+append_incremental_renames (struct directory *dir)
 {
   struct obstack stk;
   size_t size;
   struct directory *dp;
+  const char *dump;
   
   if (dirhead == NULL)
-    return dump;
+    return;
 
   obstack_init (&stk);
+  dump = directory_contents (dir);
   if (dump)
     {
       size = dumpdir_size (dump) - 1;
@@ -912,11 +894,10 @@ append_incremental_renames (const char *dump)
   if (obstack_object_size (&stk) != size)
     {
       obstack_1grow (&stk, 0);
-      dump = obstack_finish (&stk);
+      dumpdir_free (dir->dump);
+      dir->dump = dumpdir_create (obstack_finish (&stk));
     }
-  else
-    obstack_free (&stk, NULL);
-  return dump;
+  obstack_free (&stk, NULL);
 }
 
 \f
@@ -1325,6 +1306,13 @@ read_directory_file (void)
       return;
     }
 
+  /* Consume the first name from the name list and reset the
+     list afterwards.  This is done to change to the new
+     directory, if the first name is a chdir request (-C dir),
+     which is necessary to recreate absolute file names. */
+  name_from_list ();
+  blank_name_list ();
+  
   if (0 < getline (&buf, &bufsize, listed_incremental_stream))
     {
       char *ebuf;
This page took 0.027108 seconds and 4 git commands to generate.