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