1 /* GNU dump extensions to tar.
3 Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
4 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
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
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.
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. */
26 /* Incremental dump specialities. */
28 /* Which child files to save under a directory. */
29 enum children
{NO_CHILDREN
, CHANGED_CHILDREN
, ALL_CHILDREN
};
31 /* Directory attributes. */
34 struct timespec mtime
; /* Modification time */
35 dev_t device_number
; /* device number for directory */
36 ino_t inode_number
; /* inode number for directory */
37 enum children children
; /* what to save under this directory */
38 bool nfs
; /* is the directory mounted on nfs? */
39 bool found
; /* was the directory found on fs? */
40 bool new; /* is it new? */
41 char name
[1]; /* file name of directory */
44 static Hash_table
*directory_table
;
46 #if HAVE_ST_FSTYPE_STRING
47 static char const nfs_string
[] = "nfs";
48 # define NFS_FILE_STAT(st) (strcmp ((st).st_fstype, nfs_string) == 0)
50 # define ST_DEV_MSB(st) (~ (dev_t) 0 << (sizeof (st).st_dev * CHAR_BIT - 1))
51 # define NFS_FILE_STAT(st) (((st).st_dev & ST_DEV_MSB (st)) != 0)
54 /* Calculate the hash of a directory. */
56 hash_directory (void const *entry
, size_t n_buckets
)
58 struct directory
const *directory
= entry
;
59 return hash_string (directory
->name
, n_buckets
);
62 /* Compare two directories for equality. */
64 compare_directories (void const *entry1
, void const *entry2
)
66 struct directory
const *directory1
= entry1
;
67 struct directory
const *directory2
= entry2
;
68 return strcmp (directory1
->name
, directory2
->name
) == 0;
71 static struct directory
*
72 make_directory (const char *name
)
74 size_t namelen
= strlen (name
);
75 size_t size
= offsetof (struct directory
, name
) + namelen
+ 1;
76 struct directory
*directory
= xmalloc (size
);
77 strcpy (directory
->name
, name
);
78 if (ISSLASH (directory
->name
[namelen
-1]))
79 directory
->name
[namelen
-1] = 0;
80 directory
->new = false;
84 /* Create and link a new directory entry for directory NAME, having a
85 device number DEV and an inode number INO, with NFS indicating
86 whether it is an NFS device and FOUND indicating whether we have
87 found that the directory exists. */
88 static struct directory
*
89 note_directory (char const *name
, struct timespec mtime
,
90 dev_t dev
, ino_t ino
, bool nfs
, bool found
)
92 struct directory
*directory
= make_directory (name
);
94 directory
->mtime
= mtime
;
95 directory
->device_number
= dev
;
96 directory
->inode_number
= ino
;
97 directory
->children
= CHANGED_CHILDREN
;
99 directory
->found
= found
;
101 if (! ((directory_table
102 || (directory_table
= hash_initialize (0, 0, hash_directory
,
103 compare_directories
, 0)))
104 && hash_insert (directory_table
, directory
)))
110 /* Return a directory entry for a given file NAME, or zero if none found. */
111 static struct directory
*
112 find_directory (char *name
)
114 if (! directory_table
)
118 struct directory
*dir
= make_directory (name
);
119 struct directory
*ret
= hash_lookup (directory_table
, dir
);
126 update_parent_directory (const char *name
)
128 struct directory
*directory
;
129 char *p
, *name_buffer
;
132 directory
= find_directory (p
);
136 if (deref_stat (dereference_option
, p
, &st
) != 0)
139 directory
->mtime
= get_stat_mtime (&st
);
145 compare_dirents (const void *first
, const void *second
)
147 return strcmp ((*(char *const *) first
) + 1,
148 (*(char *const *) second
) + 1);
152 procdir (char *name_buffer
, struct stat
*stat_data
,
154 enum children children
,
157 struct directory
*directory
;
158 bool nfs
= NFS_FILE_STAT (*stat_data
);
161 if ((directory
= find_directory (name_buffer
)) != NULL
)
163 /* With NFS, the same file can have two different devices
164 if an NFS directory is mounted in multiple locations,
165 which is relatively common when automounting.
166 To avoid spurious incremental redumping of
167 directories, consider all NFS devices as equal,
168 relying on the i-node to establish differences. */
170 if (! (((directory
->nfs
& nfs
)
171 || directory
->device_number
== stat_data
->st_dev
)
172 && directory
->inode_number
== stat_data
->st_ino
))
175 WARN ((0, 0, _("%s: Directory has been renamed"),
176 quotearg_colon (name_buffer
)));
177 directory
->children
= ALL_CHILDREN
;
178 directory
->nfs
= nfs
;
179 directory
->device_number
= stat_data
->st_dev
;
180 directory
->inode_number
= stat_data
->st_ino
;
182 else if (listed_incremental_option
&& !directory
->new)
183 /* Newer modification time can mean that new files were
184 created in the directory or some of the existing files
186 directory
->children
=
187 timespec_cmp (get_stat_mtime (stat_data
), directory
->mtime
) > 0
188 ? ALL_CHILDREN
: CHANGED_CHILDREN
;
190 directory
->found
= true;
195 WARN ((0, 0, _("%s: Directory is new"),
196 quotearg_colon (name_buffer
)));
197 directory
= note_directory (name_buffer
,
198 get_stat_mtime(stat_data
),
204 directory
->children
=
205 (listed_incremental_option
206 || (OLDER_STAT_TIME (*stat_data
, m
)
207 || (after_date_option
208 && OLDER_STAT_TIME (*stat_data
, c
))))
211 directory
->new = true;
214 /* If the directory is on another device and --one-file-system was given,
216 if (one_file_system_option
&& device
!= stat_data
->st_dev
217 /* ... except if it was explicitely given in the command line */
218 && !((np
= name_scan (name_buffer
, true)) && np
->explicit))
219 directory
->children
= NO_CHILDREN
;
220 else if (children
== ALL_CHILDREN
)
221 directory
->children
= ALL_CHILDREN
;
223 return directory
->children
;
227 /* Recursively scan the given directory. */
229 scan_directory (struct obstack
*stk
, char *dir_name
, dev_t device
)
231 char *dirp
= savedir (dir_name
); /* for scanning directory */
232 char const *entry
; /* directory entry being scanned */
233 size_t entrylen
; /* length of directory entry */
234 char *name_buffer
; /* directory, `/', and directory member */
235 size_t name_buffer_size
; /* allocated size of name_buffer, minus 2 */
236 size_t name_length
; /* used length in name_buffer */
237 enum children children
;
238 struct stat stat_data
;
241 savedir_error (dir_name
);
243 name_buffer_size
= strlen (dir_name
) + NAME_FIELD_SIZE
;
244 name_buffer
= xmalloc (name_buffer_size
+ 2);
245 strcpy (name_buffer
, dir_name
);
246 if (! ISSLASH (dir_name
[strlen (dir_name
) - 1]))
247 strcat (name_buffer
, "/");
248 name_length
= strlen (name_buffer
);
250 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
252 stat_diag (name_buffer
);
253 children
= CHANGED_CHILDREN
;
256 children
= procdir (name_buffer
, &stat_data
, device
, NO_CHILDREN
, false);
258 if (dirp
&& children
!= NO_CHILDREN
)
260 (entrylen
= strlen (entry
)) != 0;
261 entry
+= entrylen
+ 1)
263 if (name_buffer_size
<= entrylen
+ name_length
)
266 name_buffer_size
+= NAME_FIELD_SIZE
;
267 while (name_buffer_size
<= entrylen
+ name_length
);
268 name_buffer
= xrealloc (name_buffer
, name_buffer_size
+ 2);
270 strcpy (name_buffer
+ name_length
, entry
);
272 if (excluded_name (name_buffer
))
273 obstack_1grow (stk
, 'N');
277 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
279 stat_diag (name_buffer
);
283 if (S_ISDIR (stat_data
.st_mode
))
285 procdir (name_buffer
, &stat_data
, device
, children
,
287 obstack_1grow (stk
, 'D');
290 else if (one_file_system_option
&& device
!= stat_data
.st_dev
)
291 obstack_1grow (stk
, 'N');
294 else if (S_ISHIDDEN (stat_data
.st_mode
))
296 obstack_1grow (stk
, 'D');
297 obstack_grow (stk
, entry
, entrylen
);
298 obstack_grow (stk
, "A", 2);
303 else if (children
== CHANGED_CHILDREN
304 && OLDER_STAT_TIME (stat_data
, m
)
305 && (!after_date_option
|| OLDER_STAT_TIME (stat_data
, c
)))
306 obstack_1grow (stk
, 'N');
308 obstack_1grow (stk
, 'Y');
311 obstack_grow (stk
, entry
, entrylen
+ 1);
314 obstack_grow (stk
, "\000\000", 2);
321 /* Sort the contents of the obstack, and convert it to the char * */
323 sort_obstack (struct obstack
*stk
)
325 char *pointer
= obstack_finish (stk
);
333 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
339 array
= obstack_alloc (stk
, sizeof (char *) * (counter
+ 1));
341 array_cursor
= array
;
342 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
343 *array_cursor
++ = cursor
;
346 qsort (array
, counter
, sizeof (char *), compare_dirents
);
348 buffer
= xmalloc (cursor
- pointer
+ 2);
351 for (array_cursor
= array
; *array_cursor
; array_cursor
++)
353 char *string
= *array_cursor
;
355 while ((*cursor
++ = *string
++))
363 get_directory_contents (char *dir_name
, dev_t device
)
369 scan_directory (&stk
, dir_name
, device
);
370 buffer
= sort_obstack (&stk
);
371 obstack_free (&stk
, NULL
);
376 dumpdir_size (const char *p
)
382 size_t size
= strlen (p
) + 1;
391 static FILE *listed_incremental_stream
;
393 /* Version of incremental format snapshots (directory files) used by this
394 tar. Currently it is supposed to be a single decimal number. 0 means
395 incremental snapshots as per tar version before 1.15.2.
397 The current tar version supports incremental versions from
398 0 up to TAR_INCREMENTAL_VERSION, inclusive.
399 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
401 #define TAR_INCREMENTAL_VERSION 1
403 /* Read incremental snapshot file (directory file).
404 If the file has older incremental version, make sure that it is processed
405 correctly and that tar will use the most conservative backup method among
406 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
407 etc.) This ensures that the snapshots are updated to the recent version
408 without any loss of data. */
410 read_directory_file (void)
417 /* Open the file for both read and write. That way, we can write
418 it later without having to reopen it, and don't have to worry if
419 we chdir in the meantime. */
420 fd
= open (listed_incremental_option
, O_RDWR
| O_CREAT
, MODE_RW
);
423 open_error (listed_incremental_option
);
427 fp
= fdopen (fd
, "r+");
430 open_error (listed_incremental_option
);
435 listed_incremental_stream
= fp
;
437 if (0 < getline (&buf
, &bufsize
, fp
))
444 int incremental_version
;
446 if (strncmp (buf
, PACKAGE_NAME
, sizeof PACKAGE_NAME
- 1) == 0)
448 ebuf
= buf
+ sizeof PACKAGE_NAME
- 1;
450 ERROR((1, 0, _("Bad incremental file format")));
451 for (; *ebuf
!= '-'; ebuf
++)
453 ERROR((1, 0, _("Bad incremental file format")));
455 incremental_version
= (errno
= 0, strtoumax (ebuf
+1, &ebuf
, 10));
456 if (getline (&buf
, &bufsize
, fp
) <= 0)
458 read_error (listed_incremental_option
);
465 incremental_version
= 0;
467 if (incremental_version
> TAR_INCREMENTAL_VERSION
)
468 ERROR((1, 0, _("Unsupported incremental format version: %d"),
469 incremental_version
));
471 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
472 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
473 ERROR ((0, 0, "%s:%ld: %s",
474 quotearg_colon (listed_incremental_option
),
476 _("Invalid time stamp")));
478 ERROR ((0, 0, "%s:%ld: %s",
479 quotearg_colon (listed_incremental_option
),
481 _("Time stamp out of range")));
482 else if (incremental_version
== 1)
484 newer_mtime_option
.tv_sec
= t
;
486 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
487 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
488 ERROR ((0, 0, "%s:%ld: %s",
489 quotearg_colon (listed_incremental_option
),
491 _("Invalid time stamp")));
493 ERROR ((0, 0, "%s:%ld: %s",
494 quotearg_colon (listed_incremental_option
),
496 _("Time stamp out of range")));
497 newer_mtime_option
.tv_nsec
= t
;
501 /* pre-1 incremental format does not contain nanoseconds */
502 newer_mtime_option
.tv_sec
= t
;
503 newer_mtime_option
.tv_nsec
= 0;
506 while (0 < (n
= getline (&buf
, &bufsize
, fp
)))
510 bool nfs
= buf
[0] == '+';
511 char *strp
= buf
+ nfs
;
512 struct timespec mtime
;
516 if (buf
[n
- 1] == '\n')
519 if (incremental_version
== 1)
522 mtime
.tv_sec
= u
= strtoumax (strp
, &ebuf
, 10);
523 if (!isspace (*ebuf
))
524 ERROR ((0, 0, "%s:%ld: %s",
525 quotearg_colon (listed_incremental_option
), lineno
,
526 _("Invalid modification time (seconds)")));
527 else if (mtime
.tv_sec
!= u
)
528 ERROR ((0, 0, "%s:%ld: %s",
529 quotearg_colon (listed_incremental_option
), lineno
,
530 _("Modification time (seconds) out of range")));
534 mtime
.tv_nsec
= u
= strtoumax (strp
, &ebuf
, 10);
535 if (!isspace (*ebuf
))
536 ERROR ((0, 0, "%s:%ld: %s",
537 quotearg_colon (listed_incremental_option
), lineno
,
538 _("Invalid modification time (nanoseconds)")));
539 else if (mtime
.tv_nsec
!= u
)
540 ERROR ((0, 0, "%s:%ld: %s",
541 quotearg_colon (listed_incremental_option
), lineno
,
542 _("Modification time (nanoseconds) out of range")));
546 memset (&mtime
, 0, sizeof mtime
);
549 dev
= u
= strtoumax (strp
, &ebuf
, 10);
550 if (!isspace (*ebuf
))
551 ERROR ((0, 0, "%s:%ld: %s",
552 quotearg_colon (listed_incremental_option
), lineno
,
553 _("Invalid device number")));
555 ERROR ((0, 0, "%s:%ld: %s",
556 quotearg_colon (listed_incremental_option
), lineno
,
557 _("Device number out of range")));
561 ino
= u
= strtoumax (strp
, &ebuf
, 10);
562 if (!isspace (*ebuf
))
563 ERROR ((0, 0, "%s:%ld: %s",
564 quotearg_colon (listed_incremental_option
), lineno
,
565 _("Invalid inode number")));
567 ERROR ((0, 0, "%s:%ld: %s",
568 quotearg_colon (listed_incremental_option
), lineno
,
569 _("Inode number out of range")));
573 unquote_string (strp
);
574 note_directory (strp
, mtime
, dev
, ino
, nfs
, false);
579 read_error (listed_incremental_option
);
584 /* Output incremental data for the directory ENTRY to the file DATA.
585 Return nonzero if successful, preserving errno on write failure. */
587 write_directory_file_entry (void *entry
, void *data
)
589 struct directory
const *directory
= entry
;
592 if (directory
->found
)
595 char buf
[UINTMAX_STRSIZE_BOUND
];
596 char *str
= quote_copy_string (directory
->name
);
600 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_sec
, buf
));
601 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_nsec
, buf
));
602 fprintf (fp
, "%s ", umaxtostr (directory
->device_number
, buf
));
603 fprintf (fp
, "%s ", umaxtostr (directory
->inode_number
, buf
));
604 fprintf (fp
, "%s\n", str
? str
: directory
->name
);
612 return ! ferror (fp
);
616 write_directory_file (void)
618 FILE *fp
= listed_incremental_stream
;
623 if (fseek (fp
, 0L, SEEK_SET
) != 0)
624 seek_error (listed_incremental_option
);
625 if (sys_truncate (fileno (fp
)) != 0)
626 truncate_error (listed_incremental_option
);
628 fprintf (fp
, "%s-%s-%d\n", PACKAGE_NAME
, PACKAGE_VERSION
,
629 TAR_INCREMENTAL_VERSION
);
631 fprintf (fp
, "%lu %lu\n",
632 (unsigned long int) start_time
.tv_sec
,
633 (unsigned long int) start_time
.tv_nsec
);
634 if (! ferror (fp
) && directory_table
)
635 hash_do_for_each (directory_table
, write_directory_file_entry
, fp
);
637 write_error (listed_incremental_option
);
638 if (fclose (fp
) != 0)
639 close_error (listed_incremental_option
);
643 /* Restoration of incremental dumps. */
646 get_gnu_dumpdir (struct tar_stat_info
*stat_info
)
650 union block
*data_block
;
654 size
= stat_info
->stat
.st_size
;
656 archive_dir
= xmalloc (size
);
659 set_next_block_after (current_header
);
660 mv_begin (stat_info
);
662 for (; size
> 0; size
-= copied
)
665 data_block
= find_next_block ();
667 ERROR ((1, 0, _("Unexpected EOF in archive")));
668 copied
= available_space_after (data_block
);
671 memcpy (to
, data_block
->buffer
, copied
);
673 set_next_block_after ((union block
*)
674 (data_block
->buffer
+ copied
- 1));
679 stat_info
->dumpdir
= archive_dir
;
680 stat_info
->skipped
= true; /* For skip_member() and friends
684 /* Return T if STAT_INFO represents a dumpdir archive member.
685 Note: can invalidate current_header. It happens if flush_archive()
686 gets called within get_gnu_dumpdir() */
688 is_dumpdir (struct tar_stat_info
*stat_info
)
690 if (stat_info
->is_dumpdir
&& !stat_info
->dumpdir
)
691 get_gnu_dumpdir (stat_info
);
692 return stat_info
->is_dumpdir
;
695 /* Examine the directories under directory_name and delete any
696 files that were not there at the time of the back-up. */
698 purge_directory (char const *directory_name
)
703 if (!is_dumpdir (¤t_stat_info
))
709 current_dir
= savedir (directory_name
);
713 /* The directory doesn't exist now. It'll be created. In any
714 case, we don't have to delete any files out of it. */
720 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
722 for (arc
= current_stat_info
.dumpdir
; *arc
; arc
+= strlen (arc
) + 1)
725 if (!strcmp (arc
, cur
))
731 char *p
= new_name (directory_name
, cur
);
733 if (deref_stat (false, p
, &st
))
736 WARN((0, 0, _("%s: Not purging directory: unable to stat"),
737 quotearg_colon (p
)));
740 else if (one_file_system_option
&& st
.st_dev
!= root_device
)
743 _("%s: directory is on a different device: not purging"),
744 quotearg_colon (p
)));
748 if (! interactive_option
|| confirm ("delete", p
))
751 fprintf (stdlis
, _("%s: Deleting %s\n"),
752 program_name
, quote (p
));
753 if (! remove_any_file (p
, RECURSIVE_REMOVE_OPTION
))
756 ERROR ((0, e
, _("%s: Cannot remove"), quotearg_colon (p
)));
767 list_dumpdir (char *buffer
, size_t size
)
776 fprintf (stdlis
, "%c ", *buffer
);
782 fputc ('\n', stdlis
);
788 fputc (*buffer
, stdlis
);