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