]> git.cworth.org Git - tar/blob - src/incremen.c
Imported Upstream version 1.20
[tar] / src / incremen.c
1 /* GNU dump extensions to tar.
2
3    Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
4    2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 3, or (at your option) any later
9    version.
10
11    This program is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
14    Public License for more details.
15
16    You should have received a copy of the GNU General Public License along
17    with this program; if not, write to the Free Software Foundation, Inc.,
18    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19
20 #include <system.h>
21 #include <hash.h>
22 #include <quotearg.h>
23 #include "common.h"
24
25 /* Incremental dump specialities.  */
26
27 /* Which child files to save under a directory.  */
28 enum children
29   {
30     NO_CHILDREN,
31     CHANGED_CHILDREN,
32     ALL_CHILDREN
33   };
34
35 #define DIRF_INIT     0x0001    /* directory structure is initialized
36                                    (procdir called at least once) */
37 #define DIRF_NFS      0x0002    /* directory is mounted on nfs */
38 #define DIRF_FOUND    0x0004    /* directory is found on fs */
39 #define DIRF_NEW      0x0008    /* directory is new (not found
40                                    in the previous dump) */
41 #define DIRF_RENAMED  0x0010    /* directory is renamed */
42
43 #define DIR_IS_INITED(d) ((d)->flags & DIRF_INIT)
44 #define DIR_IS_NFS(d) ((d)->flags & DIRF_NFS)
45 #define DIR_IS_FOUND(d) ((d)->flags & DIRF_FOUND)
46 #define DIR_IS_NEW(d) ((d)->flags & DIRF_NEW)
47 #define DIR_IS_RENAMED(d) ((d)->flags & DIRF_RENAMED)
48
49 #define DIR_SET_FLAG(d,f) (d)->flags |= (f)
50 #define DIR_CLEAR_FLAG(d,f) (d)->flags &= ~(f)
51
52 struct dumpdir                 /* Dump directory listing */
53 {
54   char *contents;              /* Actual contents */
55   size_t total;                /* Total number of elements */
56   size_t elc;                  /* Number of D/N/Y elements. */
57   char **elv;                  /* Array of D/N/Y elements */
58 };
59
60 /* Directory attributes.  */
61 struct directory
62   {
63     struct timespec mtime;      /* Modification time */
64     dev_t device_number;        /* device number for directory */
65     ino_t inode_number;         /* inode number for directory */
66     struct dumpdir *dump;       /* Directory contents */
67     struct dumpdir *idump;      /* Initial contents if the directory was
68                                    rescanned */
69     enum children children;     /* What to save under this directory */
70     unsigned flags;             /* See DIRF_ macros above */
71     struct directory *orig;     /* If the directory was renamed, points to
72                                    the original directory structure */
73     const char *tagfile;        /* Tag file, if the directory falls under
74                                    exclusion_tag_under */
75     char name[1];               /* file name of directory */
76   };
77
78 struct dumpdir *
79 dumpdir_create0 (const char *contents, const char *cmask)
80 {
81   struct dumpdir *dump;
82   size_t i, total, ctsize, len;
83   const char *p;
84   
85   for (i = 0, total = 0, ctsize = 1, p = contents; *p; total++, p += len)
86     {
87       len = strlen (p) + 1;
88       ctsize += len;
89       if (!cmask || strchr (cmask, *p))
90         i++;
91     }
92   dump = xmalloc (sizeof (*dump) + ctsize);
93   dump->contents = (char*)(dump + 1);
94   memcpy (dump->contents, contents, ctsize);
95   dump->total = total;
96   dump->elc = i;
97   dump->elv = xcalloc (i + 1, sizeof (dump->elv[0]));
98
99   for (i = 0, p = dump->contents; *p; p += strlen (p) + 1)
100     {
101       if (!cmask || strchr (cmask, *p))
102         dump->elv[i++] = p + 1;
103     }
104   dump->elv[i] = NULL;
105   return dump;
106 }
107
108 struct dumpdir *
109 dumpdir_create (const char *contents)
110 {
111   return dumpdir_create0 (contents, "YND");
112 }
113
114 void
115 dumpdir_free (struct dumpdir *dump)
116 {
117   free (dump->elv);
118   free (dump);
119 }
120
121 static int
122 compare_dirnames (const void *first, const void *second)
123 {
124   char const *const *name1 = first;
125   char const *const *name2 = second;
126   return strcmp (*name1, *name2);
127 }
128
129 /* Locate NAME in the dumpdir array DUMP.
130    Return pointer to the slot in DUMP->contents, or NULL if not found */
131 char *
132 dumpdir_locate (struct dumpdir *dump, const char *name)
133 {
134   char **ptr;
135   if (!dump)
136     return NULL;
137
138   ptr = bsearch (&name, dump->elv, dump->elc, sizeof (dump->elv[0]),
139                  compare_dirnames);
140   return ptr ? *ptr - 1: NULL;
141 }
142
143 struct dumpdir_iter
144 {
145   struct dumpdir *dump; /* Dumpdir being iterated */
146   int all;              /* Iterate over all entries, not only D/N/Y */ 
147   size_t next;          /* Index of the next element */
148 };
149
150 char *
151 dumpdir_next (struct dumpdir_iter *itr)
152 {
153   size_t cur = itr->next;
154   char *ret = NULL;
155   
156   if (itr->all)
157     {
158       ret = itr->dump->contents + cur;
159       if (*ret == 0)
160         return NULL;
161       itr->next += strlen (ret) + 1;
162     }
163   else if (cur < itr->dump->elc)
164     {
165       ret = itr->dump->elv[cur] - 1;
166       itr->next++;
167     }
168
169   return ret;
170 }
171
172 char *
173 dumpdir_first (struct dumpdir *dump, int all, struct dumpdir_iter **pitr)
174 {
175   struct dumpdir_iter *itr = xmalloc (sizeof (*itr));
176   itr->dump = dump;
177   itr->all = all;
178   itr->next = 0;
179   *pitr = itr;
180   return dumpdir_next (itr);
181 }
182
183 /* Return size in bytes of the dumpdir array P */
184 size_t
185 dumpdir_size (const char *p)
186 {
187   size_t totsize = 0;
188
189   while (*p)
190     {
191       size_t size = strlen (p) + 1;
192       totsize += size;
193       p += size;
194     }
195   return totsize + 1;
196 }
197
198 \f
199 static Hash_table *directory_table;
200 static Hash_table *directory_meta_table;
201
202 #if HAVE_ST_FSTYPE_STRING
203   static char const nfs_string[] = "nfs";
204 # define NFS_FILE_STAT(st) (strcmp ((st).st_fstype, nfs_string) == 0)
205 #else
206 # define ST_DEV_MSB(st) (~ (dev_t) 0 << (sizeof (st).st_dev * CHAR_BIT - 1))
207 # define NFS_FILE_STAT(st) (((st).st_dev & ST_DEV_MSB (st)) != 0)
208 #endif
209
210 /* Calculate the hash of a directory.  */
211 static size_t
212 hash_directory_name (void const *entry, size_t n_buckets)
213 {
214   struct directory const *directory = entry;
215   return hash_string (directory->name, n_buckets);
216 }
217
218 /* Compare two directories for equality of their names. */
219 static bool
220 compare_directory_names (void const *entry1, void const *entry2)
221 {
222   struct directory const *directory1 = entry1;
223   struct directory const *directory2 = entry2;
224   return strcmp (directory1->name, directory2->name) == 0;
225 }
226
227 static size_t
228 hash_directory_meta (void const *entry, size_t n_buckets)
229 {
230   struct directory const *directory = entry;
231   /* FIXME: Work out a better algorytm */
232   return (directory->device_number + directory->inode_number) % n_buckets;
233 }
234
235 /* Compare two directories for equality of their device and inode numbers. */
236 static bool
237 compare_directory_meta (void const *entry1, void const *entry2)
238 {
239   struct directory const *directory1 = entry1;
240   struct directory const *directory2 = entry2;
241   return directory1->device_number == directory2->device_number
242             && directory1->inode_number == directory2->inode_number;
243 }
244
245 /* Make a directory entry for given NAME */
246 static struct directory *
247 make_directory (const char *name)
248 {
249   size_t namelen = strlen (name);
250   size_t size = offsetof (struct directory, name) + namelen + 1;
251   struct directory *directory = xmalloc (size);
252   directory->dump = directory->idump = NULL;
253   directory->orig = NULL;
254   directory->flags = false;
255   strcpy (directory->name, name);
256   if (namelen && ISSLASH (directory->name[namelen - 1]))
257     directory->name[namelen - 1] = 0;
258   directory->tagfile = NULL;
259   return directory;
260 }
261
262 /* Create and link a new directory entry for directory NAME, having a
263    device number DEV and an inode number INO, with NFS indicating
264    whether it is an NFS device and FOUND indicating whether we have
265    found that the directory exists.  */
266 static struct directory *
267 note_directory (char const *name, struct timespec mtime,
268                 dev_t dev, ino_t ino, bool nfs, bool found,
269                 const char *contents)
270 {
271   struct directory *directory = make_directory (name);
272
273   directory->mtime = mtime;
274   directory->device_number = dev;
275   directory->inode_number = ino;
276   directory->children = CHANGED_CHILDREN;
277   if (nfs)
278     DIR_SET_FLAG (directory, DIRF_NFS);
279   if (found)
280     DIR_SET_FLAG (directory, DIRF_FOUND);
281   if (contents)
282     directory->dump = dumpdir_create (contents);
283   else
284     directory->dump = NULL;
285
286   if (! ((directory_table
287           || (directory_table = hash_initialize (0, 0,
288                                                  hash_directory_name,
289                                                  compare_directory_names, 0)))
290          && hash_insert (directory_table, directory)))
291     xalloc_die ();
292
293   if (! ((directory_meta_table
294           || (directory_meta_table = hash_initialize (0, 0,
295                                                       hash_directory_meta,
296                                                       compare_directory_meta,
297                                                       0)))
298          && hash_insert (directory_meta_table, directory)))
299     xalloc_die ();
300
301   return directory;
302 }
303
304 /* Return a directory entry for a given file NAME, or zero if none found.  */
305 static struct directory *
306 find_directory (const char *name)
307 {
308   if (! directory_table)
309     return 0;
310   else
311     {
312       struct directory *dir = make_directory (name);
313       struct directory *ret = hash_lookup (directory_table, dir);
314       free (dir);
315       return ret;
316     }
317 }
318
319 /* Return a directory entry for a given combination of device and inode
320    numbers, or zero if none found.  */
321 static struct directory *
322 find_directory_meta (dev_t dev, ino_t ino)
323 {
324   if (! directory_meta_table)
325     return 0;
326   else
327     {
328       struct directory *dir = make_directory ("");
329       struct directory *ret;
330       dir->device_number = dev;
331       dir->inode_number = ino;
332       ret = hash_lookup (directory_meta_table, dir);
333       free (dir);
334       return ret;
335     }
336 }
337
338 void
339 update_parent_directory (const char *name)
340 {
341   struct directory *directory;
342   char *p;
343
344   p = dir_name (name);
345   directory = find_directory (p);
346   if (directory)
347     {
348       struct stat st;
349       if (deref_stat (dereference_option, p, &st) != 0)
350         stat_diag (name);
351       else
352         directory->mtime = get_stat_mtime (&st);
353     }
354   free (p);
355 }
356
357 static struct directory *
358 procdir (char *name_buffer, struct stat *stat_data,
359          dev_t device,
360          enum children children,
361          bool verbose,
362          char *entry)
363 {
364   struct directory *directory;
365   bool nfs = NFS_FILE_STAT (*stat_data);
366
367   if ((directory = find_directory (name_buffer)) != NULL)
368     {
369       if (DIR_IS_INITED (directory))
370         return directory;
371
372       /* With NFS, the same file can have two different devices
373          if an NFS directory is mounted in multiple locations,
374          which is relatively common when automounting.
375          To avoid spurious incremental redumping of
376          directories, consider all NFS devices as equal,
377          relying on the i-node to establish differences.  */
378
379       if (! ((!check_device_option
380               || (DIR_IS_NFS (directory) && nfs)
381               || directory->device_number == stat_data->st_dev)
382              && directory->inode_number == stat_data->st_ino))
383         {
384           /* FIXME: find_directory_meta ignores nfs */
385           struct directory *d = find_directory_meta (stat_data->st_dev,
386                                                      stat_data->st_ino);
387           if (d)
388             {
389               if (verbose_option)
390                 WARN ((0, 0, _("%s: Directory has been renamed from %s"),
391                        quotearg_colon (name_buffer),
392                        quote_n (1, d->name)));
393               directory->orig = d;
394               DIR_SET_FLAG (directory, DIRF_RENAMED);
395               directory->children = CHANGED_CHILDREN;
396             }
397           else
398             {
399               if (verbose_option)
400                 WARN ((0, 0, _("%s: Directory has been renamed"),
401                        quotearg_colon (name_buffer)));
402               directory->children = ALL_CHILDREN;
403               directory->device_number = stat_data->st_dev;
404               directory->inode_number = stat_data->st_ino;
405             }
406           if (nfs)
407             DIR_SET_FLAG (directory, DIRF_NFS);
408         }
409       else
410         directory->children = CHANGED_CHILDREN;
411
412       DIR_SET_FLAG (directory, DIRF_FOUND);
413     }
414   else
415     {
416       struct directory *d = find_directory_meta (stat_data->st_dev,
417                                                  stat_data->st_ino);
418
419       directory = note_directory (name_buffer,
420                                   get_stat_mtime(stat_data),
421                                   stat_data->st_dev,
422                                   stat_data->st_ino,
423                                   nfs,
424                                   true,
425                                   NULL);
426
427       if (d)
428         {
429           if (verbose)
430             WARN ((0, 0, _("%s: Directory has been renamed from %s"),
431                    quotearg_colon (name_buffer),
432                    quote_n (1, d->name)));
433           directory->orig = d;
434           DIR_SET_FLAG (directory, DIRF_RENAMED);
435           directory->children = CHANGED_CHILDREN;
436         }
437       else
438         {
439           DIR_SET_FLAG (directory, DIRF_NEW);
440           if (verbose)
441             WARN ((0, 0, _("%s: Directory is new"),
442                    quotearg_colon (name_buffer)));
443           directory->children =
444             (listed_incremental_option
445              || (OLDER_STAT_TIME (*stat_data, m)
446                  || (after_date_option
447                      && OLDER_STAT_TIME (*stat_data, c))))
448             ? ALL_CHILDREN
449             : CHANGED_CHILDREN;
450         }
451     }
452
453   /* If the directory is on another device and --one-file-system was given,
454      omit it... */
455   if (one_file_system_option && device != stat_data->st_dev
456       /* ... except if it was explicitely given in the command line */
457       && !is_individual_file (name_buffer))
458     directory->children = NO_CHILDREN;
459   else if (children == ALL_CHILDREN)
460     directory->children = ALL_CHILDREN;
461
462   DIR_SET_FLAG (directory, DIRF_INIT);
463
464   {
465     const char *tag_file_name;
466
467     switch (check_exclusion_tags (name_buffer, &tag_file_name))
468       {
469       case exclusion_tag_all:
470         /* This warning can be duplicated by code in dump_file0, but only
471            in case when the topmost directory being archived contains
472            an exclusion tag. */
473         exclusion_tag_warning (name_buffer, tag_file_name,
474                                _("directory not dumped"));
475         if (entry)
476           *entry = 'N';
477         directory->children = NO_CHILDREN;
478         break;
479
480       case exclusion_tag_contents:
481         exclusion_tag_warning (name_buffer, tag_file_name,
482                                _("contents not dumped"));
483         directory->children = NO_CHILDREN;
484         break;
485
486       case exclusion_tag_under:
487         exclusion_tag_warning (name_buffer, tag_file_name,
488                                _("contents not dumped"));
489         directory->tagfile = tag_file_name;
490         break;
491
492       case exclusion_tag_none:
493         break;
494       }
495   }
496
497   return directory;
498 }
499
500 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
501    build a new dumpdir template.
502
503    DIR must be returned by a previous call to savedir().
504
505    File names in DIRECTORY->dump->contents must be sorted
506    alphabetically.
507
508    DIRECTORY->dump is replaced with the created template. Each entry is
509    prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
510
511 void
512 makedumpdir (struct directory *directory, const char *dir)
513 {
514   size_t i,
515          dirsize,  /* Number of elements in DIR */
516          len;      /* Length of DIR, including terminating nul */
517   const char *p;
518   char const **array;
519   char *new_dump, *new_dump_ptr;
520   struct dumpdir *dump;
521
522   if (directory->children == ALL_CHILDREN)
523     dump = NULL;
524   else if (DIR_IS_RENAMED (directory))
525     dump = directory->orig->idump ?
526            directory->orig->idump : directory->orig->dump;
527   else
528     dump = directory->dump;
529
530   /* Count the size of DIR and the number of elements it contains */
531   dirsize = 0;
532   len = 0;
533   for (p = dir; *p; p += strlen (p) + 1, dirsize++)
534     len += strlen (p) + 2;
535   len++;
536
537   /* Create a sorted directory listing */
538   array = xcalloc (dirsize, sizeof array[0]);
539   for (i = 0, p = dir; *p; p += strlen (p) + 1, i++)
540     array[i] = p;
541
542   qsort (array, dirsize, sizeof (array[0]), compare_dirnames);
543
544   /* Prepare space for new dumpdir */
545   new_dump = xmalloc (len);
546   new_dump_ptr = new_dump;
547
548   /* Fill in the dumpdir template */
549   for (i = 0; i < dirsize; i++)
550     {
551       const char *loc = dumpdir_locate (dump, array[i]);
552       if (loc)
553         {
554           if (directory->tagfile)
555             *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
556                                 ' ' : 'I';
557           else
558             *new_dump_ptr = ' ';
559           new_dump_ptr++;
560         }
561       else if (directory->tagfile)
562         *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
563                                ' ' : 'I';
564       else
565         *new_dump_ptr++ = 'Y'; /* New entry */
566
567       /* Copy the file name */
568       for (p = array[i]; (*new_dump_ptr++ = *p++); )
569         ;
570     }
571   *new_dump_ptr = 0;
572   directory->idump = directory->dump;
573   directory->dump = dumpdir_create0 (new_dump, NULL);
574   free (array);
575 }
576
577 /* Recursively scan the given directory. */
578 static const char *
579 scan_directory (char *dir, dev_t device)
580 {
581   char *dirp = savedir (dir);   /* for scanning directory */
582   char *name_buffer;            /* directory, `/', and directory member */
583   size_t name_buffer_size;      /* allocated size of name_buffer, minus 2 */
584   size_t name_length;           /* used length in name_buffer */
585   struct stat stat_data;
586   struct directory *directory;
587
588   if (! dirp)
589     savedir_error (dir);
590
591   name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
592   name_buffer = xmalloc (name_buffer_size + 2);
593   strcpy (name_buffer, dir);
594   if (! ISSLASH (dir[strlen (dir) - 1]))
595     strcat (name_buffer, "/");
596   name_length = strlen (name_buffer);
597
598   if (deref_stat (dereference_option, name_buffer, &stat_data))
599     {
600       stat_diag (name_buffer);
601       /* FIXME: used to be
602            children = CHANGED_CHILDREN;
603          but changed to: */
604       free (name_buffer);
605       free (dirp);
606       return NULL;
607     }
608
609   directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false,
610                        NULL);
611
612   if (dirp && directory->children != NO_CHILDREN)
613     {
614       char *entry;      /* directory entry being scanned */
615       size_t entrylen;  /* length of directory entry */
616       dumpdir_iter_t itr;
617
618       makedumpdir (directory, dirp);
619
620       for (entry = dumpdir_first (directory->dump, 1, &itr);
621            entry;
622            entry = dumpdir_next (itr))
623         {
624           entrylen = strlen (entry);
625           if (name_buffer_size <= entrylen - 1 + name_length)
626             {
627               do
628                 name_buffer_size += NAME_FIELD_SIZE;
629               while (name_buffer_size <= entrylen - 1 + name_length);
630               name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
631             }
632           strcpy (name_buffer + name_length, entry + 1);
633
634           if (*entry == 'I') /* Ignored entry */
635             *entry = 'N';
636           else if (excluded_name (name_buffer))
637             *entry = 'N';
638           else
639             {
640               if (deref_stat (dereference_option, name_buffer, &stat_data))
641                 {
642                   stat_diag (name_buffer);
643                   *entry = 'N';
644                   continue;
645                 }
646
647               if (S_ISDIR (stat_data.st_mode))
648                 {
649                   *entry = 'D';
650                   procdir (name_buffer, &stat_data, device,
651                            directory->children,
652                            verbose_option, entry);
653                 }
654
655               else if (one_file_system_option && device != stat_data.st_dev)
656                 *entry = 'N';
657
658               else if (*entry == 'Y')
659                 /* New entry, skip further checks */;
660
661               /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
662
663               else if (OLDER_STAT_TIME (stat_data, m)
664                        && (!after_date_option
665                            || OLDER_STAT_TIME (stat_data, c)))
666                 *entry = 'N';
667               else
668                 *entry = 'Y';
669             }
670         }
671       free (itr);
672     }
673
674   free (name_buffer);
675   if (dirp)
676     free (dirp);
677
678   return directory->dump ? directory->dump->contents : NULL;
679 }
680
681 const char *
682 get_directory_contents (char *dir, dev_t device)
683 {
684   return scan_directory (dir, device);
685 }
686
687 \f
688 static void
689 obstack_code_rename (struct obstack *stk, char *from, char *to)
690 {
691   char *s;
692
693   s = from[0] == 0 ? from :
694                      safer_name_suffix (from, false, absolute_names_option);
695   obstack_1grow (stk, 'R');
696   obstack_grow (stk, s, strlen (s) + 1);
697
698   s = to[0] == 0 ? to:
699                    safer_name_suffix (to, false, absolute_names_option);
700   obstack_1grow (stk, 'T');
701   obstack_grow (stk, s, strlen (s) + 1);
702 }
703
704 static bool
705 rename_handler (void *data, void *proc_data)
706 {
707   struct directory *dir = data;
708   struct obstack *stk = proc_data;
709
710   if (DIR_IS_RENAMED (dir))
711     {
712       struct directory *prev, *p;
713
714       /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries
715          are ignored when hit by this function next time.
716          If the chain forms a cycle, prev points to the entry DIR is renamed
717          from. In this case it still retains DIRF_RENAMED flag, which will be
718          cleared in the `else' branch below */
719       for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
720         DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
721
722       if (prev == NULL)
723         {
724           for (p = dir; p && p->orig; p = p->orig)
725             obstack_code_rename (stk, p->orig->name, p->name);
726         }
727       else
728         {
729           char *temp_name;
730
731           DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
732
733           /* Break the cycle by using a temporary name for one of its
734              elements.
735              First, create a temp name stub entry. */
736           temp_name = dir_name (dir->name);
737           obstack_1grow (stk, 'X');
738           obstack_grow (stk, temp_name, strlen (temp_name) + 1);
739
740           obstack_code_rename (stk, dir->name, "");
741
742           for (p = dir; p != prev; p = p->orig)
743             obstack_code_rename (stk, p->orig->name, p->name);
744
745           obstack_code_rename (stk, "", prev->name);
746         }
747     }
748   return true;
749 }
750
751 const char *
752 append_incremental_renames (const char *dump)
753 {
754   struct obstack stk;
755   size_t size;
756
757   if (directory_table == NULL)
758     return dump;
759
760   obstack_init (&stk);
761   if (dump)
762     {
763       size = dumpdir_size (dump) - 1;
764       obstack_grow (&stk, dump, size);
765     }
766   else
767     size = 0;
768
769   hash_do_for_each (directory_table, rename_handler, &stk);
770   if (obstack_object_size (&stk) != size)
771     {
772       obstack_1grow (&stk, 0);
773       dump = obstack_finish (&stk);
774     }
775   else
776     obstack_free (&stk, NULL);
777   return dump;
778 }
779
780 \f
781
782 static FILE *listed_incremental_stream;
783
784 /* Version of incremental format snapshots (directory files) used by this
785    tar. Currently it is supposed to be a single decimal number. 0 means
786    incremental snapshots as per tar version before 1.15.2.
787
788    The current tar version supports incremental versions from
789    0 up to TAR_INCREMENTAL_VERSION, inclusive.
790    It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
791
792 #define TAR_INCREMENTAL_VERSION 2
793
794 /* Read incremental snapshot formats 0 and 1 */
795 static void
796 read_incr_db_01 (int version, const char *initbuf)
797 {
798   int n;
799   uintmax_t u;
800   time_t sec;
801   long int nsec;
802   char *buf = 0;
803   size_t bufsize;
804   char *ebuf;
805   long lineno = 1;
806
807   if (version == 1)
808     {
809       if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)
810         {
811           read_error (listed_incremental_option);
812           free (buf);
813           return;
814         }
815       ++lineno;
816     }
817   else
818     {
819       buf = strdup (initbuf);
820       bufsize = strlen (buf) + 1;
821     }
822
823   sec = TYPE_MINIMUM (time_t);
824   nsec = -1;
825   errno = 0;
826   u = strtoumax (buf, &ebuf, 10);
827   if (!errno && TYPE_MAXIMUM (time_t) < u)
828     errno = ERANGE;
829   if (errno || buf == ebuf)
830     ERROR ((0, errno, "%s:%ld: %s",
831             quotearg_colon (listed_incremental_option),
832             lineno,
833             _("Invalid time stamp")));
834   else
835     {
836       sec = u;
837
838       if (version == 1 && *ebuf)
839         {
840           char const *buf_ns = ebuf + 1;
841           errno = 0;
842           u = strtoumax (buf_ns, &ebuf, 10);
843           if (!errno && BILLION <= u)
844             errno = ERANGE;
845           if (errno || buf_ns == ebuf)
846             {
847               ERROR ((0, errno, "%s:%ld: %s",
848                       quotearg_colon (listed_incremental_option),
849                       lineno,
850                       _("Invalid time stamp")));
851               sec = TYPE_MINIMUM (time_t);
852             }
853           else
854             nsec = u;
855         }
856       else
857         {
858           /* pre-1 incremental format does not contain nanoseconds */
859           nsec = 0;
860         }
861     }
862   newer_mtime_option.tv_sec = sec;
863   newer_mtime_option.tv_nsec = nsec;
864
865
866   while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
867     {
868       dev_t dev;
869       ino_t ino;
870       bool nfs = buf[0] == '+';
871       char *strp = buf + nfs;
872       struct timespec mtime;
873
874       lineno++;
875
876       if (buf[n - 1] == '\n')
877         buf[n - 1] = '\0';
878
879       if (version == 1)
880         {
881           errno = 0;
882           u = strtoumax (strp, &ebuf, 10);
883           if (!errno && TYPE_MAXIMUM (time_t) < u)
884             errno = ERANGE;
885           if (errno || strp == ebuf || *ebuf != ' ')
886             {
887               ERROR ((0, errno, "%s:%ld: %s",
888                       quotearg_colon (listed_incremental_option), lineno,
889                       _("Invalid modification time (seconds)")));
890               sec = (time_t) -1;
891             }
892           else
893             sec = u;
894           strp = ebuf;
895
896           errno = 0;
897           u = strtoumax (strp, &ebuf, 10);
898           if (!errno && BILLION <= u)
899             errno = ERANGE;
900           if (errno || strp == ebuf || *ebuf != ' ')
901             {
902               ERROR ((0, errno, "%s:%ld: %s",
903                       quotearg_colon (listed_incremental_option), lineno,
904                       _("Invalid modification time (nanoseconds)")));
905               nsec = -1;
906             }
907           else
908             nsec = u;
909           mtime.tv_sec = sec;
910           mtime.tv_nsec = nsec;
911           strp = ebuf;
912         }
913       else
914         memset (&mtime, 0, sizeof mtime);
915
916       errno = 0;
917       u = strtoumax (strp, &ebuf, 10);
918       if (!errno && TYPE_MAXIMUM (dev_t) < u)
919         errno = ERANGE;
920       if (errno || strp == ebuf || *ebuf != ' ')
921         {
922           ERROR ((0, errno, "%s:%ld: %s",
923                   quotearg_colon (listed_incremental_option), lineno,
924                   _("Invalid device number")));
925           dev = (dev_t) -1;
926         }
927       else
928         dev = u;
929       strp = ebuf;
930
931       errno = 0;
932       u = strtoumax (strp, &ebuf, 10);
933       if (!errno && TYPE_MAXIMUM (ino_t) < u)
934         errno = ERANGE;
935       if (errno || strp == ebuf || *ebuf != ' ')
936         {
937           ERROR ((0, errno, "%s:%ld: %s",
938                   quotearg_colon (listed_incremental_option), lineno,
939                   _("Invalid inode number")));
940           ino = (ino_t) -1;
941         }
942       else
943         ino = u;
944       strp = ebuf;
945
946       strp++;
947       unquote_string (strp);
948       note_directory (strp, mtime, dev, ino, nfs, false, NULL);
949     }
950   free (buf);
951 }
952
953 /* Read a nul-terminated string from FP and store it in STK.
954    Store the number of bytes read (including nul terminator) in PCOUNT.
955
956    Return the last character read or EOF on end of file. */
957 static int
958 read_obstack (FILE *fp, struct obstack *stk, size_t *pcount)
959 {
960   int c;
961   size_t i;
962
963   for (i = 0, c = getc (fp); c != EOF && c != 0; c = getc (fp), i++)
964     obstack_1grow (stk, c);
965   obstack_1grow (stk, 0);
966
967   *pcount = i;
968   return c;
969 }
970
971 /* Read from file FP a nul-terminated string and convert it to
972    intmax_t.  Return the resulting value in PVAL.  Assume '-' has
973    already been read.
974
975    Throw a fatal error if the string cannot be converted or if the
976    converted value is less than MIN_VAL.  */
977
978 static void
979 read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
980 {
981   int c;
982   size_t i;
983   char buf[INT_BUFSIZE_BOUND (intmax_t)];
984   char *ep;
985   buf[0] = '-';
986
987   for (i = 1; ISDIGIT (c = getc (fp)); i++)
988     {
989       if (i == sizeof buf - 1)
990         FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
991       buf[i] = c;
992     }
993
994   if (c < 0)
995     {
996       if (ferror (fp))
997         FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
998       else
999         FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1000     }
1001
1002   buf[i] = 0;
1003   errno = 0;
1004   *pval = strtoimax (buf, &ep, 10);
1005   if (c || errno || *pval < min_val)
1006     FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1007 }
1008
1009 /* Read from file FP a nul-terminated string and convert it to
1010    uintmax_t.  Return the resulting value in PVAL.  Assume C has
1011    already been read.
1012
1013    Throw a fatal error if the string cannot be converted or if the
1014    converted value exceeds MAX_VAL.
1015
1016    Return the last character read or EOF on end of file. */
1017
1018 static int
1019 read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
1020 {
1021   size_t i;
1022   char buf[UINTMAX_STRSIZE_BOUND], *ep;
1023
1024   for (i = 0; ISDIGIT (c); i++)
1025     {
1026       if (i == sizeof buf - 1)
1027         FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1028       buf[i] = c;
1029       c = getc (fp);
1030     }
1031
1032   if (c < 0)
1033     {
1034       if (ferror (fp))
1035         FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1036       else if (i == 0)
1037         return c;
1038       else
1039         FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1040     }
1041
1042   buf[i] = 0;
1043   errno = 0;
1044   *pval = strtoumax (buf, &ep, 10);
1045   if (c || errno || max_val < *pval)
1046     FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1047   return c;
1048 }
1049
1050 /* Read from file FP a nul-terminated string and convert it to
1051    uintmax_t.  Return the resulting value in PVAL.
1052
1053    Throw a fatal error if the string cannot be converted or if the
1054    converted value exceeds MAX_VAL.
1055
1056    Return the last character read or EOF on end of file. */
1057
1058 static int
1059 read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
1060 {
1061   return read_unsigned_num (getc (fp), fp, max_val, pval);
1062 }
1063
1064 /* Read from FP two NUL-terminated strings representing a struct
1065    timespec.  Return the resulting value in PVAL.
1066
1067    Throw a fatal error if the string cannot be converted.  */
1068
1069 static void
1070 read_timespec (FILE *fp, struct timespec *pval)
1071 {
1072   int c = getc (fp);
1073   intmax_t i;
1074   uintmax_t u;
1075
1076   if (c == '-')
1077     {
1078       read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
1079       c = 0;
1080       pval->tv_sec = i;
1081     }
1082   else
1083     {
1084       c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
1085       pval->tv_sec = u;
1086     }
1087
1088   if (c || read_num (fp, BILLION - 1, &u))
1089     FATAL_ERROR ((0, 0, "%s: %s",
1090                   quotearg_colon (listed_incremental_option),
1091                   _("Unexpected EOF in snapshot file")));
1092   pval->tv_nsec = u;
1093 }
1094
1095 /* Read incremental snapshot format 2 */
1096 static void
1097 read_incr_db_2 ()
1098 {
1099   uintmax_t u;
1100   struct obstack stk;
1101
1102   obstack_init (&stk);
1103
1104   read_timespec (listed_incremental_stream, &newer_mtime_option);
1105
1106   for (;;)
1107     {
1108       struct timespec mtime;
1109       dev_t dev;
1110       ino_t ino;
1111       bool nfs;
1112       char *name;
1113       char *content;
1114       size_t s;
1115
1116       if (read_num (listed_incremental_stream, 1, &u))
1117         return; /* Normal return */
1118
1119       nfs = u;
1120
1121       read_timespec (listed_incremental_stream, &mtime);
1122
1123       if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
1124         break;
1125       dev = u;
1126
1127       if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
1128         break;
1129       ino = u;
1130
1131       if (read_obstack (listed_incremental_stream, &stk, &s))
1132         break;
1133
1134       name = obstack_finish (&stk);
1135
1136       while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
1137         ;
1138       if (getc (listed_incremental_stream) != 0)
1139         FATAL_ERROR ((0, 0, "%s: %s",
1140                       quotearg_colon (listed_incremental_option),
1141                       _("Missing record terminator")));
1142
1143       content = obstack_finish (&stk);
1144       note_directory (name, mtime, dev, ino, nfs, false, content);
1145       obstack_free (&stk, content);
1146     }
1147   FATAL_ERROR ((0, 0, "%s: %s",
1148                 quotearg_colon (listed_incremental_option),
1149                 _("Unexpected EOF in snapshot file")));
1150 }
1151
1152 /* Read incremental snapshot file (directory file).
1153    If the file has older incremental version, make sure that it is processed
1154    correctly and that tar will use the most conservative backup method among
1155    possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
1156    etc.) This ensures that the snapshots are updated to the recent version
1157    without any loss of data. */
1158 void
1159 read_directory_file (void)
1160 {
1161   int fd;
1162   char *buf = 0;
1163   size_t bufsize;
1164
1165   /* Open the file for both read and write.  That way, we can write
1166      it later without having to reopen it, and don't have to worry if
1167      we chdir in the meantime.  */
1168   fd = open (listed_incremental_option, O_RDWR | O_CREAT, MODE_RW);
1169   if (fd < 0)
1170     {
1171       open_error (listed_incremental_option);
1172       return;
1173     }
1174
1175   listed_incremental_stream = fdopen (fd, "r+");
1176   if (! listed_incremental_stream)
1177     {
1178       open_error (listed_incremental_option);
1179       close (fd);
1180       return;
1181     }
1182
1183   if (0 < getline (&buf, &bufsize, listed_incremental_stream))
1184     {
1185       char *ebuf;
1186       uintmax_t incremental_version;
1187
1188       if (strncmp (buf, PACKAGE_NAME, sizeof PACKAGE_NAME - 1) == 0)
1189         {
1190           ebuf = buf + sizeof PACKAGE_NAME - 1;
1191           if (*ebuf++ != '-')
1192             ERROR((1, 0, _("Bad incremental file format")));
1193           for (; *ebuf != '-'; ebuf++)
1194             if (!*ebuf)
1195               ERROR((1, 0, _("Bad incremental file format")));
1196
1197           incremental_version = strtoumax (ebuf + 1, NULL, 10);
1198         }
1199       else
1200         incremental_version = 0;
1201
1202       switch (incremental_version)
1203         {
1204         case 0:
1205         case 1:
1206           read_incr_db_01 (incremental_version, buf);
1207           break;
1208
1209         case TAR_INCREMENTAL_VERSION:
1210           read_incr_db_2 ();
1211           break;
1212
1213         default:
1214           ERROR ((1, 0, _("Unsupported incremental format version: %"PRIuMAX),
1215                   incremental_version));
1216         }
1217
1218     }
1219
1220   if (ferror (listed_incremental_stream))
1221     read_error (listed_incremental_option);
1222   if (buf)
1223     free (buf);
1224 }
1225
1226 /* Output incremental data for the directory ENTRY to the file DATA.
1227    Return nonzero if successful, preserving errno on write failure.  */
1228 static bool
1229 write_directory_file_entry (void *entry, void *data)
1230 {
1231   struct directory const *directory = entry;
1232   FILE *fp = data;
1233
1234   if (DIR_IS_FOUND (directory))
1235     {
1236       char buf[UINTMAX_STRSIZE_BOUND];
1237       char *s;
1238
1239       s = DIR_IS_NFS (directory) ? "1" : "0";
1240       fwrite (s, 2, 1, fp);
1241       s = (TYPE_SIGNED (time_t)
1242            ? imaxtostr (directory->mtime.tv_sec, buf)
1243            : umaxtostr (directory->mtime.tv_sec, buf));
1244       fwrite (s, strlen (s) + 1, 1, fp);
1245       s = umaxtostr (directory->mtime.tv_nsec, buf);
1246       fwrite (s, strlen (s) + 1, 1, fp);
1247       s = umaxtostr (directory->device_number, buf);
1248       fwrite (s, strlen (s) + 1, 1, fp);
1249       s = umaxtostr (directory->inode_number, buf);
1250       fwrite (s, strlen (s) + 1, 1, fp);
1251
1252       fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
1253       if (directory->dump)
1254         {
1255           const char *p;
1256           dumpdir_iter_t itr;
1257
1258           for (p = dumpdir_first (directory->dump, 0, &itr);
1259                p;
1260                p = dumpdir_next (itr))
1261             fwrite (p, strlen (p) + 1, 1, fp);
1262           free (itr);
1263         }
1264       fwrite ("\0\0", 2, 1, fp);
1265     }
1266
1267   return ! ferror (fp);
1268 }
1269
1270 void
1271 write_directory_file (void)
1272 {
1273   FILE *fp = listed_incremental_stream;
1274   char buf[UINTMAX_STRSIZE_BOUND];
1275   char *s;
1276
1277   if (! fp)
1278     return;
1279
1280   if (fseek (fp, 0L, SEEK_SET) != 0)
1281     seek_error (listed_incremental_option);
1282   if (sys_truncate (fileno (fp)) != 0)
1283     truncate_error (listed_incremental_option);
1284
1285   fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION,
1286            TAR_INCREMENTAL_VERSION);
1287
1288   s = (TYPE_SIGNED (time_t)
1289        ? imaxtostr (start_time.tv_sec, buf)
1290        : umaxtostr (start_time.tv_sec, buf));
1291   fwrite (s, strlen (s) + 1, 1, fp);
1292   s = umaxtostr (start_time.tv_nsec, buf);
1293   fwrite (s, strlen (s) + 1, 1, fp);
1294
1295   if (! ferror (fp) && directory_table)
1296     hash_do_for_each (directory_table, write_directory_file_entry, fp);
1297
1298   if (ferror (fp))
1299     write_error (listed_incremental_option);
1300   if (fclose (fp) != 0)
1301     close_error (listed_incremental_option);
1302 }
1303
1304 \f
1305 /* Restoration of incremental dumps.  */
1306
1307 static void
1308 get_gnu_dumpdir (struct tar_stat_info *stat_info)
1309 {
1310   size_t size;
1311   size_t copied;
1312   union block *data_block;
1313   char *to;
1314   char *archive_dir;
1315
1316   size = stat_info->stat.st_size;
1317
1318   archive_dir = xmalloc (size);
1319   to = archive_dir;
1320
1321   set_next_block_after (current_header);
1322   mv_begin (stat_info);
1323
1324   for (; size > 0; size -= copied)
1325     {
1326       mv_size_left (size);
1327       data_block = find_next_block ();
1328       if (!data_block)
1329         ERROR ((1, 0, _("Unexpected EOF in archive")));
1330       copied = available_space_after (data_block);
1331       if (copied > size)
1332         copied = size;
1333       memcpy (to, data_block->buffer, copied);
1334       to += copied;
1335       set_next_block_after ((union block *)
1336                             (data_block->buffer + copied - 1));
1337     }
1338
1339   mv_end ();
1340
1341   stat_info->dumpdir = archive_dir;
1342   stat_info->skipped = true; /* For skip_member() and friends
1343                                 to work correctly */
1344 }
1345
1346 /* Return T if STAT_INFO represents a dumpdir archive member.
1347    Note: can invalidate current_header. It happens if flush_archive()
1348    gets called within get_gnu_dumpdir() */
1349 bool
1350 is_dumpdir (struct tar_stat_info *stat_info)
1351 {
1352   if (stat_info->is_dumpdir && !stat_info->dumpdir)
1353     get_gnu_dumpdir (stat_info);
1354   return stat_info->is_dumpdir;
1355 }
1356
1357 static bool
1358 dumpdir_ok (char *dumpdir)
1359 {
1360   char *p;
1361   int has_tempdir = 0;
1362   int expect = 0;
1363
1364   for (p = dumpdir; *p; p += strlen (p) + 1)
1365     {
1366       if (expect && *p != expect)
1367         {
1368           ERROR ((0, 0,
1369                   _("Malformed dumpdir: expected '%c' but found %#3o"),
1370                   expect, *p));
1371           return false;
1372         }
1373       switch (*p)
1374         {
1375         case 'X':
1376           if (has_tempdir)
1377             {
1378               ERROR ((0, 0,
1379                       _("Malformed dumpdir: 'X' duplicated")));
1380               return false;
1381             }
1382           else
1383             has_tempdir = 1;
1384           break;
1385
1386         case 'R':
1387           if (p[1] == 0)
1388             {
1389               if (!has_tempdir)
1390                 {
1391                   ERROR ((0, 0,
1392                           _("Malformed dumpdir: empty name in 'R'")));
1393                   return false;
1394                 }
1395               else
1396                 has_tempdir = 0;
1397             }
1398           expect = 'T';
1399           break;
1400
1401         case 'T':
1402           if (expect != 'T')
1403             {
1404               ERROR ((0, 0,
1405                       _("Malformed dumpdir: 'T' not preceeded by 'R'")));
1406               return false;
1407             }
1408           if (p[1] == 0 && !has_tempdir)
1409             {
1410               ERROR ((0, 0,
1411                       _("Malformed dumpdir: empty name in 'T'")));
1412               return false;
1413             }
1414           expect = 0;
1415           break;
1416
1417         case 'N':
1418         case 'Y':
1419         case 'D':
1420           break;
1421
1422         default:
1423           /* FIXME: bail out? */
1424           break;
1425         }
1426     }
1427
1428   if (expect)
1429     {
1430       ERROR ((0, 0,
1431               _("Malformed dumpdir: expected '%c' but found end of data"),
1432               expect));
1433       return false;
1434     }
1435
1436   if (has_tempdir)
1437     WARN ((0, 0, _("Malformed dumpdir: 'X' never used")));
1438
1439   return true;
1440 }
1441
1442 /* Examine the directories under directory_name and delete any
1443    files that were not there at the time of the back-up. */
1444 static bool
1445 try_purge_directory (char const *directory_name)
1446 {
1447   char *current_dir;
1448   char *cur, *arc, *p;
1449   char *temp_stub = NULL;
1450   struct dumpdir *dump;
1451
1452   if (!is_dumpdir (&current_stat_info))
1453     return false;
1454
1455   current_dir = savedir (directory_name);
1456
1457   if (!current_dir)
1458     /* The directory doesn't exist now.  It'll be created.  In any
1459        case, we don't have to delete any files out of it.  */
1460     return false;
1461
1462   /* Verify if dump directory is sane */
1463   if (!dumpdir_ok (current_stat_info.dumpdir))
1464     return false;
1465
1466   /* Process renames */
1467   for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
1468     {
1469       if (*arc == 'X')
1470         {
1471 #define TEMP_DIR_TEMPLATE "tar.XXXXXX"
1472           size_t len = strlen (arc + 1);
1473           temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
1474           memcpy (temp_stub, arc + 1, len);
1475           temp_stub[len] = '/';
1476           memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
1477                   sizeof TEMP_DIR_TEMPLATE);
1478           if (!mkdtemp (temp_stub))
1479             {
1480               ERROR ((0, errno,
1481                       _("Cannot create temporary directory using template %s"),
1482                       quote (temp_stub)));
1483               free (temp_stub);
1484               free (current_dir);
1485               return false;
1486             }
1487         }
1488       else if (*arc == 'R')
1489         {
1490           char *src, *dst;
1491           src = arc + 1;
1492           arc += strlen (arc) + 1;
1493           dst = arc + 1;
1494
1495           /* Ensure that neither source nor destination are absolute file
1496              names (unless permitted by -P option), and that they do not
1497              contain dubious parts (e.g. ../).
1498
1499              This is an extra safety precaution. Besides, it might be
1500              necessary to extract from archives created with tar versions
1501              prior to 1.19. */
1502
1503           if (*src)
1504             src = safer_name_suffix (src, false, absolute_names_option);
1505           if (*dst)
1506             dst = safer_name_suffix (dst, false, absolute_names_option);
1507
1508           if (*src == 0)
1509             src = temp_stub;
1510           else if (*dst == 0)
1511             dst = temp_stub;
1512
1513           if (!rename_directory (src, dst))
1514             {
1515               free (temp_stub);
1516               free (current_dir);
1517               /* FIXME: Make sure purge_directory(dst) will return
1518                  immediately */
1519               return false;
1520             }
1521         }
1522     }
1523
1524   free (temp_stub);
1525
1526   /* Process deletes */
1527   dump = dumpdir_create (current_stat_info.dumpdir);
1528   p = NULL;
1529   for (cur = current_dir; *cur; cur += strlen (cur) + 1)
1530     {
1531       const char *entry;
1532       struct stat st;
1533       if (p)
1534         free (p);
1535       p = new_name (directory_name, cur);
1536
1537       if (deref_stat (false, p, &st))
1538         {
1539           if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
1540                                   dirs and check it here? */
1541             {
1542               stat_diag (p);
1543               WARN ((0, 0, _("%s: Not purging directory: unable to stat"),
1544                      quotearg_colon (p)));
1545             }
1546           continue;
1547         }
1548
1549       if (!(entry = dumpdir_locate (dump, cur))
1550           || (*entry == 'D' && !S_ISDIR (st.st_mode))
1551           || (*entry == 'Y' && S_ISDIR (st.st_mode)))
1552         {
1553           if (one_file_system_option && st.st_dev != root_device)
1554             {
1555               WARN ((0, 0,
1556                      _("%s: directory is on a different device: not purging"),
1557                      quotearg_colon (p)));
1558               continue;
1559             }
1560
1561           if (! interactive_option || confirm ("delete", p))
1562             {
1563               if (verbose_option)
1564                 fprintf (stdlis, _("%s: Deleting %s\n"),
1565                          program_name, quote (p));
1566               if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
1567                 {
1568                   int e = errno;
1569                   ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));
1570                 }
1571             }
1572         }
1573     }
1574   free (p);
1575   dumpdir_free (dump);
1576   
1577   free (current_dir);
1578   return true;
1579 }
1580
1581 void
1582 purge_directory (char const *directory_name)
1583 {
1584   if (!try_purge_directory (directory_name))
1585     skip_member ();
1586 }
1587
1588 void
1589 list_dumpdir (char *buffer, size_t size)
1590 {
1591   int state = 0;
1592   while (size)
1593     {
1594       switch (*buffer)
1595         {
1596         case 'Y':
1597         case 'N':
1598         case 'D':
1599         case 'R':
1600         case 'T':
1601         case 'X':
1602           fprintf (stdlis, "%c", *buffer);
1603           if (state == 0)
1604             {
1605               fprintf (stdlis, " ");
1606               state = 1;
1607             }
1608           buffer++;
1609           size--;
1610           break;
1611
1612         case 0:
1613           fputc ('\n', stdlis);
1614           buffer++;
1615           size--;
1616           state = 0;
1617           break;
1618
1619         default:
1620           fputc (*buffer, stdlis);
1621           buffer++;
1622           size--;
1623         }
1624     }
1625 }