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