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