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