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