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 (one_file_system_option
&& device
!= stat_data
->st_dev
)
207 directory
->children
= NO_CHILDREN
;
208 else if (children
== ALL_CHILDREN
)
209 directory
->children
= ALL_CHILDREN
;
211 return directory
->children
;
215 /* Recursively scan the given directory. */
217 scan_directory (struct obstack
*stk
, char *dir_name
, dev_t device
)
219 char *dirp
= savedir (dir_name
); /* for scanning directory */
220 char const *entry
; /* directory entry being scanned */
221 size_t entrylen
; /* length of directory entry */
222 char *name_buffer
; /* directory, `/', and directory member */
223 size_t name_buffer_size
; /* allocated size of name_buffer, minus 2 */
224 size_t name_length
; /* used length in name_buffer */
225 enum children children
;
226 struct stat stat_data
;
229 savedir_error (dir_name
);
231 name_buffer_size
= strlen (dir_name
) + NAME_FIELD_SIZE
;
232 name_buffer
= xmalloc (name_buffer_size
+ 2);
233 strcpy (name_buffer
, dir_name
);
234 if (! ISSLASH (dir_name
[strlen (dir_name
) - 1]))
235 strcat (name_buffer
, "/");
236 name_length
= strlen (name_buffer
);
238 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
240 stat_diag (name_buffer
);
241 children
= CHANGED_CHILDREN
;
244 children
= procdir (name_buffer
, &stat_data
, device
, NO_CHILDREN
, false);
246 if (dirp
&& children
!= NO_CHILDREN
)
248 (entrylen
= strlen (entry
)) != 0;
249 entry
+= entrylen
+ 1)
251 if (name_buffer_size
<= entrylen
+ name_length
)
254 name_buffer_size
+= NAME_FIELD_SIZE
;
255 while (name_buffer_size
<= entrylen
+ name_length
);
256 name_buffer
= xrealloc (name_buffer
, name_buffer_size
+ 2);
258 strcpy (name_buffer
+ name_length
, entry
);
260 if (excluded_name (name_buffer
))
261 obstack_1grow (stk
, 'N');
265 if (deref_stat (dereference_option
, name_buffer
, &stat_data
))
267 stat_diag (name_buffer
);
271 if (S_ISDIR (stat_data
.st_mode
))
273 procdir (name_buffer
, &stat_data
, device
, children
,
275 obstack_1grow (stk
, 'D');
278 else if (one_file_system_option
&& device
!= stat_data
.st_dev
)
279 obstack_1grow (stk
, 'N');
282 else if (S_ISHIDDEN (stat_data
.st_mode
))
284 obstack_1grow (stk
, 'D');
285 obstack_grow (stk
, entry
, entrylen
);
286 obstack_grow (stk
, "A", 2);
292 if (children
== CHANGED_CHILDREN
293 && OLDER_STAT_TIME (stat_data
, m
)
294 && (!after_date_option
|| OLDER_STAT_TIME (stat_data
, c
)))
295 obstack_1grow (stk
, 'N');
297 obstack_1grow (stk
, 'Y');
300 obstack_grow (stk
, entry
, entrylen
+ 1);
303 obstack_grow (stk
, "\000\000", 2);
310 /* Sort the contents of the obstack, and convert it to the char * */
312 sort_obstack (struct obstack
*stk
)
314 char *pointer
= obstack_finish (stk
);
322 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
328 array
= obstack_alloc (stk
, sizeof (char *) * (counter
+ 1));
330 array_cursor
= array
;
331 for (cursor
= pointer
; *cursor
; cursor
+= strlen (cursor
) + 1)
332 *array_cursor
++ = cursor
;
335 qsort (array
, counter
, sizeof (char *), compare_dirents
);
337 buffer
= xmalloc (cursor
- pointer
+ 2);
340 for (array_cursor
= array
; *array_cursor
; array_cursor
++)
342 char *string
= *array_cursor
;
344 while ((*cursor
++ = *string
++))
352 get_directory_contents (char *dir_name
, dev_t device
)
358 scan_directory (&stk
, dir_name
, device
);
359 buffer
= sort_obstack (&stk
);
360 obstack_free (&stk
, NULL
);
365 dumpdir_size (const char *p
)
371 size_t size
= strlen (p
) + 1;
380 static FILE *listed_incremental_stream
;
382 /* Version of incremental format snapshots (directory files) used by this
383 tar. Currently it is supposed to be a single decimal number. 0 means
384 incremental snapshots as per tar version before 1.15.2.
386 The current tar version supports incremental versions from
387 0 up to TAR_INCREMENTAL_VERSION, inclusive.
388 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
390 #define TAR_INCREMENTAL_VERSION 1
392 /* Read incremental snapshot file (directory file).
393 If the file has older incremental version, make sure that it is processed
394 correctly and that tar will use the most conservative backup method among
395 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
396 etc.) This ensures that the snapshots are updated to the recent version
397 without any loss of data. */
399 read_directory_file (void)
406 /* Open the file for both read and write. That way, we can write
407 it later without having to reopen it, and don't have to worry if
408 we chdir in the meantime. */
409 fd
= open (listed_incremental_option
, O_RDWR
| O_CREAT
, MODE_RW
);
412 open_error (listed_incremental_option
);
416 fp
= fdopen (fd
, "r+");
419 open_error (listed_incremental_option
);
424 listed_incremental_stream
= fp
;
426 if (0 < getline (&buf
, &bufsize
, fp
))
433 int incremental_version
;
435 if (strncmp (buf
, PACKAGE_NAME
, sizeof PACKAGE_NAME
- 1) == 0)
437 ebuf
= buf
+ sizeof PACKAGE_NAME
- 1;
439 ERROR((1, 0, _("Bad incremental file format")));
440 for (; *ebuf
!= '-'; ebuf
++)
442 ERROR((1, 0, _("Bad incremental file format")));
444 incremental_version
= (errno
= 0, strtoumax (ebuf
+1, &ebuf
, 10));
445 if (getline (&buf
, &bufsize
, fp
) <= 0)
447 read_error (listed_incremental_option
);
454 incremental_version
= 0;
456 if (incremental_version
> TAR_INCREMENTAL_VERSION
)
457 ERROR((1, 0, _("Unsupported incremental format version: %s"),
458 incremental_version
));
460 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
461 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
462 ERROR ((0, 0, "%s:%ld: %s",
463 quotearg_colon (listed_incremental_option
),
465 _("Invalid time stamp")));
467 ERROR ((0, 0, "%s:%ld: %s",
468 quotearg_colon (listed_incremental_option
),
470 _("Time stamp out of range")));
471 else if (incremental_version
== 1)
473 newer_mtime_option
.tv_sec
= t
;
475 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
476 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
477 ERROR ((0, 0, "%s:%ld: %s",
478 quotearg_colon (listed_incremental_option
),
480 _("Invalid time stamp")));
482 ERROR ((0, 0, "%s:%ld: %s",
483 quotearg_colon (listed_incremental_option
),
485 _("Time stamp out of range")));
486 newer_mtime_option
.tv_nsec
= t
;
490 /* pre-1 incremental format does not contain nanoseconds */
491 newer_mtime_option
.tv_sec
= t
;
492 newer_mtime_option
.tv_nsec
= 0;
495 while (0 < (n
= getline (&buf
, &bufsize
, fp
)))
499 bool nfs
= buf
[0] == '+';
500 char *strp
= buf
+ nfs
;
501 struct timespec mtime
;
505 if (buf
[n
- 1] == '\n')
508 if (incremental_version
== 1)
511 mtime
.tv_sec
= u
= strtoumax (strp
, &ebuf
, 10);
512 if (!isspace (*ebuf
))
513 ERROR ((0, 0, "%s:%ld: %s",
514 quotearg_colon (listed_incremental_option
), lineno
,
515 _("Invalid modification time (seconds)")));
516 else if (mtime
.tv_sec
!= u
)
517 ERROR ((0, 0, "%s:%ld: %s",
518 quotearg_colon (listed_incremental_option
), lineno
,
519 _("Modification time (seconds) out of range")));
523 mtime
.tv_nsec
= u
= strtoumax (strp
, &ebuf
, 10);
524 if (!isspace (*ebuf
))
525 ERROR ((0, 0, "%s:%ld: %s",
526 quotearg_colon (listed_incremental_option
), lineno
,
527 _("Invalid modification time (nanoseconds)")));
528 else if (mtime
.tv_nsec
!= u
)
529 ERROR ((0, 0, "%s:%ld: %s",
530 quotearg_colon (listed_incremental_option
), lineno
,
531 _("Modification time (nanoseconds) out of range")));
535 memset (&mtime
, 0, sizeof mtime
);
538 dev
= u
= strtoumax (strp
, &ebuf
, 10);
539 if (!isspace (*ebuf
))
540 ERROR ((0, 0, "%s:%ld: %s",
541 quotearg_colon (listed_incremental_option
), lineno
,
542 _("Invalid device number")));
544 ERROR ((0, 0, "%s:%ld: %s",
545 quotearg_colon (listed_incremental_option
), lineno
,
546 _("Device number out of range")));
550 ino
= u
= strtoumax (strp
, &ebuf
, 10);
551 if (!isspace (*ebuf
))
552 ERROR ((0, 0, "%s:%ld: %s",
553 quotearg_colon (listed_incremental_option
), lineno
,
554 _("Invalid inode number")));
556 ERROR ((0, 0, "%s:%ld: %s",
557 quotearg_colon (listed_incremental_option
), lineno
,
558 _("Inode number out of range")));
562 unquote_string (strp
);
563 note_directory (strp
, mtime
, dev
, ino
, nfs
, 0);
568 read_error (listed_incremental_option
);
573 /* Output incremental data for the directory ENTRY to the file DATA.
574 Return nonzero if successful, preserving errno on write failure. */
576 write_directory_file_entry (void *entry
, void *data
)
578 struct directory
const *directory
= entry
;
581 if (directory
->found
)
584 char buf
[UINTMAX_STRSIZE_BOUND
];
585 char *str
= quote_copy_string (directory
->name
);
589 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_sec
, buf
));
590 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_nsec
, buf
));
591 fprintf (fp
, "%s ", umaxtostr (directory
->device_number
, buf
));
592 fprintf (fp
, "%s ", umaxtostr (directory
->inode_number
, buf
));
593 fprintf (fp
, "%s\n", str
? str
: directory
->name
);
601 return ! ferror (fp
);
605 write_directory_file (void)
607 FILE *fp
= listed_incremental_stream
;
612 if (fseek (fp
, 0L, SEEK_SET
) != 0)
613 seek_error (listed_incremental_option
);
614 if (sys_truncate (fileno (fp
)) != 0)
615 truncate_error (listed_incremental_option
);
617 fprintf (fp
, "%s-%s-%d\n", PACKAGE_NAME
, PACKAGE_VERSION
,
618 TAR_INCREMENTAL_VERSION
);
620 fprintf (fp
, "%lu %lu\n",
621 (unsigned long int) start_time
.tv_sec
,
622 (unsigned long int) start_time
.tv_nsec
);
623 if (! ferror (fp
) && directory_table
)
624 hash_do_for_each (directory_table
, write_directory_file_entry
, fp
);
626 write_error (listed_incremental_option
);
627 if (fclose (fp
) != 0)
628 close_error (listed_incremental_option
);
632 /* Restoration of incremental dumps. */
639 union block
*data_block
;
643 size
= current_stat_info
.stat
.st_size
;
644 if (size
!= current_stat_info
.stat
.st_size
)
647 archive_dir
= xmalloc (size
);
650 set_next_block_after (current_header
);
651 mv_begin (¤t_stat_info
);
653 for (; size
> 0; size
-= copied
)
656 data_block
= find_next_block ();
658 ERROR ((1, 0, _("Unexpected EOF in archive")));
659 copied
= available_space_after (data_block
);
662 memcpy (to
, data_block
->buffer
, copied
);
664 set_next_block_after ((union block
*)
665 (data_block
->buffer
+ copied
- 1));
670 current_stat_info
.stat
.st_size
= 0; /* For skip_member() and friends
672 current_stat_info
.dumpdir
= archive_dir
;
676 /* Examine the directories under directory_name and delete any
677 files that were not there at the time of the back-up. */
679 purge_directory (char const *directory_name
)
684 if (!current_stat_info
.dumpdir
)
690 current_dir
= savedir (directory_name
);
694 /* The directory doesn't exist now. It'll be created. In any
695 case, we don't have to delete any files out of it. */
701 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
703 for (arc
= current_stat_info
.dumpdir
; *arc
; arc
+= strlen (arc
) + 1)
706 if (!strcmp (arc
, cur
))
712 char *p
= new_name (directory_name
, cur
);
714 if (deref_stat (false, p
, &st
))
717 WARN((0, 0, _("%s: Not purging directory: unable to stat"),
718 quotearg_colon (p
)));
721 else if (one_file_system_option
&& st
.st_dev
!= root_device
)
724 _("%s: directory is on a different device: not purging"),
725 quotearg_colon (p
)));
729 if (! interactive_option
|| confirm ("delete", p
))
732 fprintf (stdlis
, _("%s: Deleting %s\n"),
733 program_name
, quote (p
));
734 if (! remove_any_file (p
, RECURSIVE_REMOVE_OPTION
))
737 ERROR ((0, e
, _("%s: Cannot remove"), quotearg_colon (p
)));
748 list_dumpdir (char *buffer
, size_t size
)
757 fprintf (stdlis
, "%c ", *buffer
);
763 fputc ('\n', stdlis
);
769 fputc (*buffer
, stdlis
);