|  | @@ -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;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  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 (¤t_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;
 | 
	
		
			
				|  |  |  }
 |