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