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