]> Dogcows Code - chaz/tar/blob - src/incremen.c
Fix handling of files removed during incremental dumps.
[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)
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 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 struct dumpdir *
112 dumpdir_create (const char *contents)
113 {
114 return dumpdir_create0 (contents, "YND");
115 }
116
117 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 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 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 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 && 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 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 (const char *name)
406 {
407 struct directory *directory;
408 char *p;
409
410 p = dir_name (name);
411 directory = find_directory (p);
412 if (directory)
413 {
414 struct stat st;
415 if (deref_stat (dereference_option, p, &st) != 0)
416 {
417 if (errno != ENOENT)
418 stat_diag (directory->name);
419 /* else: should have been already reported */
420 }
421 else
422 directory->mtime = get_stat_mtime (&st);
423 }
424 free (p);
425 }
426
427 #define PD_FORCE_CHILDREN 0x10
428 #define PD_FORCE_INIT 0x20
429 #define PD_CHILDREN(f) ((f) & 3)
430
431 static struct directory *
432 procdir (const char *name_buffer, struct stat *stat_data,
433 dev_t device,
434 int flag,
435 char *entry)
436 {
437 struct directory *directory;
438 bool nfs = NFS_FILE_STAT (*stat_data);
439
440 if ((directory = find_directory (name_buffer)) != NULL)
441 {
442 if (DIR_IS_INITED (directory))
443 {
444 if (flag & PD_FORCE_INIT)
445 {
446 assign_string (&directory->name, name_buffer);
447 }
448 else
449 {
450 *entry = 'N'; /* Avoid duplicating this directory */
451 return directory;
452 }
453 }
454
455 if (strcmp (directory->name, name_buffer))
456 {
457 *entry = 'N';
458 return directory;
459 }
460
461 /* With NFS, the same file can have two different devices
462 if an NFS directory is mounted in multiple locations,
463 which is relatively common when automounting.
464 To avoid spurious incremental redumping of
465 directories, consider all NFS devices as equal,
466 relying on the i-node to establish differences. */
467
468 if (! ((!check_device_option
469 || (DIR_IS_NFS (directory) && nfs)
470 || directory->device_number == stat_data->st_dev)
471 && directory->inode_number == stat_data->st_ino))
472 {
473 /* FIXME: find_directory_meta ignores nfs */
474 struct directory *d = find_directory_meta (stat_data->st_dev,
475 stat_data->st_ino);
476 if (d)
477 {
478 if (strcmp (d->name, name_buffer))
479 {
480 WARNOPT (WARN_RENAME_DIRECTORY,
481 (0, 0,
482 _("%s: Directory has been renamed from %s"),
483 quotearg_colon (name_buffer),
484 quote_n (1, d->name)));
485 directory->orig = d;
486 DIR_SET_FLAG (directory, DIRF_RENAMED);
487 dirlist_replace_prefix (d->name, name_buffer);
488 }
489 directory->children = CHANGED_CHILDREN;
490 }
491 else
492 {
493 WARNOPT (WARN_RENAME_DIRECTORY,
494 (0, 0, _("%s: Directory has been renamed"),
495 quotearg_colon (name_buffer)));
496 directory->children = ALL_CHILDREN;
497 directory->device_number = stat_data->st_dev;
498 directory->inode_number = stat_data->st_ino;
499 }
500 if (nfs)
501 DIR_SET_FLAG (directory, DIRF_NFS);
502 }
503 else
504 directory->children = CHANGED_CHILDREN;
505
506 DIR_SET_FLAG (directory, DIRF_FOUND);
507 }
508 else
509 {
510 struct directory *d = find_directory_meta (stat_data->st_dev,
511 stat_data->st_ino);
512
513 directory = note_directory (name_buffer,
514 get_stat_mtime(stat_data),
515 stat_data->st_dev,
516 stat_data->st_ino,
517 nfs,
518 true,
519 NULL);
520
521 if (d)
522 {
523 if (strcmp (d->name, name_buffer))
524 {
525 WARNOPT (WARN_RENAME_DIRECTORY,
526 (0, 0, _("%s: Directory has been renamed from %s"),
527 quotearg_colon (name_buffer),
528 quote_n (1, d->name)));
529 directory->orig = d;
530 DIR_SET_FLAG (directory, DIRF_RENAMED);
531 dirlist_replace_prefix (d->name, name_buffer);
532 }
533 directory->children = CHANGED_CHILDREN;
534 }
535 else
536 {
537 DIR_SET_FLAG (directory, DIRF_NEW);
538 WARNOPT (WARN_NEW_DIRECTORY,
539 (0, 0, _("%s: Directory is new"),
540 quotearg_colon (name_buffer)));
541 directory->children =
542 (listed_incremental_option
543 || (OLDER_STAT_TIME (*stat_data, m)
544 || (after_date_option
545 && OLDER_STAT_TIME (*stat_data, c))))
546 ? ALL_CHILDREN
547 : CHANGED_CHILDREN;
548 }
549 }
550
551 /* If the directory is on another device and --one-file-system was given,
552 omit it... */
553 if (one_file_system_option && device != stat_data->st_dev
554 /* ... except if it was explicitely given in the command line */
555 && !is_individual_file (name_buffer))
556 /* FIXME:
557 WARNOPT (WARN_XDEV,
558 (0, 0,
559 _("%s: directory is on a different filesystem; not dumped"),
560 quotearg_colon (directory->name)));
561 */
562 directory->children = NO_CHILDREN;
563 else if (flag & PD_FORCE_CHILDREN)
564 {
565 directory->children = PD_CHILDREN(flag);
566 if (directory->children == NO_CHILDREN)
567 *entry = 'N';
568 }
569
570 DIR_SET_FLAG (directory, DIRF_INIT);
571
572 if (directory->children != NO_CHILDREN)
573 {
574 const char *tag_file_name;
575
576 switch (check_exclusion_tags (name_buffer, &tag_file_name))
577 {
578 case exclusion_tag_all:
579 /* This warning can be duplicated by code in dump_file0, but only
580 in case when the topmost directory being archived contains
581 an exclusion tag. */
582 exclusion_tag_warning (name_buffer, tag_file_name,
583 _("directory not dumped"));
584 *entry = 'N';
585 directory->children = NO_CHILDREN;
586 break;
587
588 case exclusion_tag_contents:
589 exclusion_tag_warning (name_buffer, tag_file_name,
590 _("contents not dumped"));
591 directory->children = NO_CHILDREN;
592 break;
593
594 case exclusion_tag_under:
595 exclusion_tag_warning (name_buffer, tag_file_name,
596 _("contents not dumped"));
597 directory->tagfile = tag_file_name;
598 break;
599
600 case exclusion_tag_none:
601 break;
602 }
603 }
604
605 return directory;
606 }
607
608 /* Compare dumpdir array from DIRECTORY with directory listing DIR and
609 build a new dumpdir template.
610
611 DIR must be returned by a previous call to savedir().
612
613 File names in DIRECTORY->dump->contents must be sorted
614 alphabetically.
615
616 DIRECTORY->dump is replaced with the created template. Each entry is
617 prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */
618
619 void
620 makedumpdir (struct directory *directory, const char *dir)
621 {
622 size_t i,
623 dirsize, /* Number of elements in DIR */
624 len; /* Length of DIR, including terminating nul */
625 const char *p;
626 char const **array;
627 char *new_dump, *new_dump_ptr;
628 struct dumpdir *dump;
629
630 if (directory->children == ALL_CHILDREN)
631 dump = NULL;
632 else if (DIR_IS_RENAMED (directory))
633 dump = directory->orig->idump ?
634 directory->orig->idump : directory->orig->dump;
635 else
636 dump = directory->dump;
637
638 /* Count the size of DIR and the number of elements it contains */
639 dirsize = 0;
640 len = 0;
641 for (p = dir; *p; p += strlen (p) + 1, dirsize++)
642 len += strlen (p) + 2;
643 len++;
644
645 /* Create a sorted directory listing */
646 array = xcalloc (dirsize, sizeof array[0]);
647 for (i = 0, p = dir; *p; p += strlen (p) + 1, i++)
648 array[i] = p;
649
650 qsort (array, dirsize, sizeof (array[0]), compare_dirnames);
651
652 /* Prepare space for new dumpdir */
653 new_dump = xmalloc (len);
654 new_dump_ptr = new_dump;
655
656 /* Fill in the dumpdir template */
657 for (i = 0; i < dirsize; i++)
658 {
659 const char *loc = dumpdir_locate (dump, array[i]);
660 if (loc)
661 {
662 if (directory->tagfile)
663 *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?
664 ' ' : 'I';
665 else
666 *new_dump_ptr = ' ';
667 new_dump_ptr++;
668 }
669 else if (directory->tagfile)
670 *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?
671 ' ' : 'I';
672 else
673 *new_dump_ptr++ = 'Y'; /* New entry */
674
675 /* Copy the file name */
676 for (p = array[i]; (*new_dump_ptr++ = *p++); )
677 ;
678 }
679 *new_dump_ptr = 0;
680 directory->idump = directory->dump;
681 directory->dump = dumpdir_create0 (new_dump, NULL);
682 free (array);
683 }
684
685 /* Recursively scan the given directory DIR.
686 DEVICE is the device number where DIR resides (for --one-file-system).
687 If CMDLINE is true, the directory name was explicitly listed in the
688 command line.
689 Unless *PDIR is NULL, store there a pointer to the struct directory
690 describing DIR. */
691 struct directory *
692 scan_directory (char *dir, dev_t device, bool cmdline)
693 {
694 char *dirp = savedir (dir); /* for scanning directory */
695 char *name_buffer; /* directory, `/', and directory member */
696 size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */
697 size_t name_length; /* used length in name_buffer */
698 struct stat stat_data;
699 struct directory *directory;
700 char ch;
701
702 if (! dirp)
703 savedir_error (dir);
704
705 name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
706 name_buffer = xmalloc (name_buffer_size + 2);
707 strcpy (name_buffer, dir);
708 zap_slashes (name_buffer);
709
710 if (deref_stat (dereference_option, name_buffer, &stat_data))
711 {
712 dir_removed_diag (name_buffer, false, stat_diag);
713 /* FIXME: used to be
714 children = CHANGED_CHILDREN;
715 but changed to: */
716 free (name_buffer);
717 free (dirp);
718 return NULL;
719 }
720
721 directory = procdir (name_buffer, &stat_data, device,
722 (cmdline ? PD_FORCE_INIT : 0),
723 &ch);
724
725 name_length = strlen (name_buffer);
726 if (! ISSLASH (name_buffer[name_length - 1]))
727 {
728 name_buffer[name_length] = DIRECTORY_SEPARATOR;
729 /* name_buffer has been allocated an extra slot */
730 name_buffer[++name_length] = 0;
731 }
732
733 if (dirp && directory->children != NO_CHILDREN)
734 {
735 char *entry; /* directory entry being scanned */
736 size_t entrylen; /* length of directory entry */
737 dumpdir_iter_t itr;
738
739 makedumpdir (directory, dirp);
740
741 for (entry = dumpdir_first (directory->dump, 1, &itr);
742 entry;
743 entry = dumpdir_next (itr))
744 {
745 entrylen = strlen (entry);
746 if (name_buffer_size <= entrylen - 1 + name_length)
747 {
748 do
749 name_buffer_size += NAME_FIELD_SIZE;
750 while (name_buffer_size <= entrylen - 1 + name_length);
751 name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
752 }
753 strcpy (name_buffer + name_length, entry + 1);
754
755 if (*entry == 'I') /* Ignored entry */
756 *entry = 'N';
757 else if (excluded_name (name_buffer))
758 *entry = 'N';
759 else
760 {
761 if (deref_stat (dereference_option, name_buffer, &stat_data))
762 {
763 stat_diag (name_buffer);
764 *entry = 'N';
765 continue;
766 }
767
768 if (S_ISDIR (stat_data.st_mode))
769 {
770 int pd_flag = 0;
771 if (!recursion_option)
772 pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
773 else if (directory->children == ALL_CHILDREN)
774 pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
775 *entry = 'D';
776 procdir (name_buffer, &stat_data, device, pd_flag, entry);
777 }
778
779 else if (one_file_system_option && device != stat_data.st_dev)
780 *entry = 'N';
781
782 else if (*entry == 'Y')
783 /* New entry, skip further checks */;
784
785 /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
786
787 else if (OLDER_STAT_TIME (stat_data, m)
788 && (!after_date_option
789 || OLDER_STAT_TIME (stat_data, c)))
790 *entry = 'N';
791 else
792 *entry = 'Y';
793 }
794 }
795 free (itr);
796 }
797
798 free (name_buffer);
799 if (dirp)
800 free (dirp);
801
802 return directory;
803 }
804
805 /* Return pointer to the contents of the directory DIR */
806 const char *
807 directory_contents (struct directory *dir)
808 {
809 if (!dir)
810 return NULL;
811 return dir->dump ? dir->dump->contents : NULL;
812 }
813
814 /* A "safe" version of directory_contents, which never returns NULL. */
815 const char *
816 safe_directory_contents (struct directory *dir)
817 {
818 const char *ret = directory_contents (dir);
819 return ret ? ret : "\0\0\0\0";
820 }
821
822 void
823 name_fill_directory (struct name *name, dev_t device, bool cmdline)
824 {
825 name->directory = scan_directory (name->name, device, cmdline);
826 }
827
828 \f
829 static void
830 obstack_code_rename (struct obstack *stk, char *from, char *to)
831 {
832 char *s;
833
834 s = from[0] == 0 ? from :
835 safer_name_suffix (from, false, absolute_names_option);
836 obstack_1grow (stk, 'R');
837 obstack_grow (stk, s, strlen (s) + 1);
838
839 s = to[0] == 0 ? to:
840 safer_name_suffix (to, false, absolute_names_option);
841 obstack_1grow (stk, 'T');
842 obstack_grow (stk, s, strlen (s) + 1);
843 }
844
845 static void
846 store_rename (struct directory *dir, struct obstack *stk)
847 {
848 if (DIR_IS_RENAMED (dir))
849 {
850 struct directory *prev, *p;
851
852 /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries
853 are ignored when hit by this function next time.
854 If the chain forms a cycle, prev points to the entry DIR is renamed
855 from. In this case it still retains DIRF_RENAMED flag, which will be
856 cleared in the `else' branch below */
857 for (prev = dir; prev && prev->orig != dir; prev = prev->orig)
858 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
859
860 if (prev == NULL)
861 {
862 for (p = dir; p && p->orig; p = p->orig)
863 obstack_code_rename (stk, p->orig->name, p->name);
864 }
865 else
866 {
867 char *temp_name;
868
869 DIR_CLEAR_FLAG (prev, DIRF_RENAMED);
870
871 /* Break the cycle by using a temporary name for one of its
872 elements.
873 First, create a temp name stub entry. */
874 temp_name = dir_name (dir->name);
875 obstack_1grow (stk, 'X');
876 obstack_grow (stk, temp_name, strlen (temp_name) + 1);
877
878 obstack_code_rename (stk, dir->name, "");
879
880 for (p = dir; p != prev; p = p->orig)
881 obstack_code_rename (stk, p->orig->name, p->name);
882
883 obstack_code_rename (stk, "", prev->name);
884 }
885 }
886 }
887
888 void
889 append_incremental_renames (struct directory *dir)
890 {
891 struct obstack stk;
892 size_t size;
893 struct directory *dp;
894 const char *dump;
895
896 if (dirhead == NULL)
897 return;
898
899 obstack_init (&stk);
900 dump = directory_contents (dir);
901 if (dump)
902 {
903 size = dumpdir_size (dump) - 1;
904 obstack_grow (&stk, dump, size);
905 }
906 else
907 size = 0;
908
909 for (dp = dirhead; dp; dp = dp->next)
910 store_rename (dp, &stk);
911
912 if (obstack_object_size (&stk) != size)
913 {
914 obstack_1grow (&stk, 0);
915 dumpdir_free (dir->dump);
916 dir->dump = dumpdir_create (obstack_finish (&stk));
917 }
918 obstack_free (&stk, NULL);
919 }
920
921 \f
922
923 static FILE *listed_incremental_stream;
924
925 /* Version of incremental format snapshots (directory files) used by this
926 tar. Currently it is supposed to be a single decimal number. 0 means
927 incremental snapshots as per tar version before 1.15.2.
928
929 The current tar version supports incremental versions from
930 0 up to TAR_INCREMENTAL_VERSION, inclusive.
931 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
932
933 #define TAR_INCREMENTAL_VERSION 2
934
935 /* Read incremental snapshot formats 0 and 1 */
936 static void
937 read_incr_db_01 (int version, const char *initbuf)
938 {
939 int n;
940 uintmax_t u;
941 time_t sec;
942 long int nsec;
943 char *buf = 0;
944 size_t bufsize;
945 char *ebuf;
946 long lineno = 1;
947
948 if (version == 1)
949 {
950 if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)
951 {
952 read_error (listed_incremental_option);
953 free (buf);
954 return;
955 }
956 ++lineno;
957 }
958 else
959 {
960 buf = strdup (initbuf);
961 bufsize = strlen (buf) + 1;
962 }
963
964 sec = TYPE_MINIMUM (time_t);
965 nsec = -1;
966 errno = 0;
967 u = strtoumax (buf, &ebuf, 10);
968 if (!errno && TYPE_MAXIMUM (time_t) < u)
969 errno = ERANGE;
970 if (errno || buf == ebuf)
971 ERROR ((0, errno, "%s:%ld: %s",
972 quotearg_colon (listed_incremental_option),
973 lineno,
974 _("Invalid time stamp")));
975 else
976 {
977 sec = u;
978
979 if (version == 1 && *ebuf)
980 {
981 char const *buf_ns = ebuf + 1;
982 errno = 0;
983 u = strtoumax (buf_ns, &ebuf, 10);
984 if (!errno && BILLION <= u)
985 errno = ERANGE;
986 if (errno || buf_ns == ebuf)
987 {
988 ERROR ((0, errno, "%s:%ld: %s",
989 quotearg_colon (listed_incremental_option),
990 lineno,
991 _("Invalid time stamp")));
992 sec = TYPE_MINIMUM (time_t);
993 }
994 else
995 nsec = u;
996 }
997 else
998 {
999 /* pre-1 incremental format does not contain nanoseconds */
1000 nsec = 0;
1001 }
1002 }
1003 newer_mtime_option.tv_sec = sec;
1004 newer_mtime_option.tv_nsec = nsec;
1005
1006
1007 while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
1008 {
1009 dev_t dev;
1010 ino_t ino;
1011 bool nfs = buf[0] == '+';
1012 char *strp = buf + nfs;
1013 struct timespec mtime;
1014
1015 lineno++;
1016
1017 if (buf[n - 1] == '\n')
1018 buf[n - 1] = '\0';
1019
1020 if (version == 1)
1021 {
1022 errno = 0;
1023 u = strtoumax (strp, &ebuf, 10);
1024 if (!errno && TYPE_MAXIMUM (time_t) < u)
1025 errno = ERANGE;
1026 if (errno || strp == ebuf || *ebuf != ' ')
1027 {
1028 ERROR ((0, errno, "%s:%ld: %s",
1029 quotearg_colon (listed_incremental_option), lineno,
1030 _("Invalid modification time (seconds)")));
1031 sec = (time_t) -1;
1032 }
1033 else
1034 sec = u;
1035 strp = ebuf;
1036
1037 errno = 0;
1038 u = strtoumax (strp, &ebuf, 10);
1039 if (!errno && BILLION <= u)
1040 errno = ERANGE;
1041 if (errno || strp == ebuf || *ebuf != ' ')
1042 {
1043 ERROR ((0, errno, "%s:%ld: %s",
1044 quotearg_colon (listed_incremental_option), lineno,
1045 _("Invalid modification time (nanoseconds)")));
1046 nsec = -1;
1047 }
1048 else
1049 nsec = u;
1050 mtime.tv_sec = sec;
1051 mtime.tv_nsec = nsec;
1052 strp = ebuf;
1053 }
1054 else
1055 memset (&mtime, 0, sizeof mtime);
1056
1057 errno = 0;
1058 u = strtoumax (strp, &ebuf, 10);
1059 if (!errno && TYPE_MAXIMUM (dev_t) < u)
1060 errno = ERANGE;
1061 if (errno || strp == ebuf || *ebuf != ' ')
1062 {
1063 ERROR ((0, errno, "%s:%ld: %s",
1064 quotearg_colon (listed_incremental_option), lineno,
1065 _("Invalid device number")));
1066 dev = (dev_t) -1;
1067 }
1068 else
1069 dev = u;
1070 strp = ebuf;
1071
1072 errno = 0;
1073 u = strtoumax (strp, &ebuf, 10);
1074 if (!errno && TYPE_MAXIMUM (ino_t) < u)
1075 errno = ERANGE;
1076 if (errno || strp == ebuf || *ebuf != ' ')
1077 {
1078 ERROR ((0, errno, "%s:%ld: %s",
1079 quotearg_colon (listed_incremental_option), lineno,
1080 _("Invalid inode number")));
1081 ino = (ino_t) -1;
1082 }
1083 else
1084 ino = u;
1085 strp = ebuf;
1086
1087 strp++;
1088 unquote_string (strp);
1089 note_directory (strp, mtime, dev, ino, nfs, false, NULL);
1090 }
1091 free (buf);
1092 }
1093
1094 /* Read a nul-terminated string from FP and store it in STK.
1095 Store the number of bytes read (including nul terminator) in PCOUNT.
1096
1097 Return the last character read or EOF on end of file. */
1098 static int
1099 read_obstack (FILE *fp, struct obstack *stk, size_t *pcount)
1100 {
1101 int c;
1102 size_t i;
1103
1104 for (i = 0, c = getc (fp); c != EOF && c != 0; c = getc (fp), i++)
1105 obstack_1grow (stk, c);
1106 obstack_1grow (stk, 0);
1107
1108 *pcount = i;
1109 return c;
1110 }
1111
1112 /* Read from file FP a nul-terminated string and convert it to
1113 intmax_t. Return the resulting value in PVAL. Assume '-' has
1114 already been read.
1115
1116 Throw a fatal error if the string cannot be converted or if the
1117 converted value is less than MIN_VAL. */
1118
1119 static void
1120 read_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval)
1121 {
1122 int c;
1123 size_t i;
1124 char buf[INT_BUFSIZE_BOUND (intmax_t)];
1125 char *ep;
1126 buf[0] = '-';
1127
1128 for (i = 1; ISDIGIT (c = getc (fp)); i++)
1129 {
1130 if (i == sizeof buf - 1)
1131 FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1132 buf[i] = c;
1133 }
1134
1135 if (c < 0)
1136 {
1137 if (ferror (fp))
1138 FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1139 else
1140 FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1141 }
1142
1143 buf[i] = 0;
1144 errno = 0;
1145 *pval = strtoimax (buf, &ep, 10);
1146 if (c || errno || *pval < min_val)
1147 FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1148 }
1149
1150 /* Read from file FP a nul-terminated string and convert it to
1151 uintmax_t. Return the resulting value in PVAL. Assume C has
1152 already been read.
1153
1154 Throw a fatal error if the string cannot be converted or if the
1155 converted value exceeds MAX_VAL.
1156
1157 Return the last character read or EOF on end of file. */
1158
1159 static int
1160 read_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval)
1161 {
1162 size_t i;
1163 char buf[UINTMAX_STRSIZE_BOUND], *ep;
1164
1165 for (i = 0; ISDIGIT (c); i++)
1166 {
1167 if (i == sizeof buf - 1)
1168 FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));
1169 buf[i] = c;
1170 c = getc (fp);
1171 }
1172
1173 if (c < 0)
1174 {
1175 if (ferror (fp))
1176 FATAL_ERROR ((0, errno, _("Read error in snapshot file")));
1177 else if (i == 0)
1178 return c;
1179 else
1180 FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));
1181 }
1182
1183 buf[i] = 0;
1184 errno = 0;
1185 *pval = strtoumax (buf, &ep, 10);
1186 if (c || errno || max_val < *pval)
1187 FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));
1188 return c;
1189 }
1190
1191 /* Read from file FP a nul-terminated string and convert it to
1192 uintmax_t. Return the resulting value in PVAL.
1193
1194 Throw a fatal error if the string cannot be converted or if the
1195 converted value exceeds MAX_VAL.
1196
1197 Return the last character read or EOF on end of file. */
1198
1199 static int
1200 read_num (FILE *fp, uintmax_t max_val, uintmax_t *pval)
1201 {
1202 return read_unsigned_num (getc (fp), fp, max_val, pval);
1203 }
1204
1205 /* Read from FP two NUL-terminated strings representing a struct
1206 timespec. Return the resulting value in PVAL.
1207
1208 Throw a fatal error if the string cannot be converted. */
1209
1210 static void
1211 read_timespec (FILE *fp, struct timespec *pval)
1212 {
1213 int c = getc (fp);
1214 intmax_t i;
1215 uintmax_t u;
1216
1217 if (c == '-')
1218 {
1219 read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
1220 c = 0;
1221 pval->tv_sec = i;
1222 }
1223 else
1224 {
1225 c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
1226 pval->tv_sec = u;
1227 }
1228
1229 if (c || read_num (fp, BILLION - 1, &u))
1230 FATAL_ERROR ((0, 0, "%s: %s",
1231 quotearg_colon (listed_incremental_option),
1232 _("Unexpected EOF in snapshot file")));
1233 pval->tv_nsec = u;
1234 }
1235
1236 /* Read incremental snapshot format 2 */
1237 static void
1238 read_incr_db_2 ()
1239 {
1240 uintmax_t u;
1241 struct obstack stk;
1242
1243 obstack_init (&stk);
1244
1245 read_timespec (listed_incremental_stream, &newer_mtime_option);
1246
1247 for (;;)
1248 {
1249 struct timespec mtime;
1250 dev_t dev;
1251 ino_t ino;
1252 bool nfs;
1253 char *name;
1254 char *content;
1255 size_t s;
1256
1257 if (read_num (listed_incremental_stream, 1, &u))
1258 return; /* Normal return */
1259
1260 nfs = u;
1261
1262 read_timespec (listed_incremental_stream, &mtime);
1263
1264 if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
1265 break;
1266 dev = u;
1267
1268 if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
1269 break;
1270 ino = u;
1271
1272 if (read_obstack (listed_incremental_stream, &stk, &s))
1273 break;
1274
1275 name = obstack_finish (&stk);
1276
1277 while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
1278 ;
1279 if (getc (listed_incremental_stream) != 0)
1280 FATAL_ERROR ((0, 0, "%s: %s",
1281 quotearg_colon (listed_incremental_option),
1282 _("Missing record terminator")));
1283
1284 content = obstack_finish (&stk);
1285 note_directory (name, mtime, dev, ino, nfs, false, content);
1286 obstack_free (&stk, content);
1287 }
1288 FATAL_ERROR ((0, 0, "%s: %s",
1289 quotearg_colon (listed_incremental_option),
1290 _("Unexpected EOF in snapshot file")));
1291 }
1292
1293 /* Read incremental snapshot file (directory file).
1294 If the file has older incremental version, make sure that it is processed
1295 correctly and that tar will use the most conservative backup method among
1296 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
1297 etc.) This ensures that the snapshots are updated to the recent version
1298 without any loss of data. */
1299 void
1300 read_directory_file (void)
1301 {
1302 int fd;
1303 char *buf = 0;
1304 size_t bufsize;
1305 int flags = O_RDWR | O_CREAT;
1306
1307 if (incremental_level == 0)
1308 flags |= O_TRUNC;
1309 /* Open the file for both read and write. That way, we can write
1310 it later without having to reopen it, and don't have to worry if
1311 we chdir in the meantime. */
1312 fd = open (listed_incremental_option, flags, MODE_RW);
1313 if (fd < 0)
1314 {
1315 open_error (listed_incremental_option);
1316 return;
1317 }
1318
1319 listed_incremental_stream = fdopen (fd, "r+");
1320 if (! listed_incremental_stream)
1321 {
1322 open_error (listed_incremental_option);
1323 close (fd);
1324 return;
1325 }
1326
1327 if (0 < getline (&buf, &bufsize, listed_incremental_stream))
1328 {
1329 char *ebuf;
1330 uintmax_t incremental_version;
1331
1332 if (strncmp (buf, PACKAGE_NAME, sizeof PACKAGE_NAME - 1) == 0)
1333 {
1334 ebuf = buf + sizeof PACKAGE_NAME - 1;
1335 if (*ebuf++ != '-')
1336 ERROR((1, 0, _("Bad incremental file format")));
1337 for (; *ebuf != '-'; ebuf++)
1338 if (!*ebuf)
1339 ERROR((1, 0, _("Bad incremental file format")));
1340
1341 incremental_version = strtoumax (ebuf + 1, NULL, 10);
1342 }
1343 else
1344 incremental_version = 0;
1345
1346 switch (incremental_version)
1347 {
1348 case 0:
1349 case 1:
1350 read_incr_db_01 (incremental_version, buf);
1351 break;
1352
1353 case TAR_INCREMENTAL_VERSION:
1354 read_incr_db_2 ();
1355 break;
1356
1357 default:
1358 ERROR ((1, 0, _("Unsupported incremental format version: %"PRIuMAX),
1359 incremental_version));
1360 }
1361
1362 }
1363
1364 if (ferror (listed_incremental_stream))
1365 read_error (listed_incremental_option);
1366 if (buf)
1367 free (buf);
1368 }
1369
1370 /* Output incremental data for the directory ENTRY to the file DATA.
1371 Return nonzero if successful, preserving errno on write failure. */
1372 static bool
1373 write_directory_file_entry (void *entry, void *data)
1374 {
1375 struct directory const *directory = entry;
1376 FILE *fp = data;
1377
1378 if (DIR_IS_FOUND (directory))
1379 {
1380 char buf[UINTMAX_STRSIZE_BOUND];
1381 char *s;
1382
1383 s = DIR_IS_NFS (directory) ? "1" : "0";
1384 fwrite (s, 2, 1, fp);
1385 s = (TYPE_SIGNED (time_t)
1386 ? imaxtostr (directory->mtime.tv_sec, buf)
1387 : umaxtostr (directory->mtime.tv_sec, buf));
1388 fwrite (s, strlen (s) + 1, 1, fp);
1389 s = umaxtostr (directory->mtime.tv_nsec, buf);
1390 fwrite (s, strlen (s) + 1, 1, fp);
1391 s = umaxtostr (directory->device_number, buf);
1392 fwrite (s, strlen (s) + 1, 1, fp);
1393 s = umaxtostr (directory->inode_number, buf);
1394 fwrite (s, strlen (s) + 1, 1, fp);
1395
1396 fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
1397 if (directory->dump)
1398 {
1399 const char *p;
1400 dumpdir_iter_t itr;
1401
1402 for (p = dumpdir_first (directory->dump, 0, &itr);
1403 p;
1404 p = dumpdir_next (itr))
1405 fwrite (p, strlen (p) + 1, 1, fp);
1406 free (itr);
1407 }
1408 fwrite ("\0\0", 2, 1, fp);
1409 }
1410
1411 return ! ferror (fp);
1412 }
1413
1414 void
1415 write_directory_file (void)
1416 {
1417 FILE *fp = listed_incremental_stream;
1418 char buf[UINTMAX_STRSIZE_BOUND];
1419 char *s;
1420
1421 if (! fp)
1422 return;
1423
1424 if (fseek (fp, 0L, SEEK_SET) != 0)
1425 seek_error (listed_incremental_option);
1426 if (sys_truncate (fileno (fp)) != 0)
1427 truncate_error (listed_incremental_option);
1428
1429 fprintf (fp, "%s-%s-%d\n", PACKAGE_NAME, PACKAGE_VERSION,
1430 TAR_INCREMENTAL_VERSION);
1431
1432 s = (TYPE_SIGNED (time_t)
1433 ? imaxtostr (start_time.tv_sec, buf)
1434 : umaxtostr (start_time.tv_sec, buf));
1435 fwrite (s, strlen (s) + 1, 1, fp);
1436 s = umaxtostr (start_time.tv_nsec, buf);
1437 fwrite (s, strlen (s) + 1, 1, fp);
1438
1439 if (! ferror (fp) && directory_table)
1440 hash_do_for_each (directory_table, write_directory_file_entry, fp);
1441
1442 if (ferror (fp))
1443 write_error (listed_incremental_option);
1444 if (fclose (fp) != 0)
1445 close_error (listed_incremental_option);
1446 }
1447
1448 \f
1449 /* Restoration of incremental dumps. */
1450
1451 static void
1452 get_gnu_dumpdir (struct tar_stat_info *stat_info)
1453 {
1454 size_t size;
1455 size_t copied;
1456 union block *data_block;
1457 char *to;
1458 char *archive_dir;
1459
1460 size = stat_info->stat.st_size;
1461
1462 archive_dir = xmalloc (size);
1463 to = archive_dir;
1464
1465 set_next_block_after (current_header);
1466 mv_begin (stat_info);
1467
1468 for (; size > 0; size -= copied)
1469 {
1470 mv_size_left (size);
1471 data_block = find_next_block ();
1472 if (!data_block)
1473 ERROR ((1, 0, _("Unexpected EOF in archive")));
1474 copied = available_space_after (data_block);
1475 if (copied > size)
1476 copied = size;
1477 memcpy (to, data_block->buffer, copied);
1478 to += copied;
1479 set_next_block_after ((union block *)
1480 (data_block->buffer + copied - 1));
1481 }
1482
1483 mv_end ();
1484
1485 stat_info->dumpdir = archive_dir;
1486 stat_info->skipped = true; /* For skip_member() and friends
1487 to work correctly */
1488 }
1489
1490 /* Return T if STAT_INFO represents a dumpdir archive member.
1491 Note: can invalidate current_header. It happens if flush_archive()
1492 gets called within get_gnu_dumpdir() */
1493 bool
1494 is_dumpdir (struct tar_stat_info *stat_info)
1495 {
1496 if (stat_info->is_dumpdir && !stat_info->dumpdir)
1497 get_gnu_dumpdir (stat_info);
1498 return stat_info->is_dumpdir;
1499 }
1500
1501 static bool
1502 dumpdir_ok (char *dumpdir)
1503 {
1504 char *p;
1505 int has_tempdir = 0;
1506 int expect = 0;
1507
1508 for (p = dumpdir; *p; p += strlen (p) + 1)
1509 {
1510 if (expect && *p != expect)
1511 {
1512 ERROR ((0, 0,
1513 _("Malformed dumpdir: expected '%c' but found %#3o"),
1514 expect, *p));
1515 return false;
1516 }
1517 switch (*p)
1518 {
1519 case 'X':
1520 if (has_tempdir)
1521 {
1522 ERROR ((0, 0,
1523 _("Malformed dumpdir: 'X' duplicated")));
1524 return false;
1525 }
1526 else
1527 has_tempdir = 1;
1528 break;
1529
1530 case 'R':
1531 if (p[1] == 0)
1532 {
1533 if (!has_tempdir)
1534 {
1535 ERROR ((0, 0,
1536 _("Malformed dumpdir: empty name in 'R'")));
1537 return false;
1538 }
1539 else
1540 has_tempdir = 0;
1541 }
1542 expect = 'T';
1543 break;
1544
1545 case 'T':
1546 if (expect != 'T')
1547 {
1548 ERROR ((0, 0,
1549 _("Malformed dumpdir: 'T' not preceeded by 'R'")));
1550 return false;
1551 }
1552 if (p[1] == 0 && !has_tempdir)
1553 {
1554 ERROR ((0, 0,
1555 _("Malformed dumpdir: empty name in 'T'")));
1556 return false;
1557 }
1558 expect = 0;
1559 break;
1560
1561 case 'N':
1562 case 'Y':
1563 case 'D':
1564 break;
1565
1566 default:
1567 /* FIXME: bail out? */
1568 break;
1569 }
1570 }
1571
1572 if (expect)
1573 {
1574 ERROR ((0, 0,
1575 _("Malformed dumpdir: expected '%c' but found end of data"),
1576 expect));
1577 return false;
1578 }
1579
1580 if (has_tempdir)
1581 WARNOPT (WARN_BAD_DUMPDIR,
1582 (0, 0, _("Malformed dumpdir: 'X' never used")));
1583
1584 return true;
1585 }
1586
1587 /* Examine the directories under directory_name and delete any
1588 files that were not there at the time of the back-up. */
1589 static bool
1590 try_purge_directory (char const *directory_name)
1591 {
1592 char *current_dir;
1593 char *cur, *arc, *p;
1594 char *temp_stub = NULL;
1595 struct dumpdir *dump;
1596
1597 if (!is_dumpdir (&current_stat_info))
1598 return false;
1599
1600 current_dir = savedir (directory_name);
1601
1602 if (!current_dir)
1603 /* The directory doesn't exist now. It'll be created. In any
1604 case, we don't have to delete any files out of it. */
1605 return false;
1606
1607 /* Verify if dump directory is sane */
1608 if (!dumpdir_ok (current_stat_info.dumpdir))
1609 return false;
1610
1611 /* Process renames */
1612 for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
1613 {
1614 if (*arc == 'X')
1615 {
1616 #define TEMP_DIR_TEMPLATE "tar.XXXXXX"
1617 size_t len = strlen (arc + 1);
1618 temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
1619 memcpy (temp_stub, arc + 1, len);
1620 temp_stub[len] = '/';
1621 memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
1622 sizeof TEMP_DIR_TEMPLATE);
1623 if (!mkdtemp (temp_stub))
1624 {
1625 ERROR ((0, errno,
1626 _("Cannot create temporary directory using template %s"),
1627 quote (temp_stub)));
1628 free (temp_stub);
1629 free (current_dir);
1630 return false;
1631 }
1632 }
1633 else if (*arc == 'R')
1634 {
1635 char *src, *dst;
1636 src = arc + 1;
1637 arc += strlen (arc) + 1;
1638 dst = arc + 1;
1639
1640 /* Ensure that neither source nor destination are absolute file
1641 names (unless permitted by -P option), and that they do not
1642 contain dubious parts (e.g. ../).
1643
1644 This is an extra safety precaution. Besides, it might be
1645 necessary to extract from archives created with tar versions
1646 prior to 1.19. */
1647
1648 if (*src)
1649 src = safer_name_suffix (src, false, absolute_names_option);
1650 if (*dst)
1651 dst = safer_name_suffix (dst, false, absolute_names_option);
1652
1653 if (*src == 0)
1654 src = temp_stub;
1655 else if (*dst == 0)
1656 dst = temp_stub;
1657
1658 if (!rename_directory (src, dst))
1659 {
1660 free (temp_stub);
1661 free (current_dir);
1662 /* FIXME: Make sure purge_directory(dst) will return
1663 immediately */
1664 return false;
1665 }
1666 }
1667 }
1668
1669 free (temp_stub);
1670
1671 /* Process deletes */
1672 dump = dumpdir_create (current_stat_info.dumpdir);
1673 p = NULL;
1674 for (cur = current_dir; *cur; cur += strlen (cur) + 1)
1675 {
1676 const char *entry;
1677 struct stat st;
1678 if (p)
1679 free (p);
1680 p = new_name (directory_name, cur);
1681
1682 if (deref_stat (false, p, &st))
1683 {
1684 if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
1685 dirs and check it here? */
1686 {
1687 stat_diag (p);
1688 WARN ((0, 0, _("%s: Not purging directory: unable to stat"),
1689 quotearg_colon (p)));
1690 }
1691 continue;
1692 }
1693
1694 if (!(entry = dumpdir_locate (dump, cur))
1695 || (*entry == 'D' && !S_ISDIR (st.st_mode))
1696 || (*entry == 'Y' && S_ISDIR (st.st_mode)))
1697 {
1698 if (one_file_system_option && st.st_dev != root_device)
1699 {
1700 WARN ((0, 0,
1701 _("%s: directory is on a different device: not purging"),
1702 quotearg_colon (p)));
1703 continue;
1704 }
1705
1706 if (! interactive_option || confirm ("delete", p))
1707 {
1708 if (verbose_option)
1709 fprintf (stdlis, _("%s: Deleting %s\n"),
1710 program_name, quote (p));
1711 if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
1712 {
1713 int e = errno;
1714 ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));
1715 }
1716 }
1717 }
1718 }
1719 free (p);
1720 dumpdir_free (dump);
1721
1722 free (current_dir);
1723 return true;
1724 }
1725
1726 void
1727 purge_directory (char const *directory_name)
1728 {
1729 if (!try_purge_directory (directory_name))
1730 skip_member ();
1731 }
1732
1733 void
1734 list_dumpdir (char *buffer, size_t size)
1735 {
1736 int state = 0;
1737 while (size)
1738 {
1739 switch (*buffer)
1740 {
1741 case 'Y':
1742 case 'N':
1743 case 'D':
1744 case 'R':
1745 case 'T':
1746 case 'X':
1747 fprintf (stdlis, "%c", *buffer);
1748 if (state == 0)
1749 {
1750 fprintf (stdlis, " ");
1751 state = 1;
1752 }
1753 buffer++;
1754 size--;
1755 break;
1756
1757 case 0:
1758 fputc ('\n', stdlis);
1759 buffer++;
1760 size--;
1761 state = 0;
1762 break;
1763
1764 default:
1765 fputc (*buffer, stdlis);
1766 buffer++;
1767 size--;
1768 }
1769 }
1770 }
This page took 0.11365 seconds and 5 git commands to generate.