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