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