Fix creation of incremental archives when a subdirectory becomes a mountpoint.
[tar.git] / src / incremen.c
blobd5bc1e41d88fa6c0d8067da6d27a62f6a60e3774
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) FIXME: not used */
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 static 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 static struct dumpdir *
112 dumpdir_create (const char *contents)
114 return dumpdir_create0 (contents, "YND");
117 static 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 static 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 static 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 static 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 > 1 && 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 dirlist_replace_prefix (const char *pref, const char *repl)
296 struct directory *dp;
297 size_t pref_len = strlen (pref);
298 size_t repl_len = strlen (repl);
299 for (dp = dirhead; dp; dp = dp->next)
300 replace_prefix (&dp->name, pref, pref_len, repl, repl_len);
303 void
304 clear_directory_table (void)
306 struct directory *dp;
308 if (directory_table)
309 hash_clear (directory_table);
310 if (directory_meta_table)
311 hash_clear (directory_meta_table);
312 for (dp = dirhead; dp; )
314 struct directory *next = dp->next;
315 free_directory (dp);
316 dp = next;
318 dirhead = dirtail = NULL;
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,
349 0)))
350 && hash_insert (directory_table, directory)))
351 xalloc_die ();
353 if (! ((directory_meta_table
354 || (directory_meta_table = hash_initialize (0, 0,
355 hash_directory_meta,
356 compare_directory_meta,
357 0)))
358 && hash_insert (directory_meta_table, directory)))
359 xalloc_die ();
361 return directory;
364 /* Return a directory entry for a given file NAME, or zero if none found. */
365 static struct directory *
366 find_directory (const char *name)
368 if (! directory_table)
369 return 0;
370 else
372 char *caname = normalize_filename (name);
373 struct directory *dir = make_directory (name, caname);
374 struct directory *ret = hash_lookup (directory_table, dir);
375 free_directory (dir);
376 return ret;
380 #if 0
381 /* Remove directory entry for the given CANAME */
382 void
383 remove_directory (const char *caname)
385 struct directory *dir = make_directory (caname, xstrdup (caname));
386 struct directory *ret = hash_delete (directory_table, dir);
387 if (ret)
388 free_directory (ret);
389 free_directory (dir);
391 #endif
393 /* If first OLD_PREFIX_LEN bytes of DIR->NAME name match OLD_PREFIX,
394 replace them with NEW_PREFIX. */
395 void
396 rebase_directory (struct directory *dir,
397 const char *old_prefix, size_t old_prefix_len,
398 const char *new_prefix, size_t new_prefix_len)
400 replace_prefix (&dir->name, old_prefix, old_prefix_len,
401 new_prefix, new_prefix_len);
404 /* Return a directory entry for a given combination of device and inode
405 numbers, or zero if none found. */
406 static struct directory *
407 find_directory_meta (dev_t dev, ino_t ino)
409 if (! directory_meta_table)
410 return 0;
411 else
413 struct directory *dir = make_directory ("", NULL);
414 struct directory *ret;
415 dir->device_number = dev;
416 dir->inode_number = ino;
417 ret = hash_lookup (directory_meta_table, dir);
418 free_directory (dir);
419 return ret;
423 void
424 update_parent_directory (struct tar_stat_info *parent)
426 struct directory *directory = find_directory (parent->orig_file_name);
427 if (directory)
429 struct stat st;
430 if (fstat (parent->fd, &st) != 0)
431 stat_diag (directory->name);
432 else
433 directory->mtime = get_stat_mtime (&st);
437 #define PD_FORCE_CHILDREN 0x10
438 #define PD_FORCE_INIT 0x20
439 #define PD_CHILDREN(f) ((f) & 3)
441 static struct directory *
442 procdir (const char *name_buffer, struct tar_stat_info *st,
443 int flag,
444 char *entry)
446 struct directory *directory;
447 struct stat *stat_data = &st->stat;
448 bool nfs = NFS_FILE_STAT (*stat_data);
449 bool perhaps_renamed = false;
451 if ((directory = find_directory (name_buffer)) != NULL)
453 if (DIR_IS_INITED (directory))
455 if (flag & PD_FORCE_INIT)
457 assign_string (&directory->name, name_buffer);
459 else
461 *entry = 'N'; /* Avoid duplicating this directory */
462 return directory;
466 if (strcmp (directory->name, name_buffer))
468 *entry = 'N';
469 return directory;
472 /* With NFS, the same file can have two different devices
473 if an NFS directory is mounted in multiple locations,
474 which is relatively common when automounting.
475 To avoid spurious incremental redumping of
476 directories, consider all NFS devices as equal,
477 relying on the i-node to establish differences. */
479 if (! ((!check_device_option
480 || (DIR_IS_NFS (directory) && nfs)
481 || directory->device_number == stat_data->st_dev)
482 && directory->inode_number == stat_data->st_ino))
484 /* FIXME: find_directory_meta ignores nfs */
485 struct directory *d = find_directory_meta (stat_data->st_dev,
486 stat_data->st_ino);
487 if (d)
489 if (strcmp (d->name, name_buffer))
491 WARNOPT (WARN_RENAME_DIRECTORY,
492 (0, 0,
493 _("%s: Directory has been renamed from %s"),
494 quotearg_colon (name_buffer),
495 quote_n (1, d->name)));
496 directory->orig = d;
497 DIR_SET_FLAG (directory, DIRF_RENAMED);
498 dirlist_replace_prefix (d->name, name_buffer);
500 directory->children = CHANGED_CHILDREN;
502 else
504 perhaps_renamed = true;
505 directory->children = ALL_CHILDREN;
506 directory->device_number = stat_data->st_dev;
507 directory->inode_number = stat_data->st_ino;
509 if (nfs)
510 DIR_SET_FLAG (directory, DIRF_NFS);
512 else
513 directory->children = CHANGED_CHILDREN;
515 DIR_SET_FLAG (directory, DIRF_FOUND);
517 else
519 struct directory *d = find_directory_meta (stat_data->st_dev,
520 stat_data->st_ino);
522 directory = note_directory (name_buffer,
523 get_stat_mtime(stat_data),
524 stat_data->st_dev,
525 stat_data->st_ino,
526 nfs,
527 true,
528 NULL);
530 if (d)
532 if (strcmp (d->name, name_buffer))
534 WARNOPT (WARN_RENAME_DIRECTORY,
535 (0, 0, _("%s: Directory has been renamed from %s"),
536 quotearg_colon (name_buffer),
537 quote_n (1, d->name)));
538 directory->orig = d;
539 DIR_SET_FLAG (directory, DIRF_RENAMED);
540 dirlist_replace_prefix (d->name, name_buffer);
542 directory->children = CHANGED_CHILDREN;
544 else
546 DIR_SET_FLAG (directory, DIRF_NEW);
547 WARNOPT (WARN_NEW_DIRECTORY,
548 (0, 0, _("%s: Directory is new"),
549 quotearg_colon (name_buffer)));
550 directory->children =
551 (listed_incremental_option
552 || (OLDER_STAT_TIME (*stat_data, m)
553 || (after_date_option
554 && OLDER_STAT_TIME (*stat_data, c))))
555 ? ALL_CHILDREN
556 : CHANGED_CHILDREN;
560 if (one_file_system_option && st->parent
561 && stat_data->st_dev != st->parent->stat.st_dev)
563 WARNOPT (WARN_XDEV,
564 (0, 0,
565 _("%s: directory is on a different filesystem; not dumped"),
566 quotearg_colon (directory->name)));
567 directory->children = NO_CHILDREN;
568 /* If there is any dumpdir info in that directory, remove it */
569 if (directory->dump)
571 dumpdir_free (directory->dump);
572 directory->dump = NULL;
574 perhaps_renamed = false;
577 else if (flag & PD_FORCE_CHILDREN)
579 directory->children = PD_CHILDREN(flag);
580 if (directory->children == NO_CHILDREN)
581 *entry = 'N';
584 if (perhaps_renamed)
585 WARNOPT (WARN_RENAME_DIRECTORY,
586 (0, 0, _("%s: Directory has been renamed"),
587 quotearg_colon (name_buffer)));
589 DIR_SET_FLAG (directory, DIRF_INIT);
591 if (directory->children != NO_CHILDREN)
593 const char *tag_file_name;
595 switch (check_exclusion_tags (st, &tag_file_name))
597 case exclusion_tag_all:
598 /* This warning can be duplicated by code in dump_file0, but only
599 in case when the topmost directory being archived contains
600 an exclusion tag. */
601 exclusion_tag_warning (name_buffer, tag_file_name,
602 _("directory not dumped"));
603 *entry = 'N';
604 directory->children = NO_CHILDREN;
605 break;
607 case exclusion_tag_contents:
608 exclusion_tag_warning (name_buffer, tag_file_name,
609 _("contents not dumped"));
610 directory->children = NO_CHILDREN;
611 break;
613 case exclusion_tag_under:
614 exclusion_tag_warning (name_buffer, tag_file_name,
615 _("contents not dumped"));
616 directory->tagfile = tag_file_name;
617 break;
619 case exclusion_tag_none:
620 break;
624 return directory;
627 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
628 build a new dumpdir template.
630 DIR must be returned by a previous call to savedir().
632 File names in DIRECTORY->dump->contents must be sorted
633 alphabetically.
635 DIRECTORY->dump is replaced with the created template. Each entry is
636 prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
638 static void
639 makedumpdir (struct directory *directory, const char *dir)
641 size_t i,
642 dirsize, /* Number of elements in DIR */
643 len; /* Length of DIR, including terminating nul */
644 const char *p;
645 char const **array;
646 char *new_dump, *new_dump_ptr;
647 struct dumpdir *dump;
649 if (directory->children == ALL_CHILDREN)
650 dump = NULL;
651 else if (DIR_IS_RENAMED (directory))
652 dump = directory->orig->idump ?
653 directory->orig->idump : directory->orig->dump;
654 else
655 dump = directory->dump;
657 /* Count the size of DIR and the number of elements it contains */
658 dirsize = 0;
659 len = 0;
660 for (p = dir; *p; p += strlen (p) + 1, dirsize++)
661 len += strlen (p) + 2;
662 len++;
664 /* Create a sorted directory listing */
665 array = xcalloc (dirsize, sizeof array[0]);
666 for (i = 0, p = dir; *p; p += strlen (p) + 1, i++)
667 array[i] = p;
669 qsort (array, dirsize, sizeof (array[0]), compare_dirnames);
671 /* Prepare space for new dumpdir */
672 new_dump = xmalloc (len);
673 new_dump_ptr = new_dump;
675 /* Fill in the dumpdir template */
676 for (i = 0; i < dirsize; i++)
678 const char *loc = dumpdir_locate (dump, array[i]);
679 if (loc)
681 if (directory->tagfile)
682 *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
683 ' ' : 'I';
684 else
685 *new_dump_ptr = ' ';
686 new_dump_ptr++;
688 else if (directory->tagfile)
689 *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
690 ' ' : 'I';
691 else
692 *new_dump_ptr++ = 'Y'; /* New entry */
694 /* Copy the file name */
695 for (p = array[i]; (*new_dump_ptr++ = *p++); )
698 *new_dump_ptr = 0;
699 directory->idump = directory->dump;
700 directory->dump = dumpdir_create0 (new_dump, NULL);
701 free (array);
704 /* Recursively scan the directory identified by ST. */
705 struct directory *
706 scan_directory (struct tar_stat_info *st)
708 char const *dir = st->orig_file_name;
709 char *dirp = get_directory_entries (st);
710 dev_t device = st->stat.st_dev;
711 bool cmdline = ! st->parent;
712 namebuf_t nbuf;
713 char *tmp;
714 struct directory *directory;
715 char ch;
717 if (! dirp)
718 savedir_error (dir);
720 tmp = xstrdup (dir);
721 zap_slashes (tmp);
723 directory = procdir (tmp, st,
724 (cmdline ? PD_FORCE_INIT : 0),
725 &ch);
727 free (tmp);
729 nbuf = namebuf_create (dir);
731 if (dirp && directory->children != NO_CHILDREN)
733 char *entry; /* directory entry being scanned */
734 struct dumpdir_iter *itr;
736 makedumpdir (directory, dirp);
738 for (entry = dumpdir_first (directory->dump, 1, &itr);
739 entry;
740 entry = dumpdir_next (itr))
742 char *full_name = namebuf_name (nbuf, entry + 1);
744 if (*entry == 'I') /* Ignored entry */
745 *entry = 'N';
746 else if (excluded_name (full_name))
747 *entry = 'N';
748 else
750 int fd = st->fd;
751 void (*diag) (char const *) = 0;
752 struct tar_stat_info stsub;
753 tar_stat_init (&stsub);
755 if (fd < 0)
757 errno = - fd;
758 diag = open_diag;
760 else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0)
761 diag = stat_diag;
762 else if (S_ISDIR (stsub.stat.st_mode))
764 int subfd = subfile_open (st, entry + 1, open_read_flags);
765 if (subfd < 0)
766 diag = open_diag;
767 else
769 stsub.fd = subfd;
770 if (fstat (subfd, &stsub.stat) != 0)
771 diag = stat_diag;
775 if (diag)
777 file_removed_diag (full_name, false, diag);
778 *entry = 'N';
780 else if (S_ISDIR (stsub.stat.st_mode))
782 int pd_flag = 0;
783 if (!recursion_option)
784 pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
785 else if (directory->children == ALL_CHILDREN)
786 pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
787 *entry = 'D';
789 stsub.parent = st;
790 procdir (full_name, &stsub, pd_flag, entry);
791 restore_parent_fd (&stsub);
793 else if (one_file_system_option && device != stsub.stat.st_dev)
794 *entry = 'N';
795 else if (*entry == 'Y')
796 /* New entry, skip further checks */;
797 /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
798 else if (OLDER_STAT_TIME (stsub.stat, m)
799 && (!after_date_option
800 || OLDER_STAT_TIME (stsub.stat, c)))
801 *entry = 'N';
802 else
803 *entry = 'Y';
805 tar_stat_destroy (&stsub);
808 free (itr);
811 namebuf_free (nbuf);
813 free (dirp);
815 return directory;
818 /* Return pointer to the contents of the directory DIR */
819 const char *
820 directory_contents (struct directory *dir)
822 if (!dir)
823 return NULL;
824 return dir->dump ? dir->dump->contents : NULL;
827 /* A "safe" version of directory_contents, which never returns NULL. */
828 const char *
829 safe_directory_contents (struct directory *dir)
831 const char *ret = directory_contents (dir);
832 return ret ? ret : "\0\0\0\0";
836 static void
837 obstack_code_rename (struct obstack *stk, char const *from, char const *to)
839 char const *s;
841 s = from[0] == 0 ? from :
842 safer_name_suffix (from, false, absolute_names_option);
843 obstack_1grow (stk, 'R');
844 obstack_grow (stk, s, strlen (s) + 1);
846 s = to[0] == 0 ? to:
847 safer_name_suffix (to, false, absolute_names_option);
848 obstack_1grow (stk, 'T');
849 obstack_grow (stk, s, strlen (s) + 1);
852 static void
853 store_rename (struct directory *dir, struct obstack *stk)
855 if (DIR_IS_RENAMED (dir))
857 struct directory *prev, *p;
859 /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries
860 are ignored when hit by this function next time.
861 If the chain forms a cycle, prev points to the entry DIR is renamed
862 from. In this case it still retains DIRF_RENAMED flag, which will be
863 cleared in the 'else' branch below */
864 for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
865 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
867 if (prev == NULL)
869 for (p = dir; p && p->orig; p = p->orig)
870 obstack_code_rename (stk, p->orig->name, p->name);
872 else
874 char *temp_name;
876 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
878 /* Break the cycle by using a temporary name for one of its
879 elements.
880 First, create a temp name stub entry. */
881 temp_name = dir_name (dir->name);
882 obstack_1grow (stk, 'X');
883 obstack_grow (stk, temp_name, strlen (temp_name) + 1);
885 obstack_code_rename (stk, dir->name, "");
887 for (p = dir; p != prev; p = p->orig)
888 obstack_code_rename (stk, p->orig->name, p->name);
890 obstack_code_rename (stk, "", prev->name);
895 void
896 append_incremental_renames (struct directory *dir)
898 struct obstack stk;
899 size_t size;
900 struct directory *dp;
901 const char *dump;
903 if (dirhead == NULL)
904 return;
906 obstack_init (&stk);
907 dump = directory_contents (dir);
908 if (dump)
910 size = dumpdir_size (dump) - 1;
911 obstack_grow (&stk, dump, size);
913 else
914 size = 0;
916 for (dp = dirhead; dp; dp = dp->next)
917 store_rename (dp, &stk);
919 /* FIXME: Is this the right thing to do when DIR is null? */
920 if (dir && obstack_object_size (&stk) != size)
922 obstack_1grow (&stk, 0);
923 dumpdir_free (dir->dump);
924 dir->dump = dumpdir_create (obstack_finish (&stk));
926 obstack_free (&stk, NULL);
931 static FILE *listed_incremental_stream;
933 /* Version of incremental format snapshots (directory files) used by this
934 tar. Currently it is supposed to be a single decimal number. 0 means
935 incremental snapshots as per tar version before 1.15.2.
937 The current tar version supports incremental versions from
938 0 up to TAR_INCREMENTAL_VERSION, inclusive.
939 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
941 #define TAR_INCREMENTAL_VERSION 2
943 /* Read incremental snapshot formats 0 and 1 */
944 static void
945 read_incr_db_01 (int version, const char *initbuf)
947 int n;
948 uintmax_t u;
949 time_t sec;
950 long int nsec;
951 char *buf = NULL;
952 size_t bufsize = 0;
953 char *ebuf;
954 long lineno = 1;
956 if (version == 1)
958 if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)
960 read_error (listed_incremental_option);
961 free (buf);
962 return;
964 ++lineno;
966 else
968 buf = strdup (initbuf);
969 bufsize = strlen (buf) + 1;
972 sec = TYPE_MINIMUM (time_t);
973 nsec = -1;
974 errno = 0;
975 u = strtoumax (buf, &ebuf, 10);
976 if (!errno && TYPE_MAXIMUM (time_t) < u)
977 errno = ERANGE;
978 if (errno || buf == ebuf)
979 ERROR ((0, errno, "%s:%ld: %s",
980 quotearg_colon (listed_incremental_option),
981 lineno,
982 _("Invalid time stamp")));
983 else
985 sec = u;
987 if (version == 1 && *ebuf)
989 char const *buf_ns = ebuf + 1;
990 errno = 0;
991 u = strtoumax (buf_ns, &ebuf, 10);
992 if (!errno && BILLION <= u)
993 errno = ERANGE;
994 if (errno || buf_ns == ebuf)
996 ERROR ((0, errno, "%s:%ld: %s",
997 quotearg_colon (listed_incremental_option),
998 lineno,
999 _("Invalid time stamp")));
1000 sec = TYPE_MINIMUM (time_t);
1002 else
1003 nsec = u;
1005 else
1007 /* pre-1 incremental format does not contain nanoseconds */
1008 nsec = 0;
1011 newer_mtime_option.tv_sec = sec;
1012 newer_mtime_option.tv_nsec = nsec;
1015 while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
1017 dev_t dev;
1018 ino_t ino;
1019 bool nfs = buf[0] == '+';
1020 char *strp = buf + nfs;
1021 struct timespec mtime;
1023 lineno++;
1025 if (buf[n - 1] == '\n')
1026 buf[n - 1] = '\0';
1028 if (version == 1)
1030 errno = 0;
1031 u = strtoumax (strp, &ebuf, 10);
1032 if (!errno && TYPE_MAXIMUM (time_t) < u)
1033 errno = ERANGE;
1034 if (errno || strp == ebuf || *ebuf != ' ')
1036 ERROR ((0, errno, "%s:%ld: %s",
1037 quotearg_colon (listed_incremental_option), lineno,
1038 _("Invalid modification time (seconds)")));
1039 sec = (time_t) -1;
1041 else
1042 sec = u;
1043 strp = ebuf;
1045 errno = 0;
1046 u = strtoumax (strp, &ebuf, 10);
1047 if (!errno && BILLION <= u)
1048 errno = ERANGE;
1049 if (errno || strp == ebuf || *ebuf != ' ')
1051 ERROR ((0, errno, "%s:%ld: %s",
1052 quotearg_colon (listed_incremental_option), lineno,
1053 _("Invalid modification time (nanoseconds)")));
1054 nsec = -1;
1056 else
1057 nsec = u;
1058 mtime.tv_sec = sec;
1059 mtime.tv_nsec = nsec;
1060 strp = ebuf;
1062 else
1063 memset (&mtime, 0, sizeof mtime);
1065 errno = 0;
1066 u = strtoumax (strp, &ebuf, 10);
1067 if (!errno && TYPE_MAXIMUM (dev_t) < u)
1068 errno = ERANGE;
1069 if (errno || strp == ebuf || *ebuf != ' ')
1071 ERROR ((0, errno, "%s:%ld: %s",
1072 quotearg_colon (listed_incremental_option), lineno,
1073 _("Invalid device number")));
1074 dev = (dev_t) -1;
1076 else
1077 dev = u;
1078 strp = ebuf;
1080 errno = 0;
1081 u = strtoumax (strp, &ebuf, 10);
1082 if (!errno && TYPE_MAXIMUM (ino_t) < u)
1083 errno = ERANGE;
1084 if (errno || strp == ebuf || *ebuf != ' ')
1086 ERROR ((0, errno, "%s:%ld: %s",
1087 quotearg_colon (listed_incremental_option), lineno,
1088 _("Invalid inode number")));
1089 ino = (ino_t) -1;
1091 else
1092 ino = u;
1093 strp = ebuf;
1095 strp++;
1096 unquote_string (strp);
1097 note_directory (strp, mtime, dev, ino, nfs, false, NULL);
1099 free (buf);
1102 /* Read a nul-terminated string from FP and store it in STK.
1103 Store the number of bytes read (including nul terminator) in PCOUNT.
1105 Return the last character read or EOF on end of file. */
1106 static int
1107 read_obstack (FILE *fp, struct obstack *stk, size_t *pcount)
1109 int c;
1110 size_t i;
1112 for (i = 0, c = getc (fp); c != EOF && c != 0; c = getc (fp), i++)
1113 obstack_1grow (stk, c);
1114 obstack_1grow (stk, 0);
1116 *pcount = i;
1117 return c;
1120 /* Read from file FP a nul-terminated string and convert it to
1121 intmax_t. Return the resulting value in PVAL. Assume '-' has
1122 already been read.
1124 Throw a fatal error if the string cannot be converted or if the
1125 converted value is less than MIN_VAL. */
1127 static void
1128 read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
1130 int c;
1131 size_t i;
1132 char buf[INT_BUFSIZE_BOUND (intmax_t)];
1133 char *ep;
1134 buf[0] = '-';
1136 for (i = 1; ISDIGIT (c = getc (fp)); i++)
1138 if (i == sizeof buf - 1)
1139 FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1140 buf[i] = c;
1143 if (c < 0)
1145 if (ferror (fp))
1146 FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1147 else
1148 FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1151 buf[i] = 0;
1152 errno = 0;
1153 *pval = strtoimax (buf, &ep, 10);
1154 if (c || errno || *pval < min_val)
1155 FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1158 /* Read from file FP a nul-terminated string and convert it to
1159 uintmax_t. Return the resulting value in PVAL. Assume C has
1160 already been read.
1162 Throw a fatal error if the string cannot be converted or if the
1163 converted value exceeds MAX_VAL.
1165 Return the last character read or EOF on end of file. */
1167 static int
1168 read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
1170 size_t i;
1171 char buf[UINTMAX_STRSIZE_BOUND], *ep;
1173 for (i = 0; ISDIGIT (c); i++)
1175 if (i == sizeof buf - 1)
1176 FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1177 buf[i] = c;
1178 c = getc (fp);
1181 if (c < 0)
1183 if (ferror (fp))
1184 FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1185 else if (i == 0)
1186 return c;
1187 else
1188 FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1191 buf[i] = 0;
1192 errno = 0;
1193 *pval = strtoumax (buf, &ep, 10);
1194 if (c || errno || max_val < *pval)
1195 FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1196 return c;
1199 /* Read from file FP a nul-terminated string and convert it to
1200 uintmax_t. Return the resulting value in PVAL.
1202 Throw a fatal error if the string cannot be converted or if the
1203 converted value exceeds MAX_VAL.
1205 Return the last character read or EOF on end of file. */
1207 static int
1208 read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
1210 return read_unsigned_num (getc (fp), fp, max_val, pval);
1213 /* Read from FP two NUL-terminated strings representing a struct
1214 timespec. Return the resulting value in PVAL.
1216 Throw a fatal error if the string cannot be converted. */
1218 static void
1219 read_timespec (FILE *fp, struct timespec *pval)
1221 int c = getc (fp);
1222 intmax_t i;
1223 uintmax_t u;
1225 if (c == '-')
1227 read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
1228 c = 0;
1229 pval->tv_sec = i;
1231 else
1233 c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
1234 pval->tv_sec = u;
1237 if (c || read_num (fp, BILLION - 1, &u))
1238 FATAL_ERROR ((0, 0, "%s: %s",
1239 quotearg_colon (listed_incremental_option),
1240 _("Unexpected EOF in snapshot file")));
1241 pval->tv_nsec = u;
1244 /* Read incremental snapshot format 2 */
1245 static void
1246 read_incr_db_2 (void)
1248 uintmax_t u;
1249 struct obstack stk;
1251 obstack_init (&stk);
1253 read_timespec (listed_incremental_stream, &newer_mtime_option);
1255 for (;;)
1257 struct timespec mtime;
1258 dev_t dev;
1259 ino_t ino;
1260 bool nfs;
1261 char *name;
1262 char *content;
1263 size_t s;
1265 if (read_num (listed_incremental_stream, 1, &u))
1266 return; /* Normal return */
1268 nfs = u;
1270 read_timespec (listed_incremental_stream, &mtime);
1272 if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
1273 break;
1274 dev = u;
1276 if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
1277 break;
1278 ino = u;
1280 if (read_obstack (listed_incremental_stream, &stk, &s))
1281 break;
1283 name = obstack_finish (&stk);
1285 while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
1287 if (getc (listed_incremental_stream) != 0)
1288 FATAL_ERROR ((0, 0, "%s: %s",
1289 quotearg_colon (listed_incremental_option),
1290 _("Missing record terminator")));
1292 content = obstack_finish (&stk);
1293 note_directory (name, mtime, dev, ino, nfs, false, content);
1294 obstack_free (&stk, content);
1296 FATAL_ERROR ((0, 0, "%s: %s",
1297 quotearg_colon (listed_incremental_option),
1298 _("Unexpected EOF in snapshot file")));
1301 /* Read incremental snapshot file (directory file).
1302 If the file has older incremental version, make sure that it is processed
1303 correctly and that tar will use the most conservative backup method among
1304 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
1305 etc.) This ensures that the snapshots are updated to the recent version
1306 without any loss of data. */
1307 void
1308 read_directory_file (void)
1310 int fd;
1311 char *buf = NULL;
1312 size_t bufsize = 0;
1313 int flags = O_RDWR | O_CREAT;
1315 if (incremental_level == 0)
1316 flags |= O_TRUNC;
1317 /* Open the file for both read and write. That way, we can write
1318 it later without having to reopen it, and don't have to worry if
1319 we chdir in the meantime. */
1320 fd = open (listed_incremental_option, flags, MODE_RW);
1321 if (fd < 0)
1323 open_error (listed_incremental_option);
1324 return;
1327 listed_incremental_stream = fdopen (fd, "r+");
1328 if (! listed_incremental_stream)
1330 open_error (listed_incremental_option);
1331 close (fd);
1332 return;
1335 /* Consume the first name from the name list and reset the
1336 list afterwards. This is done to change to the new
1337 directory, if the first name is a chdir request (-C dir),
1338 which is necessary to recreate absolute file names. */
1339 name_from_list ();
1340 blank_name_list ();
1342 if (0 < getline (&buf, &bufsize, listed_incremental_stream))
1344 char *ebuf;
1345 uintmax_t incremental_version;
1347 if (strncmp (buf, PACKAGE_NAME, sizeof PACKAGE_NAME - 1) == 0)
1349 ebuf = buf + sizeof PACKAGE_NAME - 1;
1350 if (*ebuf++ != '-')
1351 ERROR((1, 0, _("Bad incremental file format")));
1352 for (; *ebuf != '-'; ebuf++)
1353 if (!*ebuf)
1354 ERROR((1, 0, _("Bad incremental file format")));
1356 incremental_version = strtoumax (ebuf + 1, NULL, 10);
1358 else
1359 incremental_version = 0;
1361 switch (incremental_version)
1363 case 0:
1364 case 1:
1365 read_incr_db_01 (incremental_version, buf);
1366 break;
1368 case TAR_INCREMENTAL_VERSION:
1369 read_incr_db_2 ();
1370 break;
1372 default:
1373 ERROR ((1, 0, _("Unsupported incremental format version: %"PRIuMAX),
1374 incremental_version));
1379 if (ferror (listed_incremental_stream))
1380 read_error (listed_incremental_option);
1381 free (buf);
1384 /* Output incremental data for the directory ENTRY to the file DATA.
1385 Return nonzero if successful, preserving errno on write failure. */
1386 static bool
1387 write_directory_file_entry (void *entry, void *data)
1389 struct directory const *directory = entry;
1390 FILE *fp = data;
1392 if (DIR_IS_FOUND (directory))
1394 char buf[UINTMAX_STRSIZE_BOUND];
1395 char const *s;
1397 s = DIR_IS_NFS (directory) ? "1" : "0";
1398 fwrite (s, 2, 1, fp);
1399 s = (TYPE_SIGNED (time_t)
1400 ? imaxtostr (directory->mtime.tv_sec, buf)
1401 : umaxtostr (directory->mtime.tv_sec, buf));
1402 fwrite (s, strlen (s) + 1, 1, fp);
1403 s = umaxtostr (directory->mtime.tv_nsec, buf);
1404 fwrite (s, strlen (s) + 1, 1, fp);
1405 s = umaxtostr (directory->device_number, buf);
1406 fwrite (s, strlen (s) + 1, 1, fp);
1407 s = umaxtostr (directory->inode_number, buf);
1408 fwrite (s, strlen (s) + 1, 1, fp);
1410 fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
1411 if (directory->dump)
1413 const char *p;
1414 struct dumpdir_iter *itr;
1416 for (p = dumpdir_first (directory->dump, 0, &itr);
1418 p = dumpdir_next (itr))
1419 fwrite (p, strlen (p) + 1, 1, fp);
1420 free (itr);
1422 fwrite ("\0\0", 2, 1, fp);
1425 return ! ferror (fp);
1428 void
1429 write_directory_file (void)
1431 FILE *fp = listed_incremental_stream;
1432 char buf[UINTMAX_STRSIZE_BOUND];
1433 char *s;
1435 if (! fp)
1436 return;
1438 if (fseeko (fp, 0L, SEEK_SET) != 0)
1439 seek_error (listed_incremental_option);
1440 if (sys_truncate (fileno (fp)) != 0)
1441 truncate_error (listed_incremental_option);
1443 fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION,
1444 TAR_INCREMENTAL_VERSION);
1446 s = (TYPE_SIGNED (time_t)
1447 ? imaxtostr (start_time.tv_sec, buf)
1448 : umaxtostr (start_time.tv_sec, buf));
1449 fwrite (s, strlen (s) + 1, 1, fp);
1450 s = umaxtostr (start_time.tv_nsec, buf);
1451 fwrite (s, strlen (s) + 1, 1, fp);
1453 if (! ferror (fp) && directory_table)
1454 hash_do_for_each (directory_table, write_directory_file_entry, fp);
1456 if (ferror (fp))
1457 write_error (listed_incremental_option);
1458 if (fclose (fp) != 0)
1459 close_error (listed_incremental_option);
1463 /* Restoration of incremental dumps. */
1465 static void
1466 get_gnu_dumpdir (struct tar_stat_info *stat_info)
1468 size_t size;
1469 size_t copied;
1470 union block *data_block;
1471 char *to;
1472 char *archive_dir;
1474 size = stat_info->stat.st_size;
1476 archive_dir = xmalloc (size);
1477 to = archive_dir;
1479 set_next_block_after (current_header);
1480 mv_begin_read (stat_info);
1482 for (; size > 0; size -= copied)
1484 mv_size_left (size);
1485 data_block = find_next_block ();
1486 if (!data_block)
1487 ERROR ((1, 0, _("Unexpected EOF in archive")));
1488 copied = available_space_after (data_block);
1489 if (copied > size)
1490 copied = size;
1491 memcpy (to, data_block->buffer, copied);
1492 to += copied;
1493 set_next_block_after ((union block *)
1494 (data_block->buffer + copied - 1));
1497 mv_end ();
1499 stat_info->dumpdir = archive_dir;
1500 stat_info->skipped = true; /* For skip_member() and friends
1501 to work correctly */
1504 /* Return T if STAT_INFO represents a dumpdir archive member.
1505 Note: can invalidate current_header. It happens if flush_archive()
1506 gets called within get_gnu_dumpdir() */
1507 bool
1508 is_dumpdir (struct tar_stat_info *stat_info)
1510 if (stat_info->is_dumpdir && !stat_info->dumpdir)
1511 get_gnu_dumpdir (stat_info);
1512 return stat_info->is_dumpdir;
1515 static bool
1516 dumpdir_ok (char *dumpdir)
1518 char *p;
1519 int has_tempdir = 0;
1520 int expect = 0;
1522 for (p = dumpdir; *p; p += strlen (p) + 1)
1524 if (expect && *p != expect)
1526 ERROR ((0, 0,
1527 _("Malformed dumpdir: expected '%c' but found %#3o"),
1528 expect, *p));
1529 return false;
1531 switch (*p)
1533 case 'X':
1534 if (has_tempdir)
1536 ERROR ((0, 0,
1537 _("Malformed dumpdir: 'X' duplicated")));
1538 return false;
1540 else
1541 has_tempdir = 1;
1542 break;
1544 case 'R':
1545 if (p[1] == 0)
1547 if (!has_tempdir)
1549 ERROR ((0, 0,
1550 _("Malformed dumpdir: empty name in 'R'")));
1551 return false;
1553 else
1554 has_tempdir = 0;
1556 expect = 'T';
1557 break;
1559 case 'T':
1560 if (expect != 'T')
1562 ERROR ((0, 0,
1563 _("Malformed dumpdir: 'T' not preceeded by 'R'")));
1564 return false;
1566 if (p[1] == 0 && !has_tempdir)
1568 ERROR ((0, 0,
1569 _("Malformed dumpdir: empty name in 'T'")));
1570 return false;
1572 expect = 0;
1573 break;
1575 case 'N':
1576 case 'Y':
1577 case 'D':
1578 break;
1580 default:
1581 /* FIXME: bail out? */
1582 break;
1586 if (expect)
1588 ERROR ((0, 0,
1589 _("Malformed dumpdir: expected '%c' but found end of data"),
1590 expect));
1591 return false;
1594 if (has_tempdir)
1595 WARNOPT (WARN_BAD_DUMPDIR,
1596 (0, 0, _("Malformed dumpdir: 'X' never used")));
1598 return true;
1601 /* Examine the directories under directory_name and delete any
1602 files that were not there at the time of the back-up. */
1603 static bool
1604 try_purge_directory (char const *directory_name)
1606 char *current_dir;
1607 char *cur, *arc, *p;
1608 char *temp_stub = NULL;
1609 struct dumpdir *dump;
1611 if (!is_dumpdir (&current_stat_info))
1612 return false;
1614 current_dir = savedir (directory_name);
1616 if (!current_dir)
1617 /* The directory doesn't exist now. It'll be created. In any
1618 case, we don't have to delete any files out of it. */
1619 return false;
1621 /* Verify if dump directory is sane */
1622 if (!dumpdir_ok (current_stat_info.dumpdir))
1623 return false;
1625 /* Process renames */
1626 for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
1628 if (*arc == 'X')
1630 #define TEMP_DIR_TEMPLATE "tar.XXXXXX"
1631 size_t len = strlen (arc + 1);
1632 temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
1633 memcpy (temp_stub, arc + 1, len);
1634 temp_stub[len] = '/';
1635 memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
1636 sizeof TEMP_DIR_TEMPLATE);
1637 if (!mkdtemp (temp_stub))
1639 ERROR ((0, errno,
1640 _("Cannot create temporary directory using template %s"),
1641 quote (temp_stub)));
1642 free (temp_stub);
1643 free (current_dir);
1644 return false;
1647 else if (*arc == 'R')
1649 char *src, *dst;
1650 src = arc + 1;
1651 arc += strlen (arc) + 1;
1652 dst = arc + 1;
1654 /* Ensure that neither source nor destination are absolute file
1655 names (unless permitted by -P option), and that they do not
1656 contain dubious parts (e.g. ../).
1658 This is an extra safety precaution. Besides, it might be
1659 necessary to extract from archives created with tar versions
1660 prior to 1.19. */
1662 if (*src)
1663 src = safer_name_suffix (src, false, absolute_names_option);
1664 if (*dst)
1665 dst = safer_name_suffix (dst, false, absolute_names_option);
1667 if (*src == 0)
1668 src = temp_stub;
1669 else if (*dst == 0)
1670 dst = temp_stub;
1672 if (!rename_directory (src, dst))
1674 free (temp_stub);
1675 free (current_dir);
1676 /* FIXME: Make sure purge_directory(dst) will return
1677 immediately */
1678 return false;
1683 free (temp_stub);
1685 /* Process deletes */
1686 dump = dumpdir_create (current_stat_info.dumpdir);
1687 p = NULL;
1688 for (cur = current_dir; *cur; cur += strlen (cur) + 1)
1690 const char *entry;
1691 struct stat st;
1692 free (p);
1693 p = new_name (directory_name, cur);
1695 if (deref_stat (p, &st) != 0)
1697 if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
1698 dirs and check it here? */
1700 stat_diag (p);
1701 WARN ((0, 0, _("%s: Not purging directory: unable to stat"),
1702 quotearg_colon (p)));
1704 continue;
1707 if (!(entry = dumpdir_locate (dump, cur))
1708 || (*entry == 'D' && !S_ISDIR (st.st_mode))
1709 || (*entry == 'Y' && S_ISDIR (st.st_mode)))
1711 if (one_file_system_option && st.st_dev != root_device)
1713 WARN ((0, 0,
1714 _("%s: directory is on a different device: not purging"),
1715 quotearg_colon (p)));
1716 continue;
1719 if (! interactive_option || confirm ("delete", p))
1721 if (verbose_option)
1722 fprintf (stdlis, _("%s: Deleting %s\n"),
1723 program_name, quote (p));
1724 if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
1726 int e = errno;
1727 ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));
1732 free (p);
1733 dumpdir_free (dump);
1735 free (current_dir);
1736 return true;
1739 void
1740 purge_directory (char const *directory_name)
1742 if (!try_purge_directory (directory_name))
1743 skip_member ();
1746 void
1747 list_dumpdir (char *buffer, size_t size)
1749 int state = 0;
1750 while (size)
1752 switch (*buffer)
1754 case 'Y':
1755 case 'N':
1756 case 'D':
1757 case 'R':
1758 case 'T':
1759 case 'X':
1760 fprintf (stdlis, "%c", *buffer);
1761 if (state == 0)
1763 fprintf (stdlis, " ");
1764 state = 1;
1766 buffer++;
1767 size--;
1768 break;
1770 case 0:
1771 fputc ('\n', stdlis);
1772 buffer++;
1773 size--;
1774 state = 0;
1775 break;
1777 default:
1778 fputc (*buffer, stdlis);
1779 buffer++;
1780 size--;