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