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