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