1 /* GNU dump extensions to tar.
3 Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
4 2003, 2004, 2005 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
);
154 if ((directory
= find_directory (name_buffer
)) != NULL
)
156 /* With NFS, the same file can have two different devices
157 if an NFS directory is mounted in multiple locations,
158 which is relatively common when automounting.
159 To avoid spurious incremental redumping of
160 directories, consider all NFS devices as equal,
161 relying on the i-node to establish differences. */
163 if (! (((directory
->nfs
& nfs
)
164 || directory
->device_number
== stat_data
->st_dev
)
165 && directory
->inode_number
== stat_data
->st_ino
))
168 WARN ((0, 0, _("%s: Directory has been renamed"),
169 quotearg_colon (name_buffer
)));
170 directory
->children
= ALL_CHILDREN
;
171 directory
->nfs
= nfs
;
172 directory
->device_number
= stat_data
->st_dev
;
173 directory
->inode_number
= stat_data
->st_ino
;
175 else if (listed_incremental_option
)
176 /* Newer modification time can mean that new files were
177 created in the directory or some of the existing files
179 directory
->children
=
180 timespec_cmp (get_stat_mtime (stat_data
), directory
->mtime
) > 0
181 ? ALL_CHILDREN
: CHANGED_CHILDREN
;
183 directory
->found
= true;
188 WARN ((0, 0, _("%s: Directory is new"),
189 quotearg_colon (name_buffer
)));
190 directory
= note_directory (name_buffer
,
191 get_stat_mtime(stat_data
),
197 directory
->children
=
198 (listed_incremental_option
199 || (OLDER_STAT_TIME (*stat_data
, m
)
200 || (after_date_option
201 && OLDER_STAT_TIME (*stat_data
, c
))))
206 /* If the directory is on another device and --one-file-system was given,
208 if (one_file_system_option
&& device
!= stat_data
->st_dev
209 /* ... except if it was explicitely given in the command line */
210 && !name_scan (name_buffer
))
211 directory
->children
= NO_CHILDREN
;
212 else if (children
== ALL_CHILDREN
)
213 directory
->children
= ALL_CHILDREN
;
215 return directory
->children
;
219 /* Recursively scan the given directory. */
221 scan_directory (struct obstack
*stk
, char *dir_name
, dev_t device
)
223 char *dirp
= savedir (dir_name
); /* for scanning directory */
224 char const *entry
; /* directory entry being scanned */
225 size_t entrylen
; /* length of directory entry */
226 char *name_buffer
; /* directory, `/', and directory member */
227 size_t name_buffer_size
; /* allocated size of name_buffer, minus 2 */
228 size_t name_length
; /* used length in name_buffer */
229 enum children children
;
230 struct stat stat_data
;
233 savedir_error (dir_name
);
235 name_buffer_size
= strlen (dir_name
) + NAME_FIELD_SIZE
;
236 name_buffer
= xmalloc (name_buffer_size
+ 2);
237 strcpy (name_buffer
, dir_name
);
238 if (! ISSLASH (dir_name
[strlen (dir_name
) - 1]))
239 strcat (name_buffer
, "/");
240 name_length
= strlen (name_buffer
);
242 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
244 stat_diag (name_buffer
);
245 children
= CHANGED_CHILDREN
;
248 children
= procdir (name_buffer
, &stat_data
, device
, NO_CHILDREN
, false);
250 if (dirp
&& children
!= NO_CHILDREN
)
252 (entrylen
= strlen (entry
)) != 0;
253 entry
+= entrylen
+ 1)
255 if (name_buffer_size
<= entrylen
+ name_length
)
258 name_buffer_size
+= NAME_FIELD_SIZE
;
259 while (name_buffer_size
<= entrylen
+ name_length
);
260 name_buffer
= xrealloc (name_buffer
, name_buffer_size
+ 2);
262 strcpy (name_buffer
+ name_length
, entry
);
264 if (excluded_name (name_buffer
))
265 obstack_1grow (stk
, 'N');
269 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
271 stat_diag (name_buffer
);
275 if (S_ISDIR (stat_data
.st_mode
))
277 procdir (name_buffer
, &stat_data
, device
, children
,
279 obstack_1grow (stk
, 'D');
282 else if (one_file_system_option
&& device
!= stat_data
.st_dev
)
283 obstack_1grow (stk
, 'N');
286 else if (S_ISHIDDEN (stat_data
.st_mode
))
288 obstack_1grow (stk
, 'D');
289 obstack_grow (stk
, entry
, entrylen
);
290 obstack_grow (stk
, "A", 2);
296 if (children
== CHANGED_CHILDREN
297 && OLDER_STAT_TIME (stat_data
, m
)
298 && (!after_date_option
|| OLDER_STAT_TIME (stat_data
, c
)))
299 obstack_1grow (stk
, 'N');
301 obstack_1grow (stk
, 'Y');
304 obstack_grow (stk
, entry
, entrylen
+ 1);
307 obstack_grow (stk
, "\000\000", 2);
314 /* Sort the contents of the obstack, and convert it to the char * */
316 sort_obstack (struct obstack
*stk
)
318 char *pointer
= obstack_finish (stk
);
326 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
332 array
= obstack_alloc (stk
, sizeof (char *) * (counter
+ 1));
334 array_cursor
= array
;
335 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
336 *array_cursor
++ = cursor
;
339 qsort (array
, counter
, sizeof (char *), compare_dirents
);
341 buffer
= xmalloc (cursor
- pointer
+ 2);
344 for (array_cursor
= array
; *array_cursor
; array_cursor
++)
346 char *string
= *array_cursor
;
348 while ((*cursor
++ = *string
++))
356 get_directory_contents (char *dir_name
, dev_t device
)
362 scan_directory (&stk
, dir_name
, device
);
363 buffer
= sort_obstack (&stk
);
364 obstack_free (&stk
, NULL
);
369 dumpdir_size (const char *p
)
375 size_t size
= strlen (p
) + 1;
384 static FILE *listed_incremental_stream
;
386 /* Version of incremental format snapshots (directory files) used by this
387 tar. Currently it is supposed to be a single decimal number. 0 means
388 incremental snapshots as per tar version before 1.15.2.
390 The current tar version supports incremental versions from
391 0 up to TAR_INCREMENTAL_VERSION, inclusive.
392 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
394 #define TAR_INCREMENTAL_VERSION 1
396 /* Read incremental snapshot file (directory file).
397 If the file has older incremental version, make sure that it is processed
398 correctly and that tar will use the most conservative backup method among
399 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
400 etc.) This ensures that the snapshots are updated to the recent version
401 without any loss of data. */
403 read_directory_file (void)
410 /* Open the file for both read and write. That way, we can write
411 it later without having to reopen it, and don't have to worry if
412 we chdir in the meantime. */
413 fd
= open (listed_incremental_option
, O_RDWR
| O_CREAT
, MODE_RW
);
416 open_error (listed_incremental_option
);
420 fp
= fdopen (fd
, "r+");
423 open_error (listed_incremental_option
);
428 listed_incremental_stream
= fp
;
430 if (0 < getline (&buf
, &bufsize
, fp
))
437 int incremental_version
;
439 if (strncmp (buf
, PACKAGE_NAME
, sizeof PACKAGE_NAME
- 1) == 0)
441 ebuf
= buf
+ sizeof PACKAGE_NAME
- 1;
443 ERROR((1, 0, _("Bad incremental file format")));
444 for (; *ebuf
!= '-'; ebuf
++)
446 ERROR((1, 0, _("Bad incremental file format")));
448 incremental_version
= (errno
= 0, strtoumax (ebuf
+1, &ebuf
, 10));
449 if (getline (&buf
, &bufsize
, fp
) <= 0)
451 read_error (listed_incremental_option
);
458 incremental_version
= 0;
460 if (incremental_version
> TAR_INCREMENTAL_VERSION
)
461 ERROR((1, 0, _("Unsupported incremental format version: %d"),
462 incremental_version
));
464 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
465 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
466 ERROR ((0, 0, "%s:%ld: %s",
467 quotearg_colon (listed_incremental_option
),
469 _("Invalid time stamp")));
471 ERROR ((0, 0, "%s:%ld: %s",
472 quotearg_colon (listed_incremental_option
),
474 _("Time stamp out of range")));
475 else if (incremental_version
== 1)
477 newer_mtime_option
.tv_sec
= t
;
479 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
480 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
481 ERROR ((0, 0, "%s:%ld: %s",
482 quotearg_colon (listed_incremental_option
),
484 _("Invalid time stamp")));
486 ERROR ((0, 0, "%s:%ld: %s",
487 quotearg_colon (listed_incremental_option
),
489 _("Time stamp out of range")));
490 newer_mtime_option
.tv_nsec
= t
;
494 /* pre-1 incremental format does not contain nanoseconds */
495 newer_mtime_option
.tv_sec
= t
;
496 newer_mtime_option
.tv_nsec
= 0;
499 while (0 < (n
= getline (&buf
, &bufsize
, fp
)))
503 bool nfs
= buf
[0] == '+';
504 char *strp
= buf
+ nfs
;
505 struct timespec mtime
;
509 if (buf
[n
- 1] == '\n')
512 if (incremental_version
== 1)
515 mtime
.tv_sec
= u
= strtoumax (strp
, &ebuf
, 10);
516 if (!isspace (*ebuf
))
517 ERROR ((0, 0, "%s:%ld: %s",
518 quotearg_colon (listed_incremental_option
), lineno
,
519 _("Invalid modification time (seconds)")));
520 else if (mtime
.tv_sec
!= u
)
521 ERROR ((0, 0, "%s:%ld: %s",
522 quotearg_colon (listed_incremental_option
), lineno
,
523 _("Modification time (seconds) out of range")));
527 mtime
.tv_nsec
= u
= strtoumax (strp
, &ebuf
, 10);
528 if (!isspace (*ebuf
))
529 ERROR ((0, 0, "%s:%ld: %s",
530 quotearg_colon (listed_incremental_option
), lineno
,
531 _("Invalid modification time (nanoseconds)")));
532 else if (mtime
.tv_nsec
!= u
)
533 ERROR ((0, 0, "%s:%ld: %s",
534 quotearg_colon (listed_incremental_option
), lineno
,
535 _("Modification time (nanoseconds) out of range")));
539 memset (&mtime
, 0, sizeof mtime
);
542 dev
= u
= strtoumax (strp
, &ebuf
, 10);
543 if (!isspace (*ebuf
))
544 ERROR ((0, 0, "%s:%ld: %s",
545 quotearg_colon (listed_incremental_option
), lineno
,
546 _("Invalid device number")));
548 ERROR ((0, 0, "%s:%ld: %s",
549 quotearg_colon (listed_incremental_option
), lineno
,
550 _("Device number out of range")));
554 ino
= u
= strtoumax (strp
, &ebuf
, 10);
555 if (!isspace (*ebuf
))
556 ERROR ((0, 0, "%s:%ld: %s",
557 quotearg_colon (listed_incremental_option
), lineno
,
558 _("Invalid inode number")));
560 ERROR ((0, 0, "%s:%ld: %s",
561 quotearg_colon (listed_incremental_option
), lineno
,
562 _("Inode number out of range")));
566 unquote_string (strp
);
567 note_directory (strp
, mtime
, dev
, ino
, nfs
, 0);
572 read_error (listed_incremental_option
);
577 /* Output incremental data for the directory ENTRY to the file DATA.
578 Return nonzero if successful, preserving errno on write failure. */
580 write_directory_file_entry (void *entry
, void *data
)
582 struct directory
const *directory
= entry
;
585 if (directory
->found
)
588 char buf
[UINTMAX_STRSIZE_BOUND
];
589 char *str
= quote_copy_string (directory
->name
);
593 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_sec
, buf
));
594 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_nsec
, buf
));
595 fprintf (fp
, "%s ", umaxtostr (directory
->device_number
, buf
));
596 fprintf (fp
, "%s ", umaxtostr (directory
->inode_number
, buf
));
597 fprintf (fp
, "%s\n", str
? str
: directory
->name
);
605 return ! ferror (fp
);
609 write_directory_file (void)
611 FILE *fp
= listed_incremental_stream
;
616 if (fseek (fp
, 0L, SEEK_SET
) != 0)
617 seek_error (listed_incremental_option
);
618 if (sys_truncate (fileno (fp
)) != 0)
619 truncate_error (listed_incremental_option
);
621 fprintf (fp
, "%s-%s-%d\n", PACKAGE_NAME
, PACKAGE_VERSION
,
622 TAR_INCREMENTAL_VERSION
);
624 fprintf (fp
, "%lu %lu\n",
625 (unsigned long int) start_time
.tv_sec
,
626 (unsigned long int) start_time
.tv_nsec
);
627 if (! ferror (fp
) && directory_table
)
628 hash_do_for_each (directory_table
, write_directory_file_entry
, fp
);
630 write_error (listed_incremental_option
);
631 if (fclose (fp
) != 0)
632 close_error (listed_incremental_option
);
636 /* Restoration of incremental dumps. */
643 union block
*data_block
;
647 size
= current_stat_info
.stat
.st_size
;
648 if (size
!= current_stat_info
.stat
.st_size
)
651 archive_dir
= xmalloc (size
);
654 set_next_block_after (current_header
);
655 mv_begin (¤t_stat_info
);
657 for (; size
> 0; size
-= copied
)
660 data_block
= find_next_block ();
662 ERROR ((1, 0, _("Unexpected EOF in archive")));
663 copied
= available_space_after (data_block
);
666 memcpy (to
, data_block
->buffer
, copied
);
668 set_next_block_after ((union block
*)
669 (data_block
->buffer
+ copied
- 1));
674 current_stat_info
.stat
.st_size
= 0; /* For skip_member() and friends
676 current_stat_info
.dumpdir
= archive_dir
;
680 /* Examine the directories under directory_name and delete any
681 files that were not there at the time of the back-up. */
683 purge_directory (char const *directory_name
)
688 if (!current_stat_info
.dumpdir
)
694 current_dir
= savedir (directory_name
);
698 /* The directory doesn't exist now. It'll be created. In any
699 case, we don't have to delete any files out of it. */
705 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
707 for (arc
= current_stat_info
.dumpdir
; *arc
; arc
+= strlen (arc
) + 1)
710 if (!strcmp (arc
, cur
))
716 char *p
= new_name (directory_name
, cur
);
718 if (deref_stat (false, p
, &st
))
721 WARN((0, 0, _("%s: Not purging directory: unable to stat"),
722 quotearg_colon (p
)));
725 else if (one_file_system_option
&& st
.st_dev
!= root_device
)
728 _("%s: directory is on a different device: not purging"),
729 quotearg_colon (p
)));
733 if (! interactive_option
|| confirm ("delete", p
))
736 fprintf (stdlis
, _("%s: Deleting %s\n"),
737 program_name
, quote (p
));
738 if (! remove_any_file (p
, RECURSIVE_REMOVE_OPTION
))
741 ERROR ((0, e
, _("%s: Cannot remove"), quotearg_colon (p
)));
752 list_dumpdir (char *buffer
, size_t size
)
761 fprintf (stdlis
, "%c ", *buffer
);
767 fputc ('\n', stdlis
);
773 fputc (*buffer
, stdlis
);