]> Dogcows Code - chaz/tar/blob - src/incremen.c
tar: pacify GCC 5.1 -Wformat-signedness
[chaz/tar] / src / incremen.c
1 /* GNU dump extensions to tar.
2
3 Copyright 1988, 1992-1994, 1996-1997, 1999-2001, 2003-2009, 2013-2014
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 (chdir_current, 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 (chdir_current, 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 info_attach_exclist (st);
738
739 tmp = xstrdup (dir);
740 zap_slashes (tmp);
741
742 directory = procdir (tmp, st,
743 (cmdline ? PD_FORCE_INIT : 0),
744 &ch);
745
746 free (tmp);
747
748 nbuf = namebuf_create (dir);
749
750 if (dirp)
751 {
752 if (directory->children != NO_CHILDREN)
753 {
754 char *entry; /* directory entry being scanned */
755 struct dumpdir_iter *itr;
756
757 makedumpdir (directory, dirp);
758
759 for (entry = dumpdir_first (directory->dump, 1, &itr);
760 entry;
761 entry = dumpdir_next (itr))
762 {
763 char *full_name = namebuf_name (nbuf, entry + 1);
764
765 if (*entry == 'I') /* Ignored entry */
766 *entry = 'N';
767 else if (excluded_name (full_name, st))
768 *entry = 'N';
769 else
770 {
771 int fd = st->fd;
772 void (*diag) (char const *) = 0;
773 struct tar_stat_info stsub;
774 tar_stat_init (&stsub);
775
776 if (fd < 0)
777 {
778 errno = - fd;
779 diag = open_diag;
780 }
781 else if (fstatat (fd, entry + 1, &stsub.stat,
782 fstatat_flags) != 0)
783 diag = stat_diag;
784 else if (S_ISDIR (stsub.stat.st_mode))
785 {
786 int subfd = subfile_open (st, entry + 1,
787 open_read_flags);
788 if (subfd < 0)
789 diag = open_diag;
790 else
791 {
792 stsub.fd = subfd;
793 if (fstat (subfd, &stsub.stat) != 0)
794 diag = stat_diag;
795 }
796 }
797
798 if (diag)
799 {
800 file_removed_diag (full_name, false, diag);
801 *entry = 'N';
802 }
803 else if (S_ISDIR (stsub.stat.st_mode))
804 {
805 int pd_flag = 0;
806 if (!recursion_option)
807 pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
808 else if (directory->children == ALL_CHILDREN)
809 pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
810 *entry = 'D';
811
812 stsub.parent = st;
813 procdir (full_name, &stsub, pd_flag, entry);
814 restore_parent_fd (&stsub);
815 }
816 else if (one_file_system_option &&
817 device != stsub.stat.st_dev)
818 *entry = 'N';
819 else if (*entry == 'Y')
820 /* New entry, skip further checks */;
821 /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
822 else if (OLDER_STAT_TIME (stsub.stat, m)
823 && (!after_date_option
824 || OLDER_STAT_TIME (stsub.stat, c)))
825 *entry = 'N';
826 else
827 *entry = 'Y';
828
829 tar_stat_destroy (&stsub);
830 }
831 }
832 free (itr);
833 }
834 else if (directory->tagfile)
835 maketagdumpdir (directory);
836 }
837
838 namebuf_free (nbuf);
839
840 free (dirp);
841
842 return directory;
843 }
844
845 /* Return pointer to the contents of the directory DIR */
846 const char *
847 directory_contents (struct directory *dir)
848 {
849 if (!dir)
850 return NULL;
851 return dir->dump ? dir->dump->contents : NULL;
852 }
853
854 /* A "safe" version of directory_contents, which never returns NULL. */
855 const char *
856 safe_directory_contents (struct directory *dir)
857 {
858 const char *ret = directory_contents (dir);
859 return ret ? ret : "\0\0\0\0";
860 }
861
862 \f
863 static void
864 obstack_code_rename (struct obstack *stk, char const *from, char const *to)
865 {
866 char const *s;
867
868 s = from[0] == 0 ? from :
869 safer_name_suffix (from, false, absolute_names_option);
870 obstack_1grow (stk, 'R');
871 obstack_grow (stk, s, strlen (s) + 1);
872
873 s = to[0] == 0 ? to:
874 safer_name_suffix (to, false, absolute_names_option);
875 obstack_1grow (stk, 'T');
876 obstack_grow (stk, s, strlen (s) + 1);
877 }
878
879 static void
880 store_rename (struct directory *dir, struct obstack *stk)
881 {
882 if (DIR_IS_RENAMED (dir))
883 {
884 struct directory *prev, *p;
885
886 /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries
887 are ignored when hit by this function next time.
888 If the chain forms a cycle, prev points to the entry DIR is renamed
889 from. In this case it still retains DIRF_RENAMED flag, which will be
890 cleared in the 'else' branch below */
891 for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
892 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
893
894 if (prev == NULL)
895 {
896 for (p = dir; p && p->orig; p = p->orig)
897 obstack_code_rename (stk, p->orig->name, p->name);
898 }
899 else
900 {
901 char *temp_name;
902
903 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
904
905 /* Break the cycle by using a temporary name for one of its
906 elements.
907 First, create a temp name stub entry. */
908 temp_name = dir_name (dir->name);
909 obstack_1grow (stk, 'X');
910 obstack_grow (stk, temp_name, strlen (temp_name) + 1);
911
912 obstack_code_rename (stk, dir->name, "");
913
914 for (p = dir; p != prev; p = p->orig)
915 obstack_code_rename (stk, p->orig->name, p->name);
916
917 obstack_code_rename (stk, "", prev->name);
918 }
919 }
920 }
921
922 void
923 append_incremental_renames (struct directory *dir)
924 {
925 struct obstack stk;
926 size_t size;
927 struct directory *dp;
928 const char *dump;
929
930 if (dirhead == NULL)
931 return;
932
933 obstack_init (&stk);
934 dump = directory_contents (dir);
935 if (dump)
936 {
937 size = dumpdir_size (dump) - 1;
938 obstack_grow (&stk, dump, size);
939 }
940 else
941 size = 0;
942
943 for (dp = dirhead; dp; dp = dp->next)
944 store_rename (dp, &stk);
945
946 /* FIXME: Is this the right thing to do when DIR is null? */
947 if (dir && obstack_object_size (&stk) != size)
948 {
949 obstack_1grow (&stk, 0);
950 dumpdir_free (dir->dump);
951 dir->dump = dumpdir_create (obstack_finish (&stk));
952 }
953 obstack_free (&stk, NULL);
954 }
955
956 \f
957
958 static FILE *listed_incremental_stream;
959
960 /* Version of incremental format snapshots (directory files) used by this
961 tar. Currently it is supposed to be a single decimal number. 0 means
962 incremental snapshots as per tar version before 1.15.2.
963
964 The current tar version supports incremental versions from
965 0 up to TAR_INCREMENTAL_VERSION, inclusive.
966 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
967
968 #define TAR_INCREMENTAL_VERSION 2
969
970 /* Read incremental snapshot formats 0 and 1 */
971 static void
972 read_incr_db_01 (int version, const char *initbuf)
973 {
974 int n;
975 uintmax_t u;
976 char *buf = NULL;
977 size_t bufsize = 0;
978 char *ebuf;
979 long lineno = 1;
980
981 if (version == 1)
982 {
983 if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)
984 {
985 read_error (listed_incremental_option);
986 free (buf);
987 return;
988 }
989 ++lineno;
990 }
991 else
992 {
993 buf = strdup (initbuf);
994 bufsize = strlen (buf) + 1;
995 }
996
997 newer_mtime_option = decode_timespec (buf, &ebuf, false);
998
999 if (! valid_timespec (newer_mtime_option))
1000 ERROR ((0, errno, "%s:%ld: %s",
1001 quotearg_colon (listed_incremental_option),
1002 lineno,
1003 _("Invalid time stamp")));
1004 else
1005 {
1006 if (version == 1 && *ebuf)
1007 {
1008 char const *buf_ns = ebuf + 1;
1009 errno = 0;
1010 u = strtoumax (buf_ns, &ebuf, 10);
1011 if (!errno && BILLION <= u)
1012 errno = ERANGE;
1013 if (errno || buf_ns == ebuf)
1014 {
1015 ERROR ((0, errno, "%s:%ld: %s",
1016 quotearg_colon (listed_incremental_option),
1017 lineno,
1018 _("Invalid time stamp")));
1019 newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
1020 newer_mtime_option.tv_nsec = -1;
1021 }
1022 else
1023 newer_mtime_option.tv_nsec = u;
1024 }
1025 }
1026
1027 while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
1028 {
1029 dev_t dev;
1030 ino_t ino;
1031 bool nfs = buf[0] == '+';
1032 char *strp = buf + nfs;
1033 struct timespec mtime;
1034
1035 lineno++;
1036
1037 if (buf[n - 1] == '\n')
1038 buf[n - 1] = '\0';
1039
1040 if (version == 1)
1041 {
1042 mtime = decode_timespec (strp, &ebuf, false);
1043 strp = ebuf;
1044 if (!valid_timespec (mtime) || *strp != ' ')
1045 ERROR ((0, errno, "%s:%ld: %s",
1046 quotearg_colon (listed_incremental_option), lineno,
1047 _("Invalid modification time")));
1048
1049 errno = 0;
1050 u = strtoumax (strp, &ebuf, 10);
1051 if (!errno && BILLION <= u)
1052 errno = ERANGE;
1053 if (errno || strp == ebuf || *ebuf != ' ')
1054 {
1055 ERROR ((0, errno, "%s:%ld: %s",
1056 quotearg_colon (listed_incremental_option), lineno,
1057 _("Invalid modification time (nanoseconds)")));
1058 mtime.tv_nsec = -1;
1059 }
1060 else
1061 mtime.tv_nsec = u;
1062 strp = ebuf;
1063 }
1064 else
1065 mtime.tv_sec = mtime.tv_nsec = 0;
1066
1067 dev = strtosysint (strp, &ebuf,
1068 TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t));
1069 strp = ebuf;
1070 if (errno || *strp != ' ')
1071 ERROR ((0, errno, "%s:%ld: %s",
1072 quotearg_colon (listed_incremental_option), lineno,
1073 _("Invalid device number")));
1074
1075 ino = strtosysint (strp, &ebuf,
1076 TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t));
1077 strp = ebuf;
1078 if (errno || *strp != ' ')
1079 ERROR ((0, errno, "%s:%ld: %s",
1080 quotearg_colon (listed_incremental_option), lineno,
1081 _("Invalid inode number")));
1082
1083 strp++;
1084 unquote_string (strp);
1085 note_directory (strp, mtime, dev, ino, nfs, false, NULL);
1086 }
1087 free (buf);
1088 }
1089
1090 /* Read a nul-terminated string from FP and store it in STK.
1091 Store the number of bytes read (including nul terminator) in PCOUNT.
1092
1093 Return the last character read or EOF on end of file. */
1094 static int
1095 read_obstack (FILE *fp, struct obstack *stk, size_t *pcount)
1096 {
1097 int c;
1098 size_t i;
1099
1100 for (i = 0, c = getc (fp); c != EOF && c != 0; c = getc (fp), i++)
1101 obstack_1grow (stk, c);
1102 obstack_1grow (stk, 0);
1103
1104 *pcount = i;
1105 return c;
1106 }
1107
1108 /* Read from file FP a null-terminated string and convert it to an
1109 integer. FIELDNAME is the intended use of the integer, useful for
1110 diagnostics. MIN_VAL and MAX_VAL are its minimum and maximum
1111 permissible values; MIN_VAL must be nonpositive and MAX_VAL positive.
1112 Store into *PVAL the resulting value, converted to intmax_t.
1113
1114 Throw a fatal error if the string cannot be converted or if the
1115 converted value is out of range.
1116
1117 Return true if successful, false if end of file. */
1118
1119 static bool
1120 read_num (FILE *fp, char const *fieldname,
1121 intmax_t min_val, uintmax_t max_val, intmax_t *pval)
1122 {
1123 int i;
1124 char buf[INT_BUFSIZE_BOUND (intmax_t)];
1125 char offbuf[INT_BUFSIZE_BOUND (off_t)];
1126 char minbuf[INT_BUFSIZE_BOUND (intmax_t)];
1127 char maxbuf[INT_BUFSIZE_BOUND (intmax_t)];
1128 int conversion_errno;
1129 int c = getc (fp);
1130 bool negative = c == '-';
1131
1132 for (i = 0; (i == 0 && negative) || ISDIGIT (c); i++)
1133 {
1134 buf[i] = c;
1135 if (i == sizeof buf - 1)
1136 FATAL_ERROR ((0, 0,
1137 _("%s: byte %s: %s %.*s... too long"),
1138 quotearg_colon (listed_incremental_option),
1139 offtostr (ftello (fp), offbuf),
1140 fieldname, i + 1, buf));
1141 c = getc (fp);
1142 }
1143
1144 buf[i] = 0;
1145
1146 if (c < 0)
1147 {
1148 if (ferror (fp))
1149 read_fatal (listed_incremental_option);
1150 if (i != 0)
1151 FATAL_ERROR ((0, 0, "%s: %s",
1152 quotearg_colon (listed_incremental_option),
1153 _("Unexpected EOF in snapshot file")));
1154 return false;
1155 }
1156
1157 if (c)
1158 {
1159 unsigned uc = c;
1160 FATAL_ERROR ((0, 0,
1161 _("%s: byte %s: %s %s followed by invalid byte 0x%02x"),
1162 quotearg_colon (listed_incremental_option),
1163 offtostr (ftello (fp), offbuf),
1164 fieldname, buf, uc));
1165 }
1166
1167 *pval = strtosysint (buf, NULL, min_val, max_val);
1168 conversion_errno = errno;
1169
1170 switch (conversion_errno)
1171 {
1172 case ERANGE:
1173 FATAL_ERROR ((0, conversion_errno,
1174 _("%s: byte %s: (valid range %s..%s)\n\t%s %s"),
1175 quotearg_colon (listed_incremental_option),
1176 offtostr (ftello (fp), offbuf),
1177 imaxtostr (min_val, minbuf),
1178 umaxtostr (max_val, maxbuf), fieldname, buf));
1179 default:
1180 FATAL_ERROR ((0, conversion_errno,
1181 _("%s: byte %s: %s %s"),
1182 quotearg_colon (listed_incremental_option),
1183 offtostr (ftello (fp), offbuf), fieldname, buf));
1184 case 0:
1185 break;
1186 }
1187
1188 return true;
1189 }
1190
1191 /* Read from FP two NUL-terminated strings representing a struct
1192 timespec. Return the resulting value in PVAL.
1193
1194 Throw a fatal error if the string cannot be converted. */
1195
1196 static void
1197 read_timespec (FILE *fp, struct timespec *pval)
1198 {
1199 intmax_t s, ns;
1200
1201 if (read_num (fp, "sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &s)
1202 && read_num (fp, "nsec", 0, BILLION - 1, &ns))
1203 {
1204 pval->tv_sec = s;
1205 pval->tv_nsec = ns;
1206 }
1207 else
1208 {
1209 FATAL_ERROR ((0, 0, "%s: %s",
1210 quotearg_colon (listed_incremental_option),
1211 _("Unexpected EOF in snapshot file")));
1212 }
1213 }
1214
1215 /* Read incremental snapshot format 2 */
1216 static void
1217 read_incr_db_2 (void)
1218 {
1219 struct obstack stk;
1220 char offbuf[INT_BUFSIZE_BOUND (off_t)];
1221
1222 obstack_init (&stk);
1223
1224 read_timespec (listed_incremental_stream, &newer_mtime_option);
1225
1226 for (;;)
1227 {
1228 intmax_t i;
1229 struct timespec mtime;
1230 dev_t dev;
1231 ino_t ino;
1232 bool nfs;
1233 char *name;
1234 char *content;
1235 size_t s;
1236
1237 if (! read_num (listed_incremental_stream, "nfs", 0, 1, &i))
1238 return; /* Normal return */
1239
1240 nfs = i;
1241
1242 read_timespec (listed_incremental_stream, &mtime);
1243
1244 if (! read_num (listed_incremental_stream, "dev",
1245 TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i))
1246 break;
1247 dev = i;
1248
1249 if (! read_num (listed_incremental_stream, "ino",
1250 TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i))
1251 break;
1252 ino = i;
1253
1254 if (read_obstack (listed_incremental_stream, &stk, &s))
1255 break;
1256
1257 name = obstack_finish (&stk);
1258
1259 while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
1260 ;
1261 if (getc (listed_incremental_stream) != 0)
1262 FATAL_ERROR ((0, 0, _("%s: byte %s: %s"),
1263 quotearg_colon (listed_incremental_option),
1264 offtostr (ftello (listed_incremental_stream), offbuf),
1265 _("Missing record terminator")));
1266
1267 content = obstack_finish (&stk);
1268 note_directory (name, mtime, dev, ino, nfs, false, content);
1269 obstack_free (&stk, content);
1270 }
1271 FATAL_ERROR ((0, 0, "%s: %s",
1272 quotearg_colon (listed_incremental_option),
1273 _("Unexpected EOF in snapshot file")));
1274 }
1275
1276 /* Display (to stdout) the range of allowed values for each field
1277 in the snapshot file. The array below should be kept in sync
1278 with any changes made to the read_num() calls in the parsing
1279 loop inside read_incr_db_2().
1280
1281 (This function is invoked via the --show-snapshot-field-ranges
1282 command line option.) */
1283
1284 struct field_range
1285 {
1286 char const *fieldname;
1287 intmax_t min_val;
1288 uintmax_t max_val;
1289 };
1290
1291 static struct field_range const field_ranges[] = {
1292 { "nfs", 0, 1 },
1293 { "timestamp_sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t) },
1294 { "timestamp_nsec", 0, BILLION - 1 },
1295 { "dev", TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t) },
1296 { "ino", TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t) },
1297 { NULL, 0, 0 }
1298 };
1299
1300 void
1301 show_snapshot_field_ranges (void)
1302 {
1303 struct field_range const *p;
1304 char minbuf[SYSINT_BUFSIZE];
1305 char maxbuf[SYSINT_BUFSIZE];
1306
1307 printf("This tar's snapshot file field ranges are\n");
1308 printf (" (%-15s => [ %s, %s ]):\n\n", "field name", "min", "max");
1309
1310 for (p=field_ranges; p->fieldname != NULL; p++)
1311 {
1312 printf (" %-15s => [ %s, %s ],\n", p->fieldname,
1313 sysinttostr (p->min_val, p->min_val, p->max_val, minbuf),
1314 sysinttostr (p->max_val, p->min_val, p->max_val, maxbuf));
1315
1316 }
1317
1318 printf("\n");
1319 }
1320
1321 /* Read incremental snapshot file (directory file).
1322 If the file has older incremental version, make sure that it is processed
1323 correctly and that tar will use the most conservative backup method among
1324 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
1325 etc.) This ensures that the snapshots are updated to the recent version
1326 without any loss of data. */
1327 void
1328 read_directory_file (void)
1329 {
1330 int fd;
1331 char *buf = NULL;
1332 size_t bufsize = 0;
1333 int flags = O_RDWR | O_CREAT;
1334
1335 if (incremental_level == 0)
1336 flags |= O_TRUNC;
1337 /* Open the file for both read and write. That way, we can write
1338 it later without having to reopen it, and don't have to worry if
1339 we chdir in the meantime. */
1340 fd = open (listed_incremental_option, flags, MODE_RW);
1341 if (fd < 0)
1342 {
1343 open_error (listed_incremental_option);
1344 return;
1345 }
1346
1347 listed_incremental_stream = fdopen (fd, "r+");
1348 if (! listed_incremental_stream)
1349 {
1350 open_error (listed_incremental_option);
1351 close (fd);
1352 return;
1353 }
1354
1355 /* Consume the first name from the name list and reset the
1356 list afterwards. This is done to change to the new
1357 directory, if the first name is a chdir request (-C dir),
1358 which is necessary to recreate absolute file names. */
1359 name_from_list ();
1360 blank_name_list ();
1361
1362 if (0 < getline (&buf, &bufsize, listed_incremental_stream))
1363 {
1364 char *ebuf;
1365 uintmax_t incremental_version;
1366
1367 if (strncmp (buf, PACKAGE_NAME, sizeof PACKAGE_NAME - 1) == 0)
1368 {
1369 ebuf = buf + sizeof PACKAGE_NAME - 1;
1370 if (*ebuf++ != '-')
1371 ERROR((1, 0, _("Bad incremental file format")));
1372 for (; *ebuf != '-'; ebuf++)
1373 if (!*ebuf)
1374 ERROR((1, 0, _("Bad incremental file format")));
1375
1376 incremental_version = strtoumax (ebuf + 1, NULL, 10);
1377 }
1378 else
1379 incremental_version = 0;
1380
1381 switch (incremental_version)
1382 {
1383 case 0:
1384 case 1:
1385 read_incr_db_01 (incremental_version, buf);
1386 break;
1387
1388 case TAR_INCREMENTAL_VERSION:
1389 read_incr_db_2 ();
1390 break;
1391
1392 default:
1393 ERROR ((1, 0, _("Unsupported incremental format version: %"PRIuMAX),
1394 incremental_version));
1395 }
1396
1397 }
1398
1399 if (ferror (listed_incremental_stream))
1400 read_error (listed_incremental_option);
1401 free (buf);
1402 }
1403
1404 /* Output incremental data for the directory ENTRY to the file DATA.
1405 Return nonzero if successful, preserving errno on write failure. */
1406 static bool
1407 write_directory_file_entry (void *entry, void *data)
1408 {
1409 struct directory const *directory = entry;
1410 FILE *fp = data;
1411
1412 if (DIR_IS_FOUND (directory))
1413 {
1414 char buf[SYSINT_BUFSIZE];
1415 char const *s;
1416
1417 s = DIR_IS_NFS (directory) ? "1" : "0";
1418 fwrite (s, 2, 1, fp);
1419 s = sysinttostr (directory->mtime.tv_sec, TYPE_MINIMUM (time_t),
1420 TYPE_MAXIMUM (time_t), buf);
1421 fwrite (s, strlen (s) + 1, 1, fp);
1422 s = imaxtostr (directory->mtime.tv_nsec, buf);
1423 fwrite (s, strlen (s) + 1, 1, fp);
1424 s = sysinttostr (directory->device_number,
1425 TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf);
1426 fwrite (s, strlen (s) + 1, 1, fp);
1427 s = sysinttostr (directory->inode_number,
1428 TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), buf);
1429 fwrite (s, strlen (s) + 1, 1, fp);
1430
1431 fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
1432 if (directory->dump)
1433 {
1434 const char *p;
1435 struct dumpdir_iter *itr;
1436
1437 for (p = dumpdir_first (directory->dump, 0, &itr);
1438 p;
1439 p = dumpdir_next (itr))
1440 fwrite (p, strlen (p) + 1, 1, fp);
1441 free (itr);
1442 }
1443 fwrite ("\0\0", 2, 1, fp);
1444 }
1445
1446 return ! ferror (fp);
1447 }
1448
1449 void
1450 write_directory_file (void)
1451 {
1452 FILE *fp = listed_incremental_stream;
1453 char buf[UINTMAX_STRSIZE_BOUND];
1454 char *s;
1455
1456 if (! fp)
1457 return;
1458
1459 if (fseeko (fp, 0L, SEEK_SET) != 0)
1460 seek_error (listed_incremental_option);
1461 if (sys_truncate (fileno (fp)) != 0)
1462 truncate_error (listed_incremental_option);
1463
1464 fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION,
1465 TAR_INCREMENTAL_VERSION);
1466
1467 s = (TYPE_SIGNED (time_t)
1468 ? imaxtostr (start_time.tv_sec, buf)
1469 : umaxtostr (start_time.tv_sec, buf));
1470 fwrite (s, strlen (s) + 1, 1, fp);
1471 s = umaxtostr (start_time.tv_nsec, buf);
1472 fwrite (s, strlen (s) + 1, 1, fp);
1473
1474 if (! ferror (fp) && directory_table)
1475 hash_do_for_each (directory_table, write_directory_file_entry, fp);
1476
1477 if (ferror (fp))
1478 write_error (listed_incremental_option);
1479 if (fclose (fp) != 0)
1480 close_error (listed_incremental_option);
1481 }
1482
1483 \f
1484 /* Restoration of incremental dumps. */
1485
1486 static void
1487 get_gnu_dumpdir (struct tar_stat_info *stat_info)
1488 {
1489 size_t size;
1490 size_t copied;
1491 union block *data_block;
1492 char *to;
1493 char *archive_dir;
1494
1495 size = stat_info->stat.st_size;
1496
1497 archive_dir = xmalloc (size);
1498 to = archive_dir;
1499
1500 set_next_block_after (current_header);
1501 mv_begin_read (stat_info);
1502
1503 for (; size > 0; size -= copied)
1504 {
1505 mv_size_left (size);
1506 data_block = find_next_block ();
1507 if (!data_block)
1508 ERROR ((1, 0, _("Unexpected EOF in archive")));
1509 copied = available_space_after (data_block);
1510 if (copied > size)
1511 copied = size;
1512 memcpy (to, data_block->buffer, copied);
1513 to += copied;
1514 set_next_block_after ((union block *)
1515 (data_block->buffer + copied - 1));
1516 }
1517
1518 mv_end ();
1519
1520 stat_info->dumpdir = archive_dir;
1521 stat_info->skipped = true; /* For skip_member() and friends
1522 to work correctly */
1523 }
1524
1525 /* Return T if STAT_INFO represents a dumpdir archive member.
1526 Note: can invalidate current_header. It happens if flush_archive()
1527 gets called within get_gnu_dumpdir() */
1528 bool
1529 is_dumpdir (struct tar_stat_info *stat_info)
1530 {
1531 if (stat_info->is_dumpdir && !stat_info->dumpdir)
1532 get_gnu_dumpdir (stat_info);
1533 return stat_info->is_dumpdir;
1534 }
1535
1536 static bool
1537 dumpdir_ok (char *dumpdir)
1538 {
1539 char *p;
1540 int has_tempdir = 0;
1541 int expect = 0;
1542
1543 for (p = dumpdir; *p; p += strlen (p) + 1)
1544 {
1545 if (expect && *p != expect)
1546 {
1547 unsigned char uc = *p;
1548 ERROR ((0, 0,
1549 _("Malformed dumpdir: expected '%c' but found %#3o"),
1550 expect, uc));
1551 return false;
1552 }
1553 switch (*p)
1554 {
1555 case 'X':
1556 if (has_tempdir)
1557 {
1558 ERROR ((0, 0,
1559 _("Malformed dumpdir: 'X' duplicated")));
1560 return false;
1561 }
1562 else
1563 has_tempdir = 1;
1564 break;
1565
1566 case 'R':
1567 if (p[1] == 0)
1568 {
1569 if (!has_tempdir)
1570 {
1571 ERROR ((0, 0,
1572 _("Malformed dumpdir: empty name in 'R'")));
1573 return false;
1574 }
1575 else
1576 has_tempdir = 0;
1577 }
1578 expect = 'T';
1579 break;
1580
1581 case 'T':
1582 if (expect != 'T')
1583 {
1584 ERROR ((0, 0,
1585 _("Malformed dumpdir: 'T' not preceeded by 'R'")));
1586 return false;
1587 }
1588 if (p[1] == 0 && !has_tempdir)
1589 {
1590 ERROR ((0, 0,
1591 _("Malformed dumpdir: empty name in 'T'")));
1592 return false;
1593 }
1594 expect = 0;
1595 break;
1596
1597 case 'N':
1598 case 'Y':
1599 case 'D':
1600 break;
1601
1602 default:
1603 /* FIXME: bail out? */
1604 break;
1605 }
1606 }
1607
1608 if (expect)
1609 {
1610 ERROR ((0, 0,
1611 _("Malformed dumpdir: expected '%c' but found end of data"),
1612 expect));
1613 return false;
1614 }
1615
1616 if (has_tempdir)
1617 WARNOPT (WARN_BAD_DUMPDIR,
1618 (0, 0, _("Malformed dumpdir: 'X' never used")));
1619
1620 return true;
1621 }
1622
1623 /* Examine the directories under directory_name and delete any
1624 files that were not there at the time of the back-up. */
1625 static bool
1626 try_purge_directory (char const *directory_name)
1627 {
1628 char *current_dir;
1629 char *cur, *arc, *p;
1630 char *temp_stub = NULL;
1631 struct dumpdir *dump;
1632
1633 if (!is_dumpdir (&current_stat_info))
1634 return false;
1635
1636 current_dir = tar_savedir (directory_name, 0);
1637
1638 if (!current_dir)
1639 /* The directory doesn't exist now. It'll be created. In any
1640 case, we don't have to delete any files out of it. */
1641 return false;
1642
1643 /* Verify if dump directory is sane */
1644 if (!dumpdir_ok (current_stat_info.dumpdir))
1645 return false;
1646
1647 /* Process renames */
1648 for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
1649 {
1650 if (*arc == 'X')
1651 {
1652 #define TEMP_DIR_TEMPLATE "tar.XXXXXX"
1653 size_t len = strlen (arc + 1);
1654 temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
1655 memcpy (temp_stub, arc + 1, len);
1656 temp_stub[len] = '/';
1657 memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
1658 sizeof TEMP_DIR_TEMPLATE);
1659 if (!mkdtemp (temp_stub))
1660 {
1661 ERROR ((0, errno,
1662 _("Cannot create temporary directory using template %s"),
1663 quote (temp_stub)));
1664 free (temp_stub);
1665 free (current_dir);
1666 return false;
1667 }
1668 }
1669 else if (*arc == 'R')
1670 {
1671 char *src, *dst;
1672 src = arc + 1;
1673 arc += strlen (arc) + 1;
1674 dst = arc + 1;
1675
1676 /* Ensure that neither source nor destination are absolute file
1677 names (unless permitted by -P option), and that they do not
1678 contain dubious parts (e.g. ../).
1679
1680 This is an extra safety precaution. Besides, it might be
1681 necessary to extract from archives created with tar versions
1682 prior to 1.19. */
1683
1684 if (*src)
1685 src = safer_name_suffix (src, false, absolute_names_option);
1686 if (*dst)
1687 dst = safer_name_suffix (dst, false, absolute_names_option);
1688
1689 if (*src == 0)
1690 src = temp_stub;
1691 else if (*dst == 0)
1692 dst = temp_stub;
1693
1694 if (!rename_directory (src, dst))
1695 {
1696 free (temp_stub);
1697 free (current_dir);
1698 /* FIXME: Make sure purge_directory(dst) will return
1699 immediately */
1700 return false;
1701 }
1702 }
1703 }
1704
1705 free (temp_stub);
1706
1707 /* Process deletes */
1708 dump = dumpdir_create (current_stat_info.dumpdir);
1709 p = NULL;
1710 for (cur = current_dir; *cur; cur += strlen (cur) + 1)
1711 {
1712 const char *entry;
1713 struct stat st;
1714 free (p);
1715 p = new_name (directory_name, cur);
1716
1717 if (deref_stat (p, &st) != 0)
1718 {
1719 if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
1720 dirs and check it here? */
1721 {
1722 stat_diag (p);
1723 WARN ((0, 0, _("%s: Not purging directory: unable to stat"),
1724 quotearg_colon (p)));
1725 }
1726 continue;
1727 }
1728
1729 if (!(entry = dumpdir_locate (dump, cur))
1730 || (*entry == 'D' && !S_ISDIR (st.st_mode))
1731 || (*entry == 'Y' && S_ISDIR (st.st_mode)))
1732 {
1733 if (one_file_system_option && st.st_dev != root_device)
1734 {
1735 WARN ((0, 0,
1736 _("%s: directory is on a different device: not purging"),
1737 quotearg_colon (p)));
1738 continue;
1739 }
1740
1741 if (! interactive_option || confirm ("delete", p))
1742 {
1743 if (verbose_option)
1744 fprintf (stdlis, _("%s: Deleting %s\n"),
1745 program_name, quote (p));
1746 if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
1747 {
1748 int e = errno;
1749 ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));
1750 }
1751 }
1752 }
1753 }
1754 free (p);
1755 dumpdir_free (dump);
1756
1757 free (current_dir);
1758 return true;
1759 }
1760
1761 void
1762 purge_directory (char const *directory_name)
1763 {
1764 if (!try_purge_directory (directory_name))
1765 skip_member ();
1766 }
1767
1768 void
1769 list_dumpdir (char *buffer, size_t size)
1770 {
1771 int state = 0;
1772 while (size)
1773 {
1774 switch (*buffer)
1775 {
1776 case 'Y':
1777 case 'N':
1778 case 'D':
1779 case 'R':
1780 case 'T':
1781 case 'X':
1782 fprintf (stdlis, "%c", *buffer);
1783 if (state == 0)
1784 {
1785 fprintf (stdlis, " ");
1786 state = 1;
1787 }
1788 buffer++;
1789 size--;
1790 break;
1791
1792 case 0:
1793 fputc ('\n', stdlis);
1794 buffer++;
1795 size--;
1796 state = 0;
1797 break;
1798
1799 default:
1800 fputc (*buffer, stdlis);
1801 buffer++;
1802 size--;
1803 }
1804 }
1805 }
This page took 0.10782 seconds and 4 git commands to generate.