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