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