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