Minor fixes.
[tar.git] / src / incremen.c
blobf5631a142282c7639b8f76affa3e7b6972d11970
1 /* GNU dump extensions to tar.
3 Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
4 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
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.
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.
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. */
20 #include <system.h>
21 #include <hash.h>
22 #include <quotearg.h>
23 #include "common.h"
25 /* Incremental dump specialities. */
27 /* Which child files to save under a directory. */
28 enum children
30 NO_CHILDREN,
31 CHANGED_CHILDREN,
32 ALL_CHILDREN
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 */
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)
49 #define DIR_SET_FLAG(d,f) (d)->flags |= (f)
50 #define DIR_CLEAR_FLAG(d,f) (d)->flags &= ~(f)
52 struct dumpdir /* Dump directory listing */
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 */
60 /* Directory attributes. */
61 struct directory
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 *caname; /* canonical name */
77 char *name; /* file name of directory */
80 struct dumpdir *
81 dumpdir_create0 (const char *contents, const char *cmask)
83 struct dumpdir *dump;
84 size_t i, total, ctsize, len;
85 char *p;
86 const char *q;
88 for (i = 0, total = 0, ctsize = 1, q = contents; *q; total++, q += len)
90 len = strlen (q) + 1;
91 ctsize += len;
92 if (!cmask || strchr (cmask, *q))
93 i++;
95 dump = xmalloc (sizeof (*dump) + ctsize);
96 dump->contents = (char*)(dump + 1);
97 memcpy (dump->contents, contents, ctsize);
98 dump->total = total;
99 dump->elc = i;
100 dump->elv = xcalloc (i + 1, sizeof (dump->elv[0]));
102 for (i = 0, p = dump->contents; *p; p += strlen (p) + 1)
104 if (!cmask || strchr (cmask, *p))
105 dump->elv[i++] = p + 1;
107 dump->elv[i] = NULL;
108 return dump;
111 struct dumpdir *
112 dumpdir_create (const char *contents)
114 return dumpdir_create0 (contents, "YND");
117 void
118 dumpdir_free (struct dumpdir *dump)
120 free (dump->elv);
121 free (dump);
124 static int
125 compare_dirnames (const void *first, const void *second)
127 char const *const *name1 = first;
128 char const *const *name2 = second;
129 return strcmp (*name1, *name2);
132 /* Locate NAME in the dumpdir array DUMP.
133 Return pointer to the slot in DUMP->contents, or NULL if not found */
134 char *
135 dumpdir_locate (struct dumpdir *dump, const char *name)
137 char **ptr;
138 if (!dump)
139 return NULL;
141 ptr = bsearch (&name, dump->elv, dump->elc, sizeof (dump->elv[0]),
142 compare_dirnames);
143 return ptr ? *ptr - 1: NULL;
146 struct dumpdir_iter
148 struct dumpdir *dump; /* Dumpdir being iterated */
149 int all; /* Iterate over all entries, not only D/N/Y */
150 size_t next; /* Index of the next element */
153 char *
154 dumpdir_next (struct dumpdir_iter *itr)
156 size_t cur = itr->next;
157 char *ret = NULL;
159 if (itr->all)
161 ret = itr->dump->contents + cur;
162 if (*ret == 0)
163 return NULL;
164 itr->next += strlen (ret) + 1;
166 else if (cur < itr->dump->elc)
168 ret = itr->dump->elv[cur] - 1;
169 itr->next++;
172 return ret;
175 char *
176 dumpdir_first (struct dumpdir *dump, int all, struct dumpdir_iter **pitr)
178 struct dumpdir_iter *itr = xmalloc (sizeof (*itr));
179 itr->dump = dump;
180 itr->all = all;
181 itr->next = 0;
182 *pitr = itr;
183 return dumpdir_next (itr);
186 /* Return size in bytes of the dumpdir array P */
187 size_t
188 dumpdir_size (const char *p)
190 size_t totsize = 0;
192 while (*p)
194 size_t size = strlen (p) + 1;
195 totsize += size;
196 p += size;
198 return totsize + 1;
202 static struct directory *dirhead, *dirtail;
203 static Hash_table *directory_table;
204 static Hash_table *directory_meta_table;
206 #if HAVE_ST_FSTYPE_STRING
207 static char const nfs_string[] = "nfs";
208 # define NFS_FILE_STAT(st) (strcmp ((st).st_fstype, nfs_string) == 0)
209 #else
210 # define ST_DEV_MSB(st) (~ (dev_t) 0 << (sizeof (st).st_dev * CHAR_BIT - 1))
211 # define NFS_FILE_STAT(st) (((st).st_dev & ST_DEV_MSB (st)) != 0)
212 #endif
214 /* Calculate the hash of a directory. */
215 static size_t
216 hash_directory_canonical_name (void const *entry, size_t n_buckets)
218 struct directory const *directory = entry;
219 return hash_string (directory->caname, n_buckets);
222 /* Compare two directories for equality of their names. */
223 static bool
224 compare_directory_canonical_names (void const *entry1, void const *entry2)
226 struct directory const *directory1 = entry1;
227 struct directory const *directory2 = entry2;
228 return strcmp (directory1->caname, directory2->caname) == 0;
231 static size_t
232 hash_directory_meta (void const *entry, size_t n_buckets)
234 struct directory const *directory = entry;
235 /* FIXME: Work out a better algorytm */
236 return (directory->device_number + directory->inode_number) % n_buckets;
239 /* Compare two directories for equality of their device and inode numbers. */
240 static bool
241 compare_directory_meta (void const *entry1, void const *entry2)
243 struct directory const *directory1 = entry1;
244 struct directory const *directory2 = entry2;
245 return directory1->device_number == directory2->device_number
246 && directory1->inode_number == directory2->inode_number;
249 /* Make a directory entry for given relative NAME and canonical name CANAME.
250 The latter is "stolen", i.e. the returned directory contains pointer to
251 it. */
252 static struct directory *
253 make_directory (const char *name, char *caname)
255 size_t namelen = strlen (name);
256 struct directory *directory = xmalloc (sizeof (*directory));
257 directory->next = NULL;
258 directory->dump = directory->idump = NULL;
259 directory->orig = NULL;
260 directory->flags = false;
261 if (namelen && ISSLASH (name[namelen - 1]))
262 namelen--;
263 directory->name = xmalloc (namelen + 1);
264 memcpy (directory->name, name, namelen);
265 directory->name[namelen] = 0;
266 directory->caname = caname;
267 directory->tagfile = NULL;
268 return directory;
271 static void
272 free_directory (struct directory *dir)
274 free (dir->caname);
275 free (dir->name);
276 free (dir);
279 static struct directory *
280 attach_directory (const char *name)
282 char *cname = normalize_filename (name);
283 struct directory *dir = make_directory (name, cname);
284 if (dirtail)
285 dirtail->next = dir;
286 else
287 dirhead = dir;
288 dirtail = dir;
289 return dir;
293 static void
294 replace_prefix (char **pname, const char *samp, size_t slen,
295 const char *repl, size_t rlen)
297 char *name = *pname;
298 size_t nlen = strlen (name);
299 if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
301 if (rlen > slen)
303 name = xrealloc (name, nlen - slen + rlen + 1);
304 *pname = name;
306 memmove (name + rlen, name + slen, nlen - slen + 1);
307 memcpy (name, repl, rlen);
311 void
312 dirlist_replace_prefix (const char *pref, const char *repl)
314 struct directory *dp;
315 size_t pref_len = strlen (pref);
316 size_t repl_len = strlen (repl);
317 for (dp = dirhead; dp; dp = dp->next)
318 replace_prefix (&dp->name, pref, pref_len, repl, repl_len);
321 /* Create and link a new directory entry for directory NAME, having a
322 device number DEV and an inode number INO, with NFS indicating
323 whether it is an NFS device and FOUND indicating whether we have
324 found that the directory exists. */
325 static struct directory *
326 note_directory (char const *name, struct timespec mtime,
327 dev_t dev, ino_t ino, bool nfs, bool found,
328 const char *contents)
330 struct directory *directory = attach_directory (name);
332 directory->mtime = mtime;
333 directory->device_number = dev;
334 directory->inode_number = ino;
335 directory->children = CHANGED_CHILDREN;
336 if (nfs)
337 DIR_SET_FLAG (directory, DIRF_NFS);
338 if (found)
339 DIR_SET_FLAG (directory, DIRF_FOUND);
340 if (contents)
341 directory->dump = dumpdir_create (contents);
342 else
343 directory->dump = NULL;
345 if (! ((directory_table
346 || (directory_table = hash_initialize (0, 0,
347 hash_directory_canonical_name,
348 compare_directory_canonical_names, 0)))
349 && hash_insert (directory_table, directory)))
350 xalloc_die ();
352 if (! ((directory_meta_table
353 || (directory_meta_table = hash_initialize (0, 0,
354 hash_directory_meta,
355 compare_directory_meta,
356 0)))
357 && hash_insert (directory_meta_table, directory)))
358 xalloc_die ();
360 return directory;
363 /* Return a directory entry for a given file NAME, or zero if none found. */
364 static struct directory *
365 find_directory (const char *name)
367 if (! directory_table)
368 return 0;
369 else
371 char *caname = normalize_filename (name);
372 struct directory *dir = make_directory (name, caname);
373 struct directory *ret = hash_lookup (directory_table, dir);
374 free_directory (dir);
375 return ret;
379 #if 0
380 /* Remove directory entry for the given CANAME */
381 void
382 remove_directory (const char *caname)
384 struct directory *dir = make_directory (caname, xstrdup (caname));
385 struct directory *ret = hash_delete (directory_table, dir);
386 if (ret)
387 free_directory (ret);
388 free_directory (dir);
390 #endif
392 /* Find a directory entry for NAME. If first OLD_PREFIX_LEN
393 bytes of its name match OLD_PREFIX, replace them with
394 NEW_PREFIX. */
395 void
396 rebase_directory (const char *name, size_t old_prefix_len,
397 const char *old_prefix,
398 const char *new_prefix)
400 struct directory *dir = find_directory (name);
401 if (dir)
402 replace_prefix (&dir->name, old_prefix, old_prefix_len,
403 new_prefix, strlen (new_prefix));
406 /* Return a directory entry for a given combination of device and inode
407 numbers, or zero if none found. */
408 static struct directory *
409 find_directory_meta (dev_t dev, ino_t ino)
411 if (! directory_meta_table)
412 return 0;
413 else
415 struct directory *dir = make_directory ("", NULL);
416 struct directory *ret;
417 dir->device_number = dev;
418 dir->inode_number = ino;
419 ret = hash_lookup (directory_meta_table, dir);
420 free_directory (dir);
421 return ret;
425 void
426 update_parent_directory (const char *name)
428 struct directory *directory;
429 char *p;
431 p = dir_name (name);
432 directory = find_directory (p);
433 if (directory)
435 struct stat st;
436 if (deref_stat (dereference_option, p, &st) != 0)
437 stat_diag (name);
438 else
439 directory->mtime = get_stat_mtime (&st);
441 free (p);
444 #define PD_FORCE_CHILDREN 0x10
445 #define PD_FORCE_INIT 0x20
446 #define PD_CHILDREN(f) ((f) & 3)
448 static struct directory *
449 procdir (const char *name_buffer, struct stat *stat_data,
450 dev_t device,
451 int flag,
452 char *entry)
454 struct directory *directory;
455 bool nfs = NFS_FILE_STAT (*stat_data);
457 if ((directory = find_directory (name_buffer)) != NULL)
459 if (DIR_IS_INITED (directory))
461 if (flag & PD_FORCE_INIT)
463 assign_string (&directory->name, name_buffer);
465 else
467 *entry = 'N'; /* Avoid duplicating this directory */
468 return directory;
472 if (strcmp (directory->name, name_buffer))
474 *entry = 'N';
475 return directory;
478 /* With NFS, the same file can have two different devices
479 if an NFS directory is mounted in multiple locations,
480 which is relatively common when automounting.
481 To avoid spurious incremental redumping of
482 directories, consider all NFS devices as equal,
483 relying on the i-node to establish differences. */
485 if (! ((!check_device_option
486 || (DIR_IS_NFS (directory) && nfs)
487 || directory->device_number == stat_data->st_dev)
488 && directory->inode_number == stat_data->st_ino))
490 /* FIXME: find_directory_meta ignores nfs */
491 struct directory *d = find_directory_meta (stat_data->st_dev,
492 stat_data->st_ino);
493 if (d)
495 if (strcmp (d->name, name_buffer))
497 WARNOPT (WARN_RENAME_DIRECTORY,
498 (0, 0,
499 _("%s: Directory has been renamed from %s"),
500 quotearg_colon (name_buffer),
501 quote_n (1, d->name)));
502 directory->orig = d;
503 DIR_SET_FLAG (directory, DIRF_RENAMED);
504 dirlist_replace_prefix (d->name, name_buffer);
506 directory->children = CHANGED_CHILDREN;
508 else
510 WARNOPT (WARN_RENAME_DIRECTORY,
511 (0, 0, _("%s: Directory has been renamed"),
512 quotearg_colon (name_buffer)));
513 directory->children = ALL_CHILDREN;
514 directory->device_number = stat_data->st_dev;
515 directory->inode_number = stat_data->st_ino;
517 if (nfs)
518 DIR_SET_FLAG (directory, DIRF_NFS);
520 else
521 directory->children = CHANGED_CHILDREN;
523 DIR_SET_FLAG (directory, DIRF_FOUND);
525 else
527 struct directory *d = find_directory_meta (stat_data->st_dev,
528 stat_data->st_ino);
530 directory = note_directory (name_buffer,
531 get_stat_mtime(stat_data),
532 stat_data->st_dev,
533 stat_data->st_ino,
534 nfs,
535 true,
536 NULL);
538 if (d)
540 if (strcmp (d->name, name_buffer))
542 WARNOPT (WARN_RENAME_DIRECTORY,
543 (0, 0, _("%s: Directory has been renamed from %s"),
544 quotearg_colon (name_buffer),
545 quote_n (1, d->name)));
546 directory->orig = d;
547 DIR_SET_FLAG (directory, DIRF_RENAMED);
548 dirlist_replace_prefix (d->name, name_buffer);
550 directory->children = CHANGED_CHILDREN;
552 else
554 DIR_SET_FLAG (directory, DIRF_NEW);
555 WARNOPT (WARN_NEW_DIRECTORY,
556 (0, 0, _("%s: Directory is new"),
557 quotearg_colon (name_buffer)));
558 directory->children =
559 (listed_incremental_option
560 || (OLDER_STAT_TIME (*stat_data, m)
561 || (after_date_option
562 && OLDER_STAT_TIME (*stat_data, c))))
563 ? ALL_CHILDREN
564 : CHANGED_CHILDREN;
568 /* If the directory is on another device and --one-file-system was given,
569 omit it... */
570 if (one_file_system_option && device != stat_data->st_dev
571 /* ... except if it was explicitely given in the command line */
572 && !is_individual_file (name_buffer))
573 directory->children = NO_CHILDREN;
574 else if (flag & PD_FORCE_CHILDREN)
576 directory->children = PD_CHILDREN(flag);
577 if (directory->children == NO_CHILDREN)
578 *entry = 'N';
581 DIR_SET_FLAG (directory, DIRF_INIT);
583 if (directory->children != NO_CHILDREN)
585 const char *tag_file_name;
587 switch (check_exclusion_tags (name_buffer, &tag_file_name))
589 case exclusion_tag_all:
590 /* This warning can be duplicated by code in dump_file0, but only
591 in case when the topmost directory being archived contains
592 an exclusion tag. */
593 exclusion_tag_warning (name_buffer, tag_file_name,
594 _("directory not dumped"));
595 *entry = 'N';
596 directory->children = NO_CHILDREN;
597 break;
599 case exclusion_tag_contents:
600 exclusion_tag_warning (name_buffer, tag_file_name,
601 _("contents not dumped"));
602 directory->children = NO_CHILDREN;
603 break;
605 case exclusion_tag_under:
606 exclusion_tag_warning (name_buffer, tag_file_name,
607 _("contents not dumped"));
608 directory->tagfile = tag_file_name;
609 break;
611 case exclusion_tag_none:
612 break;
616 return directory;
619 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
620 build a new dumpdir template.
622 DIR must be returned by a previous call to savedir().
624 File names in DIRECTORY->dump->contents must be sorted
625 alphabetically.
627 DIRECTORY->dump is replaced with the created template. Each entry is
628 prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
630 void
631 makedumpdir (struct directory *directory, const char *dir)
633 size_t i,
634 dirsize, /* Number of elements in DIR */
635 len; /* Length of DIR, including terminating nul */
636 const char *p;
637 char const **array;
638 char *new_dump, *new_dump_ptr;
639 struct dumpdir *dump;
641 if (directory->children == ALL_CHILDREN)
642 dump = NULL;
643 else if (DIR_IS_RENAMED (directory))
644 dump = directory->orig->idump ?
645 directory->orig->idump : directory->orig->dump;
646 else
647 dump = directory->dump;
649 /* Count the size of DIR and the number of elements it contains */
650 dirsize = 0;
651 len = 0;
652 for (p = dir; *p; p += strlen (p) + 1, dirsize++)
653 len += strlen (p) + 2;
654 len++;
656 /* Create a sorted directory listing */
657 array = xcalloc (dirsize, sizeof array[0]);
658 for (i = 0, p = dir; *p; p += strlen (p) + 1, i++)
659 array[i] = p;
661 qsort (array, dirsize, sizeof (array[0]), compare_dirnames);
663 /* Prepare space for new dumpdir */
664 new_dump = xmalloc (len);
665 new_dump_ptr = new_dump;
667 /* Fill in the dumpdir template */
668 for (i = 0; i < dirsize; i++)
670 const char *loc = dumpdir_locate (dump, array[i]);
671 if (loc)
673 if (directory->tagfile)
674 *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
675 ' ' : 'I';
676 else
677 *new_dump_ptr = ' ';
678 new_dump_ptr++;
680 else if (directory->tagfile)
681 *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
682 ' ' : 'I';
683 else
684 *new_dump_ptr++ = 'Y'; /* New entry */
686 /* Copy the file name */
687 for (p = array[i]; (*new_dump_ptr++ = *p++); )
690 *new_dump_ptr = 0;
691 directory->idump = directory->dump;
692 directory->dump = dumpdir_create0 (new_dump, NULL);
693 free (array);
696 /* Recursively scan the given directory DIR.
697 DEVICE is the device number where DIR resides (for --one-file-system).
698 If CMDLINE is true, the directory name was explicitly listed in the
699 command line. */
700 const char *
701 scan_directory (char *dir, dev_t device, bool cmdline)
703 char *dirp = savedir (dir); /* for scanning directory */
704 char *name_buffer; /* directory, `/', and directory member */
705 size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */
706 size_t name_length; /* used length in name_buffer */
707 struct stat stat_data;
708 struct directory *directory;
709 char ch;
711 if (! dirp)
712 savedir_error (dir);
714 name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
715 name_buffer = xmalloc (name_buffer_size + 2);
716 strcpy (name_buffer, dir);
717 zap_slashes (name_buffer);
719 if (deref_stat (dereference_option, name_buffer, &stat_data))
721 stat_diag (name_buffer);
722 /* FIXME: used to be
723 children = CHANGED_CHILDREN;
724 but changed to: */
725 free (name_buffer);
726 free (dirp);
727 return NULL;
730 directory = procdir (name_buffer, &stat_data, device,
731 (cmdline ? PD_FORCE_INIT : 0),
732 &ch);
734 name_length = strlen (name_buffer);
735 if (! ISSLASH (name_buffer[name_length - 1]))
737 name_buffer[name_length] = DIRECTORY_SEPARATOR;
738 /* name_buffer has been allocated an extra slot */
739 name_buffer[++name_length] = 0;
742 if (dirp && directory->children != NO_CHILDREN)
744 char *entry; /* directory entry being scanned */
745 size_t entrylen; /* length of directory entry */
746 dumpdir_iter_t itr;
748 makedumpdir (directory, dirp);
750 for (entry = dumpdir_first (directory->dump, 1, &itr);
751 entry;
752 entry = dumpdir_next (itr))
754 entrylen = strlen (entry);
755 if (name_buffer_size <= entrylen - 1 + name_length)
758 name_buffer_size += NAME_FIELD_SIZE;
759 while (name_buffer_size <= entrylen - 1 + name_length);
760 name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
762 strcpy (name_buffer + name_length, entry + 1);
764 if (*entry == 'I') /* Ignored entry */
765 *entry = 'N';
766 else if (excluded_name (name_buffer))
767 *entry = 'N';
768 else
770 if (deref_stat (dereference_option, name_buffer, &stat_data))
772 stat_diag (name_buffer);
773 *entry = 'N';
774 continue;
777 if (S_ISDIR (stat_data.st_mode))
779 int pd_flag = 0;
780 if (!recursion_option)
781 pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
782 else if (directory->children == ALL_CHILDREN)
783 pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
784 *entry = 'D';
785 procdir (name_buffer, &stat_data, device, pd_flag, entry);
788 else if (one_file_system_option && device != stat_data.st_dev)
789 *entry = 'N';
791 else if (*entry == 'Y')
792 /* New entry, skip further checks */;
794 /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
796 else if (OLDER_STAT_TIME (stat_data, m)
797 && (!after_date_option
798 || OLDER_STAT_TIME (stat_data, c)))
799 *entry = 'N';
800 else
801 *entry = 'Y';
804 free (itr);
807 free (name_buffer);
808 if (dirp)
809 free (dirp);
811 return directory->dump ? directory->dump->contents : NULL;
814 const char *
815 get_directory_contents (char *dir, dev_t device, bool force)
817 return scan_directory (dir, device, force);
821 static void
822 obstack_code_rename (struct obstack *stk, char *from, char *to)
824 char *s;
826 s = from[0] == 0 ? from :
827 safer_name_suffix (from, false, absolute_names_option);
828 obstack_1grow (stk, 'R');
829 obstack_grow (stk, s, strlen (s) + 1);
831 s = to[0] == 0 ? to:
832 safer_name_suffix (to, false, absolute_names_option);
833 obstack_1grow (stk, 'T');
834 obstack_grow (stk, s, strlen (s) + 1);
837 static void
838 store_rename (struct directory *dir, struct obstack *stk)
840 if (DIR_IS_RENAMED (dir))
842 struct directory *prev, *p;
844 /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries
845 are ignored when hit by this function next time.
846 If the chain forms a cycle, prev points to the entry DIR is renamed
847 from. In this case it still retains DIRF_RENAMED flag, which will be
848 cleared in the `else' branch below */
849 for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
850 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
852 if (prev == NULL)
854 for (p = dir; p && p->orig; p = p->orig)
855 obstack_code_rename (stk, p->orig->name, p->name);
857 else
859 char *temp_name;
861 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
863 /* Break the cycle by using a temporary name for one of its
864 elements.
865 First, create a temp name stub entry. */
866 temp_name = dir_name (dir->name);
867 obstack_1grow (stk, 'X');
868 obstack_grow (stk, temp_name, strlen (temp_name) + 1);
870 obstack_code_rename (stk, dir->name, "");
872 for (p = dir; p != prev; p = p->orig)
873 obstack_code_rename (stk, p->orig->name, p->name);
875 obstack_code_rename (stk, "", prev->name);
880 const char *
881 append_incremental_renames (const char *dump)
883 struct obstack stk;
884 size_t size;
885 struct directory *dp;
887 if (dirhead == NULL)
888 return dump;
890 obstack_init (&stk);
891 if (dump)
893 size = dumpdir_size (dump) - 1;
894 obstack_grow (&stk, dump, size);
896 else
897 size = 0;
899 for (dp = dirhead; dp; dp = dp->next)
900 store_rename (dp, &stk);
902 if (obstack_object_size (&stk) != size)
904 obstack_1grow (&stk, 0);
905 dump = obstack_finish (&stk);
907 else
908 obstack_free (&stk, NULL);
909 return dump;
914 static FILE *listed_incremental_stream;
916 /* Version of incremental format snapshots (directory files) used by this
917 tar. Currently it is supposed to be a single decimal number. 0 means
918 incremental snapshots as per tar version before 1.15.2.
920 The current tar version supports incremental versions from
921 0 up to TAR_INCREMENTAL_VERSION, inclusive.
922 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
924 #define TAR_INCREMENTAL_VERSION 2
926 /* Read incremental snapshot formats 0 and 1 */
927 static void
928 read_incr_db_01 (int version, const char *initbuf)
930 int n;
931 uintmax_t u;
932 time_t sec;
933 long int nsec;
934 char *buf = 0;
935 size_t bufsize;
936 char *ebuf;
937 long lineno = 1;
939 if (version == 1)
941 if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)
943 read_error (listed_incremental_option);
944 free (buf);
945 return;
947 ++lineno;
949 else
951 buf = strdup (initbuf);
952 bufsize = strlen (buf) + 1;
955 sec = TYPE_MINIMUM (time_t);
956 nsec = -1;
957 errno = 0;
958 u = strtoumax (buf, &ebuf, 10);
959 if (!errno && TYPE_MAXIMUM (time_t) < u)
960 errno = ERANGE;
961 if (errno || buf == ebuf)
962 ERROR ((0, errno, "%s:%ld: %s",
963 quotearg_colon (listed_incremental_option),
964 lineno,
965 _("Invalid time stamp")));
966 else
968 sec = u;
970 if (version == 1 && *ebuf)
972 char const *buf_ns = ebuf + 1;
973 errno = 0;
974 u = strtoumax (buf_ns, &ebuf, 10);
975 if (!errno && BILLION <= u)
976 errno = ERANGE;
977 if (errno || buf_ns == ebuf)
979 ERROR ((0, errno, "%s:%ld: %s",
980 quotearg_colon (listed_incremental_option),
981 lineno,
982 _("Invalid time stamp")));
983 sec = TYPE_MINIMUM (time_t);
985 else
986 nsec = u;
988 else
990 /* pre-1 incremental format does not contain nanoseconds */
991 nsec = 0;
994 newer_mtime_option.tv_sec = sec;
995 newer_mtime_option.tv_nsec = nsec;
998 while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
1000 dev_t dev;
1001 ino_t ino;
1002 bool nfs = buf[0] == '+';
1003 char *strp = buf + nfs;
1004 struct timespec mtime;
1006 lineno++;
1008 if (buf[n - 1] == '\n')
1009 buf[n - 1] = '\0';
1011 if (version == 1)
1013 errno = 0;
1014 u = strtoumax (strp, &ebuf, 10);
1015 if (!errno && TYPE_MAXIMUM (time_t) < u)
1016 errno = ERANGE;
1017 if (errno || strp == ebuf || *ebuf != ' ')
1019 ERROR ((0, errno, "%s:%ld: %s",
1020 quotearg_colon (listed_incremental_option), lineno,
1021 _("Invalid modification time (seconds)")));
1022 sec = (time_t) -1;
1024 else
1025 sec = u;
1026 strp = ebuf;
1028 errno = 0;
1029 u = strtoumax (strp, &ebuf, 10);
1030 if (!errno && BILLION <= u)
1031 errno = ERANGE;
1032 if (errno || strp == ebuf || *ebuf != ' ')
1034 ERROR ((0, errno, "%s:%ld: %s",
1035 quotearg_colon (listed_incremental_option), lineno,
1036 _("Invalid modification time (nanoseconds)")));
1037 nsec = -1;
1039 else
1040 nsec = u;
1041 mtime.tv_sec = sec;
1042 mtime.tv_nsec = nsec;
1043 strp = ebuf;
1045 else
1046 memset (&mtime, 0, sizeof mtime);
1048 errno = 0;
1049 u = strtoumax (strp, &ebuf, 10);
1050 if (!errno && TYPE_MAXIMUM (dev_t) < u)
1051 errno = ERANGE;
1052 if (errno || strp == ebuf || *ebuf != ' ')
1054 ERROR ((0, errno, "%s:%ld: %s",
1055 quotearg_colon (listed_incremental_option), lineno,
1056 _("Invalid device number")));
1057 dev = (dev_t) -1;
1059 else
1060 dev = u;
1061 strp = ebuf;
1063 errno = 0;
1064 u = strtoumax (strp, &ebuf, 10);
1065 if (!errno && TYPE_MAXIMUM (ino_t) < u)
1066 errno = ERANGE;
1067 if (errno || strp == ebuf || *ebuf != ' ')
1069 ERROR ((0, errno, "%s:%ld: %s",
1070 quotearg_colon (listed_incremental_option), lineno,
1071 _("Invalid inode number")));
1072 ino = (ino_t) -1;
1074 else
1075 ino = u;
1076 strp = ebuf;
1078 strp++;
1079 unquote_string (strp);
1080 note_directory (strp, mtime, dev, ino, nfs, false, NULL);
1082 free (buf);
1085 /* Read a nul-terminated string from FP and store it in STK.
1086 Store the number of bytes read (including nul terminator) in PCOUNT.
1088 Return the last character read or EOF on end of file. */
1089 static int
1090 read_obstack (FILE *fp, struct obstack *stk, size_t *pcount)
1092 int c;
1093 size_t i;
1095 for (i = 0, c = getc (fp); c != EOF && c != 0; c = getc (fp), i++)
1096 obstack_1grow (stk, c);
1097 obstack_1grow (stk, 0);
1099 *pcount = i;
1100 return c;
1103 /* Read from file FP a nul-terminated string and convert it to
1104 intmax_t. Return the resulting value in PVAL. Assume '-' has
1105 already been read.
1107 Throw a fatal error if the string cannot be converted or if the
1108 converted value is less than MIN_VAL. */
1110 static void
1111 read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
1113 int c;
1114 size_t i;
1115 char buf[INT_BUFSIZE_BOUND (intmax_t)];
1116 char *ep;
1117 buf[0] = '-';
1119 for (i = 1; ISDIGIT (c = getc (fp)); i++)
1121 if (i == sizeof buf - 1)
1122 FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1123 buf[i] = c;
1126 if (c < 0)
1128 if (ferror (fp))
1129 FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1130 else
1131 FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1134 buf[i] = 0;
1135 errno = 0;
1136 *pval = strtoimax (buf, &ep, 10);
1137 if (c || errno || *pval < min_val)
1138 FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1141 /* Read from file FP a nul-terminated string and convert it to
1142 uintmax_t. Return the resulting value in PVAL. Assume C has
1143 already been read.
1145 Throw a fatal error if the string cannot be converted or if the
1146 converted value exceeds MAX_VAL.
1148 Return the last character read or EOF on end of file. */
1150 static int
1151 read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
1153 size_t i;
1154 char buf[UINTMAX_STRSIZE_BOUND], *ep;
1156 for (i = 0; ISDIGIT (c); i++)
1158 if (i == sizeof buf - 1)
1159 FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1160 buf[i] = c;
1161 c = getc (fp);
1164 if (c < 0)
1166 if (ferror (fp))
1167 FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1168 else if (i == 0)
1169 return c;
1170 else
1171 FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1174 buf[i] = 0;
1175 errno = 0;
1176 *pval = strtoumax (buf, &ep, 10);
1177 if (c || errno || max_val < *pval)
1178 FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1179 return c;
1182 /* Read from file FP a nul-terminated string and convert it to
1183 uintmax_t. Return the resulting value in PVAL.
1185 Throw a fatal error if the string cannot be converted or if the
1186 converted value exceeds MAX_VAL.
1188 Return the last character read or EOF on end of file. */
1190 static int
1191 read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
1193 return read_unsigned_num (getc (fp), fp, max_val, pval);
1196 /* Read from FP two NUL-terminated strings representing a struct
1197 timespec. Return the resulting value in PVAL.
1199 Throw a fatal error if the string cannot be converted. */
1201 static void
1202 read_timespec (FILE *fp, struct timespec *pval)
1204 int c = getc (fp);
1205 intmax_t i;
1206 uintmax_t u;
1208 if (c == '-')
1210 read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
1211 c = 0;
1212 pval->tv_sec = i;
1214 else
1216 c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
1217 pval->tv_sec = u;
1220 if (c || read_num (fp, BILLION - 1, &u))
1221 FATAL_ERROR ((0, 0, "%s: %s",
1222 quotearg_colon (listed_incremental_option),
1223 _("Unexpected EOF in snapshot file")));
1224 pval->tv_nsec = u;
1227 /* Read incremental snapshot format 2 */
1228 static void
1229 read_incr_db_2 ()
1231 uintmax_t u;
1232 struct obstack stk;
1234 obstack_init (&stk);
1236 read_timespec (listed_incremental_stream, &newer_mtime_option);
1238 for (;;)
1240 struct timespec mtime;
1241 dev_t dev;
1242 ino_t ino;
1243 bool nfs;
1244 char *name;
1245 char *content;
1246 size_t s;
1248 if (read_num (listed_incremental_stream, 1, &u))
1249 return; /* Normal return */
1251 nfs = u;
1253 read_timespec (listed_incremental_stream, &mtime);
1255 if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
1256 break;
1257 dev = u;
1259 if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
1260 break;
1261 ino = u;
1263 if (read_obstack (listed_incremental_stream, &stk, &s))
1264 break;
1266 name = obstack_finish (&stk);
1268 while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
1270 if (getc (listed_incremental_stream) != 0)
1271 FATAL_ERROR ((0, 0, "%s: %s",
1272 quotearg_colon (listed_incremental_option),
1273 _("Missing record terminator")));
1275 content = obstack_finish (&stk);
1276 note_directory (name, mtime, dev, ino, nfs, false, content);
1277 obstack_free (&stk, content);
1279 FATAL_ERROR ((0, 0, "%s: %s",
1280 quotearg_colon (listed_incremental_option),
1281 _("Unexpected EOF in snapshot file")));
1284 /* Read incremental snapshot file (directory file).
1285 If the file has older incremental version, make sure that it is processed
1286 correctly and that tar will use the most conservative backup method among
1287 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
1288 etc.) This ensures that the snapshots are updated to the recent version
1289 without any loss of data. */
1290 void
1291 read_directory_file (void)
1293 int fd;
1294 char *buf = 0;
1295 size_t bufsize;
1296 int flags = O_RDWR | O_CREAT;
1298 if (incremental_level == 0)
1299 flags |= O_TRUNC;
1300 /* Open the file for both read and write. That way, we can write
1301 it later without having to reopen it, and don't have to worry if
1302 we chdir in the meantime. */
1303 fd = open (listed_incremental_option, flags, MODE_RW);
1304 if (fd < 0)
1306 open_error (listed_incremental_option);
1307 return;
1310 listed_incremental_stream = fdopen (fd, "r+");
1311 if (! listed_incremental_stream)
1313 open_error (listed_incremental_option);
1314 close (fd);
1315 return;
1318 if (0 < getline (&buf, &bufsize, listed_incremental_stream))
1320 char *ebuf;
1321 uintmax_t incremental_version;
1323 if (strncmp (buf, PACKAGE_NAME, sizeof PACKAGE_NAME - 1) == 0)
1325 ebuf = buf + sizeof PACKAGE_NAME - 1;
1326 if (*ebuf++ != '-')
1327 ERROR((1, 0, _("Bad incremental file format")));
1328 for (; *ebuf != '-'; ebuf++)
1329 if (!*ebuf)
1330 ERROR((1, 0, _("Bad incremental file format")));
1332 incremental_version = strtoumax (ebuf + 1, NULL, 10);
1334 else
1335 incremental_version = 0;
1337 switch (incremental_version)
1339 case 0:
1340 case 1:
1341 read_incr_db_01 (incremental_version, buf);
1342 break;
1344 case TAR_INCREMENTAL_VERSION:
1345 read_incr_db_2 ();
1346 break;
1348 default:
1349 ERROR ((1, 0, _("Unsupported incremental format version: %"PRIuMAX),
1350 incremental_version));
1355 if (ferror (listed_incremental_stream))
1356 read_error (listed_incremental_option);
1357 if (buf)
1358 free (buf);
1361 /* Output incremental data for the directory ENTRY to the file DATA.
1362 Return nonzero if successful, preserving errno on write failure. */
1363 static bool
1364 write_directory_file_entry (void *entry, void *data)
1366 struct directory const *directory = entry;
1367 FILE *fp = data;
1369 if (DIR_IS_FOUND (directory))
1371 char buf[UINTMAX_STRSIZE_BOUND];
1372 char *s;
1374 s = DIR_IS_NFS (directory) ? "1" : "0";
1375 fwrite (s, 2, 1, fp);
1376 s = (TYPE_SIGNED (time_t)
1377 ? imaxtostr (directory->mtime.tv_sec, buf)
1378 : umaxtostr (directory->mtime.tv_sec, buf));
1379 fwrite (s, strlen (s) + 1, 1, fp);
1380 s = umaxtostr (directory->mtime.tv_nsec, buf);
1381 fwrite (s, strlen (s) + 1, 1, fp);
1382 s = umaxtostr (directory->device_number, buf);
1383 fwrite (s, strlen (s) + 1, 1, fp);
1384 s = umaxtostr (directory->inode_number, buf);
1385 fwrite (s, strlen (s) + 1, 1, fp);
1387 fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
1388 if (directory->dump)
1390 const char *p;
1391 dumpdir_iter_t itr;
1393 for (p = dumpdir_first (directory->dump, 0, &itr);
1395 p = dumpdir_next (itr))
1396 fwrite (p, strlen (p) + 1, 1, fp);
1397 free (itr);
1399 fwrite ("\0\0", 2, 1, fp);
1402 return ! ferror (fp);
1405 void
1406 write_directory_file (void)
1408 FILE *fp = listed_incremental_stream;
1409 char buf[UINTMAX_STRSIZE_BOUND];
1410 char *s;
1412 if (! fp)
1413 return;
1415 if (fseek (fp, 0L, SEEK_SET) != 0)
1416 seek_error (listed_incremental_option);
1417 if (sys_truncate (fileno (fp)) != 0)
1418 truncate_error (listed_incremental_option);
1420 fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION,
1421 TAR_INCREMENTAL_VERSION);
1423 s = (TYPE_SIGNED (time_t)
1424 ? imaxtostr (start_time.tv_sec, buf)
1425 : umaxtostr (start_time.tv_sec, buf));
1426 fwrite (s, strlen (s) + 1, 1, fp);
1427 s = umaxtostr (start_time.tv_nsec, buf);
1428 fwrite (s, strlen (s) + 1, 1, fp);
1430 if (! ferror (fp) && directory_table)
1431 hash_do_for_each (directory_table, write_directory_file_entry, fp);
1433 if (ferror (fp))
1434 write_error (listed_incremental_option);
1435 if (fclose (fp) != 0)
1436 close_error (listed_incremental_option);
1440 /* Restoration of incremental dumps. */
1442 static void
1443 get_gnu_dumpdir (struct tar_stat_info *stat_info)
1445 size_t size;
1446 size_t copied;
1447 union block *data_block;
1448 char *to;
1449 char *archive_dir;
1451 size = stat_info->stat.st_size;
1453 archive_dir = xmalloc (size);
1454 to = archive_dir;
1456 set_next_block_after (current_header);
1457 mv_begin (stat_info);
1459 for (; size > 0; size -= copied)
1461 mv_size_left (size);
1462 data_block = find_next_block ();
1463 if (!data_block)
1464 ERROR ((1, 0, _("Unexpected EOF in archive")));
1465 copied = available_space_after (data_block);
1466 if (copied > size)
1467 copied = size;
1468 memcpy (to, data_block->buffer, copied);
1469 to += copied;
1470 set_next_block_after ((union block *)
1471 (data_block->buffer + copied - 1));
1474 mv_end ();
1476 stat_info->dumpdir = archive_dir;
1477 stat_info->skipped = true; /* For skip_member() and friends
1478 to work correctly */
1481 /* Return T if STAT_INFO represents a dumpdir archive member.
1482 Note: can invalidate current_header. It happens if flush_archive()
1483 gets called within get_gnu_dumpdir() */
1484 bool
1485 is_dumpdir (struct tar_stat_info *stat_info)
1487 if (stat_info->is_dumpdir && !stat_info->dumpdir)
1488 get_gnu_dumpdir (stat_info);
1489 return stat_info->is_dumpdir;
1492 static bool
1493 dumpdir_ok (char *dumpdir)
1495 char *p;
1496 int has_tempdir = 0;
1497 int expect = 0;
1499 for (p = dumpdir; *p; p += strlen (p) + 1)
1501 if (expect && *p != expect)
1503 ERROR ((0, 0,
1504 _("Malformed dumpdir: expected '%c' but found %#3o"),
1505 expect, *p));
1506 return false;
1508 switch (*p)
1510 case 'X':
1511 if (has_tempdir)
1513 ERROR ((0, 0,
1514 _("Malformed dumpdir: 'X' duplicated")));
1515 return false;
1517 else
1518 has_tempdir = 1;
1519 break;
1521 case 'R':
1522 if (p[1] == 0)
1524 if (!has_tempdir)
1526 ERROR ((0, 0,
1527 _("Malformed dumpdir: empty name in 'R'")));
1528 return false;
1530 else
1531 has_tempdir = 0;
1533 expect = 'T';
1534 break;
1536 case 'T':
1537 if (expect != 'T')
1539 ERROR ((0, 0,
1540 _("Malformed dumpdir: 'T' not preceeded by 'R'")));
1541 return false;
1543 if (p[1] == 0 && !has_tempdir)
1545 ERROR ((0, 0,
1546 _("Malformed dumpdir: empty name in 'T'")));
1547 return false;
1549 expect = 0;
1550 break;
1552 case 'N':
1553 case 'Y':
1554 case 'D':
1555 break;
1557 default:
1558 /* FIXME: bail out? */
1559 break;
1563 if (expect)
1565 ERROR ((0, 0,
1566 _("Malformed dumpdir: expected '%c' but found end of data"),
1567 expect));
1568 return false;
1571 if (has_tempdir)
1572 WARNOPT (WARN_BAD_DUMPDIR,
1573 (0, 0, _("Malformed dumpdir: 'X' never used")));
1575 return true;
1578 /* Examine the directories under directory_name and delete any
1579 files that were not there at the time of the back-up. */
1580 static bool
1581 try_purge_directory (char const *directory_name)
1583 char *current_dir;
1584 char *cur, *arc, *p;
1585 char *temp_stub = NULL;
1586 struct dumpdir *dump;
1588 if (!is_dumpdir (&current_stat_info))
1589 return false;
1591 current_dir = savedir (directory_name);
1593 if (!current_dir)
1594 /* The directory doesn't exist now. It'll be created. In any
1595 case, we don't have to delete any files out of it. */
1596 return false;
1598 /* Verify if dump directory is sane */
1599 if (!dumpdir_ok (current_stat_info.dumpdir))
1600 return false;
1602 /* Process renames */
1603 for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
1605 if (*arc == 'X')
1607 #define TEMP_DIR_TEMPLATE "tar.XXXXXX"
1608 size_t len = strlen (arc + 1);
1609 temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
1610 memcpy (temp_stub, arc + 1, len);
1611 temp_stub[len] = '/';
1612 memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
1613 sizeof TEMP_DIR_TEMPLATE);
1614 if (!mkdtemp (temp_stub))
1616 ERROR ((0, errno,
1617 _("Cannot create temporary directory using template %s"),
1618 quote (temp_stub)));
1619 free (temp_stub);
1620 free (current_dir);
1621 return false;
1624 else if (*arc == 'R')
1626 char *src, *dst;
1627 src = arc + 1;
1628 arc += strlen (arc) + 1;
1629 dst = arc + 1;
1631 /* Ensure that neither source nor destination are absolute file
1632 names (unless permitted by -P option), and that they do not
1633 contain dubious parts (e.g. ../).
1635 This is an extra safety precaution. Besides, it might be
1636 necessary to extract from archives created with tar versions
1637 prior to 1.19. */
1639 if (*src)
1640 src = safer_name_suffix (src, false, absolute_names_option);
1641 if (*dst)
1642 dst = safer_name_suffix (dst, false, absolute_names_option);
1644 if (*src == 0)
1645 src = temp_stub;
1646 else if (*dst == 0)
1647 dst = temp_stub;
1649 if (!rename_directory (src, dst))
1651 free (temp_stub);
1652 free (current_dir);
1653 /* FIXME: Make sure purge_directory(dst) will return
1654 immediately */
1655 return false;
1660 free (temp_stub);
1662 /* Process deletes */
1663 dump = dumpdir_create (current_stat_info.dumpdir);
1664 p = NULL;
1665 for (cur = current_dir; *cur; cur += strlen (cur) + 1)
1667 const char *entry;
1668 struct stat st;
1669 if (p)
1670 free (p);
1671 p = new_name (directory_name, cur);
1673 if (deref_stat (false, p, &st))
1675 if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
1676 dirs and check it here? */
1678 stat_diag (p);
1679 WARN ((0, 0, _("%s: Not purging directory: unable to stat"),
1680 quotearg_colon (p)));
1682 continue;
1685 if (!(entry = dumpdir_locate (dump, cur))
1686 || (*entry == 'D' && !S_ISDIR (st.st_mode))
1687 || (*entry == 'Y' && S_ISDIR (st.st_mode)))
1689 if (one_file_system_option && st.st_dev != root_device)
1691 WARN ((0, 0,
1692 _("%s: directory is on a different device: not purging"),
1693 quotearg_colon (p)));
1694 continue;
1697 if (! interactive_option || confirm ("delete", p))
1699 if (verbose_option)
1700 fprintf (stdlis, _("%s: Deleting %s\n"),
1701 program_name, quote (p));
1702 if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
1704 int e = errno;
1705 ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));
1710 free (p);
1711 dumpdir_free (dump);
1713 free (current_dir);
1714 return true;
1717 void
1718 purge_directory (char const *directory_name)
1720 if (!try_purge_directory (directory_name))
1721 skip_member ();
1724 void
1725 list_dumpdir (char *buffer, size_t size)
1727 int state = 0;
1728 while (size)
1730 switch (*buffer)
1732 case 'Y':
1733 case 'N':
1734 case 'D':
1735 case 'R':
1736 case 'T':
1737 case 'X':
1738 fprintf (stdlis, "%c", *buffer);
1739 if (state == 0)
1741 fprintf (stdlis, " ");
1742 state = 1;
1744 buffer++;
1745 size--;
1746 break;
1748 case 0:
1749 fputc ('\n', stdlis);
1750 buffer++;
1751 size--;
1752 state = 0;
1753 break;
1755 default:
1756 fputc (*buffer, stdlis);
1757 buffer++;
1758 size--;