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
);
366 static FILE *listed_incremental_stream
;
368 /* Version of incremental format snapshots (directory files) used by this
369 tar. Currently it is supposed to be a single decimal number. 0 means
370 incremental snapshots as per tar version before 1.15.2.
372 The current tar version supports incremental versions from
373 0 up to TAR_INCREMENTAL_VERSION, inclusive.
374 It is able to create only snapshots of TAR_INCREMENTAL_VERSION */
376 #define TAR_INCREMENTAL_VERSION 1
378 /* Read incremental snapshot file (directory file).
379 If the file has older incremental version, make sure that it is processed
380 correctly and that tar will use the most conservative backup method among
381 possible alternatives (i.e. prefer ALL_CHILDREN over CHANGED_CHILDREN,
382 etc.) This ensures that the snapshots are updated to the recent version
383 without any loss of data. */
385 read_directory_file (void)
392 /* Open the file for both read and write. That way, we can write
393 it later without having to reopen it, and don't have to worry if
394 we chdir in the meantime. */
395 fd
= open (listed_incremental_option
, O_RDWR
| O_CREAT
, MODE_RW
);
398 open_error (listed_incremental_option
);
402 fp
= fdopen (fd
, "r+");
405 open_error (listed_incremental_option
);
410 listed_incremental_stream
= fp
;
412 if (0 < getline (&buf
, &bufsize
, fp
))
419 int incremental_version
;
421 if (strncmp (buf
, PACKAGE_NAME
, sizeof PACKAGE_NAME
- 1) == 0)
423 ebuf
= buf
+ sizeof PACKAGE_NAME
- 1;
425 ERROR((1, 0, _("Bad incremental file format")));
426 for (; *ebuf
!= '-'; ebuf
++)
428 ERROR((1, 0, _("Bad incremental file format")));
430 incremental_version
= (errno
= 0, strtoumax (ebuf
+1, &ebuf
, 10));
431 if (getline (&buf
, &bufsize
, fp
) <= 0)
433 read_error (listed_incremental_option
);
440 incremental_version
= 0;
442 if (incremental_version
> TAR_INCREMENTAL_VERSION
)
443 ERROR((1, 0, _("Unsupported incremental format version: %s"),
444 incremental_version
));
446 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
447 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
448 ERROR ((0, 0, "%s:%ld: %s",
449 quotearg_colon (listed_incremental_option
),
451 _("Invalid time stamp")));
453 ERROR ((0, 0, "%s:%ld: %s",
454 quotearg_colon (listed_incremental_option
),
456 _("Time stamp out of range")));
457 else if (incremental_version
== 1)
459 newer_mtime_option
.tv_sec
= t
;
461 t
= u
= (errno
= 0, strtoumax (buf
, &ebuf
, 10));
462 if (buf
== ebuf
|| (u
== 0 && errno
== EINVAL
))
463 ERROR ((0, 0, "%s:%ld: %s",
464 quotearg_colon (listed_incremental_option
),
466 _("Invalid time stamp")));
468 ERROR ((0, 0, "%s:%ld: %s",
469 quotearg_colon (listed_incremental_option
),
471 _("Time stamp out of range")));
472 newer_mtime_option
.tv_nsec
= t
;
476 /* pre-1 incremental format does not contain nanoseconds */
477 newer_mtime_option
.tv_sec
= t
;
478 newer_mtime_option
.tv_nsec
= 0;
481 while (0 < (n
= getline (&buf
, &bufsize
, fp
)))
485 bool nfs
= buf
[0] == '+';
486 char *strp
= buf
+ nfs
;
487 struct timespec mtime
;
491 if (buf
[n
- 1] == '\n')
494 if (incremental_version
== 1)
497 mtime
.tv_sec
= u
= strtoumax (strp
, &ebuf
, 10);
498 if (!isspace (*ebuf
))
499 ERROR ((0, 0, "%s:%ld: %s",
500 quotearg_colon (listed_incremental_option
), lineno
,
501 _("Invalid modification time (seconds)")));
502 else if (mtime
.tv_sec
!= u
)
503 ERROR ((0, 0, "%s:%ld: %s",
504 quotearg_colon (listed_incremental_option
), lineno
,
505 _("Modification time (seconds) out of range")));
509 mtime
.tv_nsec
= u
= strtoumax (strp
, &ebuf
, 10);
510 if (!isspace (*ebuf
))
511 ERROR ((0, 0, "%s:%ld: %s",
512 quotearg_colon (listed_incremental_option
), lineno
,
513 _("Invalid modification time (nanoseconds)")));
514 else if (mtime
.tv_nsec
!= u
)
515 ERROR ((0, 0, "%s:%ld: %s",
516 quotearg_colon (listed_incremental_option
), lineno
,
517 _("Modification time (nanoseconds) out of range")));
521 memset (&mtime
, 0, sizeof mtime
);
524 dev
= u
= strtoumax (strp
, &ebuf
, 10);
525 if (!isspace (*ebuf
))
526 ERROR ((0, 0, "%s:%ld: %s",
527 quotearg_colon (listed_incremental_option
), lineno
,
528 _("Invalid device number")));
530 ERROR ((0, 0, "%s:%ld: %s",
531 quotearg_colon (listed_incremental_option
), lineno
,
532 _("Device number out of range")));
536 ino
= u
= strtoumax (strp
, &ebuf
, 10);
537 if (!isspace (*ebuf
))
538 ERROR ((0, 0, "%s:%ld: %s",
539 quotearg_colon (listed_incremental_option
), lineno
,
540 _("Invalid inode number")));
542 ERROR ((0, 0, "%s:%ld: %s",
543 quotearg_colon (listed_incremental_option
), lineno
,
544 _("Inode number out of range")));
548 unquote_string (strp
);
549 note_directory (strp
, mtime
, dev
, ino
, nfs
, 0);
554 read_error (listed_incremental_option
);
559 /* Output incremental data for the directory ENTRY to the file DATA.
560 Return nonzero if successful, preserving errno on write failure. */
562 write_directory_file_entry (void *entry
, void *data
)
564 struct directory
const *directory
= entry
;
567 if (directory
->found
)
570 char buf
[UINTMAX_STRSIZE_BOUND
];
571 char *str
= quote_copy_string (directory
->name
);
575 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_sec
, buf
));
576 fprintf (fp
, "%s ", umaxtostr (directory
->mtime
.tv_nsec
, buf
));
577 fprintf (fp
, "%s ", umaxtostr (directory
->device_number
, buf
));
578 fprintf (fp
, "%s ", umaxtostr (directory
->inode_number
, buf
));
579 fprintf (fp
, "%s\n", str
? str
: directory
->name
);
587 return ! ferror (fp
);
591 write_directory_file (void)
593 FILE *fp
= listed_incremental_stream
;
598 if (fseek (fp
, 0L, SEEK_SET
) != 0)
599 seek_error (listed_incremental_option
);
600 if (sys_truncate (fileno (fp
)) != 0)
601 truncate_error (listed_incremental_option
);
603 fprintf (fp
, "%s-%s-%d\n", PACKAGE_NAME
, PACKAGE_VERSION
,
604 TAR_INCREMENTAL_VERSION
);
606 fprintf (fp
, "%lu %lu\n",
607 (unsigned long int) start_time
.tv_sec
,
608 (unsigned long int) start_time
.tv_nsec
);
609 if (! ferror (fp
) && directory_table
)
610 hash_do_for_each (directory_table
, write_directory_file_entry
, fp
);
612 write_error (listed_incremental_option
);
613 if (fclose (fp
) != 0)
614 close_error (listed_incremental_option
);
618 /* Restoration of incremental dumps. */
620 /* Examine the directories under directory_name and delete any
621 files that were not there at the time of the back-up. */
623 purge_directory (char const *directory_name
)
630 union block
*data_block
;
633 current_dir
= savedir (directory_name
);
637 /* The directory doesn't exist now. It'll be created. In any
638 case, we don't have to delete any files out of it. */
644 size
= current_stat_info
.stat
.st_size
;
645 if (size
!= current_stat_info
.stat
.st_size
)
647 archive_dir
= xmalloc (size
);
649 for (; size
> 0; size
-= copied
)
651 data_block
= find_next_block ();
654 ERROR ((0, 0, _("Unexpected EOF in archive")));
655 break; /* FIXME: What happens then? */
657 copied
= available_space_after (data_block
);
660 memcpy (to
, data_block
->buffer
, copied
);
662 set_next_block_after ((union block
*)
663 (data_block
->buffer
+ copied
- 1));
666 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
668 for (arc
= archive_dir
; *arc
; arc
+= strlen (arc
) + 1)
671 if (!strcmp (arc
, cur
))
677 char *p
= new_name (directory_name
, cur
);
679 if (deref_stat (false, p
, &st
))
682 WARN((0, 0, _("%s: Not purging directory: unable to stat"),
683 quotearg_colon (p
)));
686 else if (one_file_system_option
&& st
.st_dev
!= root_device
)
689 _("%s: directory is on a different device: not purging"),
690 quotearg_colon (p
)));
694 if (! interactive_option
|| confirm ("delete", p
))
697 fprintf (stdlis
, _("%s: Deleting %s\n"),
698 program_name
, quote (p
));
699 if (! remove_any_file (p
, RECURSIVE_REMOVE_OPTION
))
702 ERROR ((0, e
, _("%s: Cannot remove"), quotearg_colon (p
)));
714 list_dumpdir (char *buffer
, size_t size
)
723 fprintf (stdlis
, "%c ", *buffer
);
729 fputc ('\n', stdlis
);
735 fputc (*buffer
, stdlis
);