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