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