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