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