]> Dogcows Code - chaz/tar/blobdiff - src/incremen.c
(main): Reword the "delayed error" message. New wording proposed by Karl Berry.
[chaz/tar] / src / incremen.c
index 59215e5e2f393b8d459192facc8e7e725089a935..372061dd12a3aadb4f51524482e7066107dd6df9 100644 (file)
@@ -1,11 +1,11 @@
 /* GNU dump extensions to tar.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
 /* 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
 
    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 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -18,7 +18,6 @@
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include <system.h>
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include <system.h>
-#include <getline.h>
 #include <hash.h>
 #include <quotearg.h>
 #include "common.h"
 #include <hash.h>
 #include <quotearg.h>
 #include "common.h"
@@ -50,22 +49,153 @@ enum children
 #define DIR_SET_FLAG(d,f) (d)->flags |= (f)
 #define DIR_CLEAR_FLAG(d,f) (d)->flags &= ~(f)
 
 #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 */
 /* 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 */
     struct directory *orig;     /* If the directory was renamed, points to
                                   the original directory structure */
                                   rescanned */
     enum children children;     /* What to save under this directory */
     unsigned flags;             /* See DIRF_ macros above */
     struct directory *orig;     /* If the directory was renamed, points to
                                   the original directory structure */
+    const char *tagfile;        /* Tag file, if the directory falls under
+                                  exclusion_tag_under */
     char name[1];              /* file name of 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;
 
 static Hash_table *directory_table;
 static Hash_table *directory_meta_table;
 
@@ -119,12 +249,13 @@ make_directory (const char *name)
   size_t namelen = strlen (name);
   size_t size = offsetof (struct directory, name) + namelen + 1;
   struct directory *directory = xmalloc (size);
   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);
   directory->orig = NULL;
   directory->flags = false;
   strcpy (directory->name, name);
-  if (ISSLASH (directory->name[namelen-1]))
-    directory->name[namelen-1] = 0;
+  if (namelen && ISSLASH (directory->name[namelen - 1]))
+    directory->name[namelen - 1] = 0;
+  directory->tagfile = NULL;
   return directory;
 }
 
   return directory;
 }
 
@@ -134,7 +265,8 @@ make_directory (const char *name)
    found that the directory exists.  */
 static struct directory *
 note_directory (char const *name, struct timespec mtime,
    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);
 
 {
   struct directory *directory = make_directory (name);
 
@@ -147,13 +279,9 @@ note_directory (char const *name, struct timespec mtime,
   if (found)
     DIR_SET_FLAG (directory, DIRF_FOUND);
   if (contents)
   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
   else
-    directory->contents = NULL;
+    directory->dump = NULL;
 
   if (! ((directory_table
          || (directory_table = hash_initialize (0, 0,
 
   if (! ((directory_table
          || (directory_table = hash_initialize (0, 0,
@@ -230,7 +358,8 @@ static struct directory *
 procdir (char *name_buffer, struct stat *stat_data,
         dev_t device,
         enum children children,
 procdir (char *name_buffer, struct stat *stat_data,
         dev_t device,
         enum children children,
-        bool verbose)
+        bool verbose,
+        char *entry)
 {
   struct directory *directory;
   bool nfs = NFS_FILE_STAT (*stat_data);
 {
   struct directory *directory;
   bool nfs = NFS_FILE_STAT (*stat_data);
@@ -247,7 +376,8 @@ procdir (char *name_buffer, struct stat *stat_data,
         directories, consider all NFS devices as equal,
         relying on the i-node to establish differences.  */
 
         directories, consider all NFS devices as equal,
         relying on the i-node to establish differences.  */
 
-      if (! (((DIR_IS_NFS (directory) & nfs)
+      if (! ((!check_device_option
+             || (DIR_IS_NFS (directory) && nfs)
              || directory->device_number == stat_data->st_dev)
             && directory->inode_number == stat_data->st_ino))
        {
              || directory->device_number == stat_data->st_dev)
             && directory->inode_number == stat_data->st_ino))
        {
@@ -331,56 +461,40 @@ procdir (char *name_buffer, struct stat *stat_data,
 
   DIR_SET_FLAG (directory, DIRF_INIT);
 
 
   DIR_SET_FLAG (directory, DIRF_INIT);
 
-  return directory;
-}
+  {
+    const char *tag_file_name;
 
 
-/* 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)
+    switch (check_exclusion_tags (name_buffer, &tag_file_name))
       {
       {
-       /* 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;
-}
+      case exclusion_tag_all:
+       /* This warning can be duplicated by code in dump_file0, but only
+          in case when the topmost directory being archived contains
+          an exclusion tag. */
+       exclusion_tag_warning (name_buffer, tag_file_name,
+                              _("directory not dumped"));
+       if (entry)
+         *entry = 'N';
+       directory->children = NO_CHILDREN;
+       break;
 
 
-/* Return size in bytes of the dumpdir array P */
-size_t
-dumpdir_size (const char *p)
-{
-  size_t totsize = 0;
+      case exclusion_tag_contents:
+       exclusion_tag_warning (name_buffer, tag_file_name,
+                              _("contents not dumped"));
+       directory->children = NO_CHILDREN;
+       break;
 
 
-  while (*p)
-    {
-      size_t size = strlen (p) + 1;
-      totsize += size;
-      p += size;
-    }
-  return totsize + 1;
-}
+      case exclusion_tag_under:
+       exclusion_tag_warning (name_buffer, tag_file_name,
+                              _("contents not dumped"));
+       directory->tagfile = tag_file_name;
+       break;
 
 
-static int
-compare_dirnames (const void *first, const void *second)
-{
-  char const *const *name1 = first;
-  char const *const *name2 = second;
-  return strcmp (*name1, *name2);
+      case exclusion_tag_none:
+       break;
+      }
+  }
+
+  return directory;
 }
 
 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
 }
 
 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
@@ -388,10 +502,10 @@ compare_dirnames (const void *first, const void *second)
 
    DIR must be returned by a previous call to savedir().
 
 
    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.
 
    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
    prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
 
 void
@@ -403,15 +517,15 @@ makedumpdir (struct directory *directory, const char *dir)
   const char *p;
   char const **array;
   char *new_dump, *new_dump_ptr;
   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))
 
   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
   else
-    dump = directory->contents;
+    dump = directory->dump;
 
   /* Count the size of DIR and the number of elements it contains */
   dirsize = 0;
 
   /* Count the size of DIR and the number of elements it contains */
   dirsize = 0;
@@ -437,9 +551,16 @@ makedumpdir (struct directory *directory, const char *dir)
       const char *loc = dumpdir_locate (dump, array[i]);
       if (loc)
        {
       const char *loc = dumpdir_locate (dump, array[i]);
       if (loc)
        {
-         *new_dump_ptr++ = ' ';
-         dump = loc + strlen (loc) + 1;
+         if (directory->tagfile)
+           *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
+                               ' ' : 'I';
+         else
+           *new_dump_ptr = ' ';
+         new_dump_ptr++;
        }
        }
+      else if (directory->tagfile)
+       *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
+                              ' ' : 'I';
       else
        *new_dump_ptr++ = 'Y'; /* New entry */
 
       else
        *new_dump_ptr++ = 'Y'; /* New entry */
 
@@ -448,16 +569,16 @@ makedumpdir (struct directory *directory, const char *dir)
        ;
     }
   *new_dump_ptr = 0;
        ;
     }
   *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. */
   free (array);
 }
 
 /* Recursively scan the given directory. */
-static char *
-scan_directory (char *dir_name, dev_t device)
+static const char *
+scan_directory (char *dir, dev_t device)
 {
 {
-  char *dirp = savedir (dir_name);     /* for scanning directory */
+  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 */
   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 */
@@ -465,12 +586,12 @@ scan_directory (char *dir_name, dev_t device)
   struct directory *directory;
 
   if (! dirp)
   struct directory *directory;
 
   if (! dirp)
-    savedir_error (dir_name);
+    savedir_error (dir);
 
 
-  name_buffer_size = strlen (dir_name) + NAME_FIELD_SIZE;
+  name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
   name_buffer = xmalloc (name_buffer_size + 2);
   name_buffer = xmalloc (name_buffer_size + 2);
-  strcpy (name_buffer, dir_name);
-  if (! ISSLASH (dir_name[strlen (dir_name) - 1]))
+  strcpy (name_buffer, dir);
+  if (! ISSLASH (dir[strlen (dir) - 1]))
     strcat (name_buffer, "/");
   name_length = strlen (name_buffer);
 
     strcat (name_buffer, "/");
   name_length = strlen (name_buffer);
 
@@ -485,19 +606,22 @@ scan_directory (char *dir_name, dev_t device)
       return NULL;
     }
 
       return NULL;
     }
 
-  directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false);
+  directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false,
+                      NULL);
 
   if (dirp && directory->children != NO_CHILDREN)
     {
 
   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 */
       size_t entrylen; /* length of directory entry */
+      dumpdir_iter_t itr;
 
       makedumpdir (directory, dirp);
 
 
       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
          if (name_buffer_size <= entrylen - 1 + name_length)
            {
              do
@@ -507,7 +631,9 @@ scan_directory (char *dir_name, dev_t device)
            }
          strcpy (name_buffer + name_length, entry + 1);
 
            }
          strcpy (name_buffer + name_length, entry + 1);
 
-         if (excluded_name (name_buffer))
+         if (*entry == 'I') /* Ignored entry */
+           *entry = 'N';
+         else if (excluded_name (name_buffer))
            *entry = 'N';
          else
            {
            *entry = 'N';
          else
            {
@@ -520,10 +646,10 @@ scan_directory (char *dir_name, dev_t device)
 
              if (S_ISDIR (stat_data.st_mode))
                {
 
              if (S_ISDIR (stat_data.st_mode))
                {
+                 *entry = 'D';
                  procdir (name_buffer, &stat_data, device,
                           directory->children,
                  procdir (name_buffer, &stat_data, device,
                           directory->children,
-                          verbose_option);
-                 *entry = 'D';
+                          verbose_option, entry);
                }
 
              else if (one_file_system_option && device != stat_data.st_dev)
                }
 
              else if (one_file_system_option && device != stat_data.st_dev)
@@ -542,29 +668,37 @@ scan_directory (char *dir_name, dev_t device)
                *entry = 'Y';
            }
        }
                *entry = 'Y';
            }
        }
+      free (itr);
     }
 
   free (name_buffer);
   if (dirp)
     free (dirp);
 
     }
 
   free (name_buffer);
   if (dirp)
     free (dirp);
 
-  return directory->contents;
+  return directory->dump ? directory->dump->contents : NULL;
 }
 
 }
 
-char *
-get_directory_contents (char *dir_name, dev_t device)
+const char *
+get_directory_contents (char *dir, dev_t device)
 {
 {
-  return scan_directory (dir_name, device);
+  return scan_directory (dir, device);
 }
 
 \f
 static void
 obstack_code_rename (struct obstack *stk, char *from, char *to)
 {
 }
 
 \f
 static void
 obstack_code_rename (struct obstack *stk, char *from, char *to)
 {
+  char *s;
+
+  s = from[0] == 0 ? from :
+                     safer_name_suffix (from, false, absolute_names_option);
   obstack_1grow (stk, 'R');
   obstack_1grow (stk, 'R');
-  obstack_grow (stk, from, strlen (from) + 1);
+  obstack_grow (stk, s, strlen (s) + 1);
+
+  s = to[0] == 0 ? to:
+                   safer_name_suffix (to, false, absolute_names_option);
   obstack_1grow (stk, 'T');
   obstack_1grow (stk, 'T');
-  obstack_grow (stk, to, strlen (to) + 1);
+  obstack_grow (stk, s, strlen (s) + 1);
 }
 
 static bool
 }
 
 static bool
@@ -1116,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);
       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);
     }
        }
       fwrite ("\0\0", 2, 1, fp);
     }
@@ -1311,6 +1447,7 @@ try_purge_directory (char const *directory_name)
   char *current_dir;
   char *cur, *arc, *p;
   char *temp_stub = NULL;
   char *current_dir;
   char *cur, *arc, *p;
   char *temp_stub = NULL;
+  struct dumpdir *dump;
 
   if (!is_dumpdir (&current_stat_info))
     return false;
 
   if (!is_dumpdir (&current_stat_info))
     return false;
@@ -1355,6 +1492,19 @@ try_purge_directory (char const *directory_name)
          arc += strlen (arc) + 1;
          dst = arc + 1;
 
          arc += strlen (arc) + 1;
          dst = arc + 1;
 
+         /* Ensure that neither source nor destination are absolute file
+            names (unless permitted by -P option), and that they do not
+            contain dubious parts (e.g. ../).
+
+            This is an extra safety precaution. Besides, it might be
+            necessary to extract from archives created with tar versions
+            prior to 1.19. */
+
+         if (*src)
+           src = safer_name_suffix (src, false, absolute_names_option);
+         if (*dst)
+           dst = safer_name_suffix (dst, false, absolute_names_option);
+
          if (*src == 0)
            src = temp_stub;
          else if (*dst == 0)
          if (*src == 0)
            src = temp_stub;
          else if (*dst == 0)
@@ -1374,6 +1524,7 @@ try_purge_directory (char const *directory_name)
   free (temp_stub);
 
   /* Process deletes */
   free (temp_stub);
 
   /* Process deletes */
+  dump = dumpdir_create (current_stat_info.dumpdir);
   p = NULL;
   for (cur = current_dir; *cur; cur += strlen (cur) + 1)
     {
   p = NULL;
   for (cur = current_dir; *cur; cur += strlen (cur) + 1)
     {
@@ -1395,7 +1546,7 @@ try_purge_directory (char const *directory_name)
          continue;
        }
 
          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)))
        {
          || (*entry == 'D' && !S_ISDIR (st.st_mode))
          || (*entry == 'Y' && S_ISDIR (st.st_mode)))
        {
@@ -1421,7 +1572,8 @@ try_purge_directory (char const *directory_name)
        }
     }
   free (p);
        }
     }
   free (p);
-
+  dumpdir_free (dump);
+  
   free (current_dir);
   return true;
 }
   free (current_dir);
   return true;
 }
This page took 0.035199 seconds and 4 git commands to generate.