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