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
;
40 char name
[1]; /* file name of directory */
43 static Hash_table
*directory_table
;
45 #if HAVE_ST_FSTYPE_STRING
46 static char const nfs_string
[] = "nfs";
47 # define NFS_FILE_STAT(st) (strcmp ((st).st_fstype, nfs_string) == 0)
49 # define ST_DEV_MSB(st) (~ (dev_t) 0 << (sizeof (st).st_dev * CHAR_BIT - 1))
50 # define NFS_FILE_STAT(st) (((st).st_dev & ST_DEV_MSB (st)) != 0)
53 /* Calculate the hash of a directory. */
55 hash_directory (void const *entry
, size_t n_buckets
)
57 struct directory
const *directory
= entry
;
58 return hash_string (directory
->name
, n_buckets
);
61 /* Compare two directories for equality. */
63 compare_directories (void const *entry1
, void const *entry2
)
65 struct directory
const *directory1
= entry1
;
66 struct directory
const *directory2
= entry2
;
67 return strcmp (directory1
->name
, directory2
->name
) == 0;
70 /* Create and link a new directory entry for directory NAME, having a
71 device number DEV and an inode number INO, with NFS indicating
72 whether it is an NFS device and FOUND indicating whether we have
73 found that the directory exists. */
74 static struct directory
*
75 note_directory (char const *name
, struct timespec mtime
,
76 dev_t dev
, ino_t ino
, bool nfs
, bool found
)
78 size_t size
= offsetof (struct directory
, name
) + strlen (name
) + 1;
79 struct directory
*directory
= xmalloc (size
);
81 directory
->mtime
= mtime
;
82 directory
->device_number
= dev
;
83 directory
->inode_number
= ino
;
84 directory
->children
= CHANGED_CHILDREN
;
86 directory
->found
= found
;
87 strcpy (directory
->name
, name
);
89 if (! ((directory_table
90 || (directory_table
= hash_initialize (0, 0, hash_directory
,
91 compare_directories
, 0)))
92 && hash_insert (directory_table
, directory
)))
98 /* Return a directory entry for a given file NAME, or zero if none found. */
99 static struct directory
*
100 find_directory (char *name
)
102 if (! directory_table
)
106 size_t size
= offsetof (struct directory
, name
) + strlen (name
) + 1;
107 struct directory
*dir
= alloca (size
);
108 strcpy (dir
->name
, name
);
109 return hash_lookup (directory_table
, dir
);
114 update_parent_directory (const char *name
)
116 struct directory
*directory
;
117 char *p
, *name_buffer
;
120 name_buffer
= xmalloc (strlen (p
) + 2);
121 strcpy (name_buffer
, p
);
122 if (! ISSLASH (p
[strlen (p
) - 1]))
123 strcat (name_buffer
, "/");
125 directory
= find_directory (name_buffer
);
130 if (deref_stat (dereference_option
, p
, &st
) != 0)
133 directory
->mtime
= get_stat_mtime (&st
);
139 compare_dirents (const void *first
, const void *second
)
141 return strcmp ((*(char *const *) first
) + 1,
142 (*(char *const *) second
) + 1);
146 procdir (char *name_buffer
, struct stat
*stat_data
,
148 enum children children
,
151 struct directory
*directory
;
152 bool nfs
= NFS_FILE_STAT (*stat_data
);
155 if ((directory
= find_directory (name_buffer
)) != NULL
)
157 /* With NFS, the same file can have two different devices
158 if an NFS directory is mounted in multiple locations,
159 which is relatively common when automounting.
160 To avoid spurious incremental redumping of
161 directories, consider all NFS devices as equal,
162 relying on the i-node to establish differences. */
164 if (! (((directory
->nfs
& nfs
)
165 || directory
->device_number
== stat_data
->st_dev
)
166 && directory
->inode_number
== stat_data
->st_ino
))
169 WARN ((0, 0, _("%s: Directory has been renamed"),
170 quotearg_colon (name_buffer
)));
171 directory
->children
= ALL_CHILDREN
;
172 directory
->nfs
= nfs
;
173 directory
->device_number
= stat_data
->st_dev
;
174 directory
->inode_number
= stat_data
->st_ino
;
176 else if (listed_incremental_option
)
177 /* Newer modification time can mean that new files were
178 created in the directory or some of the existing files
180 directory
->children
=
181 timespec_cmp (get_stat_mtime (stat_data
), directory
->mtime
) > 0
182 ? ALL_CHILDREN
: CHANGED_CHILDREN
;
184 directory
->found
= true;
189 WARN ((0, 0, _("%s: Directory is new"),
190 quotearg_colon (name_buffer
)));
191 directory
= note_directory (name_buffer
,
192 get_stat_mtime(stat_data
),
198 directory
->children
=
199 (listed_incremental_option
200 || (OLDER_STAT_TIME (*stat_data
, m
)
201 || (after_date_option
202 && OLDER_STAT_TIME (*stat_data
, c
))))
207 /* If the directory is on another device and --one-file-system was given,
209 if (one_file_system_option
&& device
!= stat_data
->st_dev
210 /* ... except if it was explicitely given in the command line */
211 && !((np
= name_scan (name_buffer
, true)) && np
->explicit))
212 directory
->children
= NO_CHILDREN
;
213 else if (children
== ALL_CHILDREN
)
214 directory
->children
= ALL_CHILDREN
;
216 return directory
->children
;
220 /* Recursively scan the given directory. */
222 scan_directory (struct obstack
*stk
, char *dir_name
, dev_t device
)
224 char *dirp
= savedir (dir_name
); /* for scanning directory */
225 char const *entry
; /* directory entry being scanned */
226 size_t entrylen
; /* length of directory entry */
227 char *name_buffer
; /* directory, `/', and directory member */
228 size_t name_buffer_size
; /* allocated size of name_buffer, minus 2 */
229 size_t name_length
; /* used length in name_buffer */
230 enum children children
;
231 struct stat stat_data
;
234 savedir_error (dir_name
);
236 name_buffer_size
= strlen (dir_name
) + NAME_FIELD_SIZE
;
237 name_buffer
= xmalloc (name_buffer_size
+ 2);
238 strcpy (name_buffer
, dir_name
);
239 if (! ISSLASH (dir_name
[strlen (dir_name
) - 1]))
240 strcat (name_buffer
, "/");
241 name_length
= strlen (name_buffer
);
243 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
245 stat_diag (name_buffer
);
246 children
= CHANGED_CHILDREN
;
249 children
= procdir (name_buffer
, &stat_data
, device
, NO_CHILDREN
, false);
251 if (dirp
&& children
!= NO_CHILDREN
)
253 (entrylen
= strlen (entry
)) != 0;
254 entry
+= entrylen
+ 1)
256 if (name_buffer_size
<= entrylen
+ name_length
)
259 name_buffer_size
+= NAME_FIELD_SIZE
;
260 while (name_buffer_size
<= entrylen
+ name_length
);
261 name_buffer
= xrealloc (name_buffer
, name_buffer_size
+ 2);
263 strcpy (name_buffer
+ name_length
, entry
);
265 if (excluded_name (name_buffer
))
266 obstack_1grow (stk
, 'N');
270 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
272 stat_diag (name_buffer
);
276 if (S_ISDIR (stat_data
.st_mode
))
278 procdir (name_buffer
, &stat_data
, device
, children
,
280 obstack_1grow (stk
, 'D');
283 else if (one_file_system_option
&& device
!= stat_data
.st_dev
)
284 obstack_1grow (stk
, 'N');
287 else if (S_ISHIDDEN (stat_data
.st_mode
))
289 obstack_1grow (stk
, 'D');
290 obstack_grow (stk
, entry
, entrylen
);
291 obstack_grow (stk
, "A", 2);
297 if (children
== CHANGED_CHILDREN
298 && OLDER_STAT_TIME (stat_data
, m
)
299 && (!after_date_option
|| OLDER_STAT_TIME (stat_data
, c
)))
300 obstack_1grow (stk
, 'N');
302 obstack_1grow (stk
, 'Y');
305 obstack_grow (stk
, entry
, entrylen
+ 1);
308 obstack_grow (stk
, "\000\000", 2);
315 /* Sort the contents of the obstack, and convert it to the char * */
317 sort_obstack (struct obstack
*stk
)
319 char *pointer
= obstack_finish (stk
);
327 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
333 array
= obstack_alloc (stk
, sizeof (char *) * (counter
+ 1));
335 array_cursor
= array
;
336 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
337 *array_cursor
++ = cursor
;
340 qsort (array
, counter
, sizeof (char *), compare_dirents
);
342 buffer
= xmalloc (cursor
- pointer
+ 2);
345 for (array_cursor
= array
; *array_cursor
; array_cursor
++)
347 char *string
= *array_cursor
;
349 while ((*cursor
++ = *string
++))
357 get_directory_contents (char *dir_name
, dev_t device
)
363 scan_directory (&stk
, dir_name
, device
);
364 buffer
= sort_obstack (&stk
);
365 obstack_free (&stk
, NULL
);
370 dumpdir_size (const char *p
)
376 size_t size
= strlen (p
) + 1;
385 static FILE *listed_incremental_stream
;
387 /* Version of incremental format snapshots (directory files) used by this
388 tar. Currently it is supposed to be a single decimal number. 0 means
389 incremental snapshots as per tar version before 1.15.2.
391 The current tar version supports incremental versions from
392 0 up to TAR_INCREMENTAL_VERSION, inclusive.
393 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
395 #define TAR_INCREMENTAL_VERSION 1
397 /* Read incremental snapshot file (directory file).
398 If the file has older incremental version, make sure that it is processed
399 correctly and that tar will use the most conservative backup method among
400 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
401 etc.) This ensures that the snapshots are updated to the recent version
402 without any loss of data. */
404 read_directory_file (void)
411 /* Open the file for both read and write. That way, we can write
412 it later without having to reopen it, and don't have to worry if
413 we chdir in the meantime. */
414 fd
= open (listed_incremental_option
, O_RDWR
| O_CREAT
, MODE_RW
);
417 open_error (listed_incremental_option
);
421 fp
= fdopen (fd
, "r+");
424 open_error (listed_incremental_option
);
429 listed_incremental_stream
= fp
;
431 if (0 < getline (&buf
, &bufsize
, fp
))
438 int incremental_version
;
440 if (strncmp (buf
, PACKAGE_NAME
, sizeof PACKAGE_NAME
- 1) == 0)
442 ebuf
= buf
+ sizeof PACKAGE_NAME
- 1;
444 ERROR((1, 0, _("Bad incremental file format")));
445 for (; *ebuf
!= '-'; ebuf
++)
447 ERROR((1, 0, _("Bad incremental file format")));
449 incremental_version
= (errno
= 0, strtoumax (ebuf
+1, &ebuf
, 10));
450 if (getline (&buf
, &bufsize
, fp
) <= 0)
452 read_error (listed_incremental_option
);
459 incremental_version
= 0;
461 if (incremental_version
> TAR_INCREMENTAL_VERSION
)
462 ERROR((1, 0, _("Unsupported incremental format version: %d"),
463 incremental_version
));
465 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
466 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
467 ERROR ((0, 0, "%s:%ld: %s",
468 quotearg_colon (listed_incremental_option
),
470 _("Invalid time stamp")));
472 ERROR ((0, 0, "%s:%ld: %s",
473 quotearg_colon (listed_incremental_option
),
475 _("Time stamp out of range")));
476 else if (incremental_version
== 1)
478 newer_mtime_option
.tv_sec
= t
;
480 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
481 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
482 ERROR ((0, 0, "%s:%ld: %s",
483 quotearg_colon (listed_incremental_option
),
485 _("Invalid time stamp")));
487 ERROR ((0, 0, "%s:%ld: %s",
488 quotearg_colon (listed_incremental_option
),
490 _("Time stamp out of range")));
491 newer_mtime_option
.tv_nsec
= t
;
495 /* pre-1 incremental format does not contain nanoseconds */
496 newer_mtime_option
.tv_sec
= t
;
497 newer_mtime_option
.tv_nsec
= 0;
500 while (0 < (n
= getline (&buf
, &bufsize
, fp
)))
504 bool nfs
= buf
[0] == '+';
505 char *strp
= buf
+ nfs
;
506 struct timespec mtime
;
510 if (buf
[n
- 1] == '\n')
513 if (incremental_version
== 1)
516 mtime
.tv_sec
= u
= strtoumax (strp
, &ebuf
, 10);
517 if (!isspace (*ebuf
))
518 ERROR ((0, 0, "%s:%ld: %s",
519 quotearg_colon (listed_incremental_option
), lineno
,
520 _("Invalid modification time (seconds)")));
521 else if (mtime
.tv_sec
!= u
)
522 ERROR ((0, 0, "%s:%ld: %s",
523 quotearg_colon (listed_incremental_option
), lineno
,
524 _("Modification time (seconds) out of range")));
528 mtime
.tv_nsec
= u
= strtoumax (strp
, &ebuf
, 10);
529 if (!isspace (*ebuf
))
530 ERROR ((0, 0, "%s:%ld: %s",
531 quotearg_colon (listed_incremental_option
), lineno
,
532 _("Invalid modification time (nanoseconds)")));
533 else if (mtime
.tv_nsec
!= u
)
534 ERROR ((0, 0, "%s:%ld: %s",
535 quotearg_colon (listed_incremental_option
), lineno
,
536 _("Modification time (nanoseconds) out of range")));
540 memset (&mtime
, 0, sizeof mtime
);
543 dev
= u
= strtoumax (strp
, &ebuf
, 10);
544 if (!isspace (*ebuf
))
545 ERROR ((0, 0, "%s:%ld: %s",
546 quotearg_colon (listed_incremental_option
), lineno
,
547 _("Invalid device number")));
549 ERROR ((0, 0, "%s:%ld: %s",
550 quotearg_colon (listed_incremental_option
), lineno
,
551 _("Device number out of range")));
555 ino
= u
= strtoumax (strp
, &ebuf
, 10);
556 if (!isspace (*ebuf
))
557 ERROR ((0, 0, "%s:%ld: %s",
558 quotearg_colon (listed_incremental_option
), lineno
,
559 _("Invalid inode number")));
561 ERROR ((0, 0, "%s:%ld: %s",
562 quotearg_colon (listed_incremental_option
), lineno
,
563 _("Inode number out of range")));
567 unquote_string (strp
);
568 note_directory (strp
, mtime
, dev
, ino
, nfs
, 0);
573 read_error (listed_incremental_option
);
578 /* Output incremental data for the directory ENTRY to the file DATA.
579 Return nonzero if successful, preserving errno on write failure. */
581 write_directory_file_entry (void *entry
, void *data
)
583 struct directory
const *directory
= entry
;
586 if (directory
->found
)
589 char buf
[UINTMAX_STRSIZE_BOUND
];
590 char *str
= quote_copy_string (directory
->name
);
594 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_sec
, buf
));
595 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_nsec
, buf
));
596 fprintf (fp
, "%s ", umaxtostr (directory
->device_number
, buf
));
597 fprintf (fp
, "%s ", umaxtostr (directory
->inode_number
, buf
));
598 fprintf (fp
, "%s\n", str
? str
: directory
->name
);
606 return ! ferror (fp
);
610 write_directory_file (void)
612 FILE *fp
= listed_incremental_stream
;
617 if (fseek (fp
, 0L, SEEK_SET
) != 0)
618 seek_error (listed_incremental_option
);
619 if (sys_truncate (fileno (fp
)) != 0)
620 truncate_error (listed_incremental_option
);
622 fprintf (fp
, "%s-%s-%d\n", PACKAGE_NAME
, PACKAGE_VERSION
,
623 TAR_INCREMENTAL_VERSION
);
625 fprintf (fp
, "%lu %lu\n",
626 (unsigned long int) start_time
.tv_sec
,
627 (unsigned long int) start_time
.tv_nsec
);
628 if (! ferror (fp
) && directory_table
)
629 hash_do_for_each (directory_table
, write_directory_file_entry
, fp
);
631 write_error (listed_incremental_option
);
632 if (fclose (fp
) != 0)
633 close_error (listed_incremental_option
);
637 /* Restoration of incremental dumps. */
640 get_gnu_dumpdir (struct tar_stat_info
*stat_info
)
644 union block
*data_block
;
648 size
= stat_info
->stat
.st_size
;
650 archive_dir
= xmalloc (size
);
653 set_next_block_after (current_header
);
654 mv_begin (stat_info
);
656 for (; size
> 0; size
-= copied
)
659 data_block
= find_next_block ();
661 ERROR ((1, 0, _("Unexpected EOF in archive")));
662 copied
= available_space_after (data_block
);
665 memcpy (to
, data_block
->buffer
, copied
);
667 set_next_block_after ((union block
*)
668 (data_block
->buffer
+ copied
- 1));
673 stat_info
->dumpdir
= archive_dir
;
674 stat_info
->skipped
= true; /* For skip_member() and friends
678 /* Return T if STAT_INFO represents a dumpdir archive member.
679 Note: can invalidate current_header. It happens if flush_archive()
680 gets called within get_gnu_dumpdir() */
682 is_dumpdir (struct tar_stat_info
*stat_info
)
684 if (stat_info
->is_dumpdir
&& !stat_info
->dumpdir
)
685 get_gnu_dumpdir (stat_info
);
686 return stat_info
->is_dumpdir
;
689 /* Examine the directories under directory_name and delete any
690 files that were not there at the time of the back-up. */
692 purge_directory (char const *directory_name
)
697 if (!is_dumpdir (¤t_stat_info
))
703 current_dir
= savedir (directory_name
);
707 /* The directory doesn't exist now. It'll be created. In any
708 case, we don't have to delete any files out of it. */
714 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
716 for (arc
= current_stat_info
.dumpdir
; *arc
; arc
+= strlen (arc
) + 1)
719 if (!strcmp (arc
, cur
))
725 char *p
= new_name (directory_name
, cur
);
727 if (deref_stat (false, p
, &st
))
730 WARN((0, 0, _("%s: Not purging directory: unable to stat"),
731 quotearg_colon (p
)));
734 else if (one_file_system_option
&& st
.st_dev
!= root_device
)
737 _("%s: directory is on a different device: not purging"),
738 quotearg_colon (p
)));
742 if (! interactive_option
|| confirm ("delete", p
))
745 fprintf (stdlis
, _("%s: Deleting %s\n"),
746 program_name
, quote (p
));
747 if (! remove_any_file (p
, RECURSIVE_REMOVE_OPTION
))
750 ERROR ((0, e
, _("%s: Cannot remove"), quotearg_colon (p
)));
761 list_dumpdir (char *buffer
, size_t size
)
770 fprintf (stdlis
, "%c ", *buffer
);
776 fputc ('\n', stdlis
);
782 fputc (*buffer
, stdlis
);