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