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