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