X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=69805a7f779dc72710865febf85182abc4972636;hb=d659cbaccdc1f3279c49107cf15f15a639738529;hp=facc751c4bc20dbc9fb7a05d2055f9d62087d31c;hpb=e8af2fec8a7ac51bc8a80586566b342044119fe8;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index facc751..69805a7 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -1,7 +1,7 @@ /* GNU dump extensions to tar. Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, - 2003, 2004 Free Software Foundation, Inc. + 2003, 2004, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -15,16 +15,13 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "system.h" +#include #include #include #include #include "common.h" -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free -#include /* Incremental dump specialities. */ @@ -39,7 +36,7 @@ struct directory enum children children; bool nfs; bool found; - char name[1]; /* path name of directory */ + char name[1]; /* file name of directory */ }; static Hash_table *directory_table; @@ -53,8 +50,8 @@ static Hash_table *directory_table; #endif /* Calculate the hash of a directory. */ -static unsigned -hash_directory (void const *entry, unsigned n_buckets) +static size_t +hash_directory (void const *entry, size_t n_buckets) { struct directory const *directory = entry; return hash_string (directory->name, n_buckets); @@ -95,7 +92,7 @@ note_directory (char const *name, dev_t dev, ino_t ino, bool nfs, bool found) return directory; } -/* Return a directory entry for a given path NAME, or zero if none found. */ +/* Return a directory entry for a given file NAME, or zero if none found. */ static struct directory * find_directory (char *name) { @@ -117,11 +114,11 @@ compare_dirents (const void *first, const void *second) (*(char *const *) second) + 1); } -/* Recursively scan the given PATH. */ +/* Recursively scan the given directory. */ static void -scan_path (struct obstack *stk, char *path, dev_t device) +scan_directory (struct obstack *stk, char *dir_name, dev_t device) { - char *dirp = savedir (path); /* for scanning directory */ + char *dirp = savedir (dir_name); /* for scanning directory */ char const *entry; /* directory entry being scanned */ size_t entrylen; /* length of directory entry */ char *name_buffer; /* directory, `/', and directory member */ @@ -132,20 +129,20 @@ scan_path (struct obstack *stk, char *path, dev_t device) if (! dirp) { - savedir_error (path); + savedir_error (dir_name); } errno = 0; - name_buffer_size = strlen (path) + NAME_FIELD_SIZE; + name_buffer_size = strlen (dir_name) + NAME_FIELD_SIZE; name_buffer = xmalloc (name_buffer_size + 2); - strcpy (name_buffer, path); - if (! ISSLASH (path[strlen (path) - 1])) + strcpy (name_buffer, dir_name); + if (! ISSLASH (dir_name[strlen (dir_name) - 1])) strcat (name_buffer, "/"); name_length = strlen (name_buffer); - directory = find_directory (path); + directory = find_directory (dir_name); children = directory ? directory->children : CHANGED_CHILDREN; - + if (dirp && children != NO_CHILDREN) for (entry = dirp; (entrylen = strlen (entry)) != 0; @@ -159,23 +156,23 @@ scan_path (struct obstack *stk, char *path, dev_t device) name_buffer = xrealloc (name_buffer, name_buffer_size + 2); } strcpy (name_buffer + name_length, entry); - + if (excluded_name (name_buffer)) obstack_1grow (stk, 'N'); else { struct stat stat_data; - + if (deref_stat (dereference_option, name_buffer, &stat_data)) { stat_diag (name_buffer); continue; } - + if (S_ISDIR (stat_data.st_mode)) { bool nfs = NFS_FILE_STAT (stat_data); - + if ((directory = find_directory (name_buffer)) != NULL) { /* With NFS, the same file can have two different devices @@ -184,7 +181,7 @@ scan_path (struct obstack *stk, char *path, dev_t device) To avoid spurious incremental redumping of directories, consider all NFS devices as equal, relying on the i-node to establish differences. */ - + if (! (((directory->nfs & nfs) || directory->device_number == stat_data.st_dev) && directory->inode_number == stat_data.st_ino)) @@ -209,13 +206,13 @@ scan_path (struct obstack *stk, char *path, dev_t device) stat_data.st_ino, nfs, 1); directory->children = ((listed_incremental_option - || newer_mtime_option <= stat_data.st_mtime - || (after_date_option && - newer_ctime_option <= stat_data.st_ctime)) + || OLDER_STAT_TIME (stat_data, m) + || (after_date_option + && OLDER_STAT_TIME (stat_data, c))) ? ALL_CHILDREN : CHANGED_CHILDREN); } - + if (one_file_system_option && device != stat_data.st_dev) directory->children = NO_CHILDREN; else if (children == ALL_CHILDREN) @@ -239,19 +236,18 @@ scan_path (struct obstack *stk, char *path, dev_t device) else if (children == CHANGED_CHILDREN - && stat_data.st_mtime < newer_mtime_option - && (!after_date_option - || stat_data.st_ctime < newer_ctime_option)) + && OLDER_STAT_TIME (stat_data, m) + && (!after_date_option || OLDER_STAT_TIME (stat_data, c))) obstack_1grow (stk, 'N'); else obstack_1grow (stk, 'Y'); } - + obstack_grow (stk, entry, entrylen + 1); } obstack_grow (stk, "\000\000", 2); - + free (name_buffer); if (dirp) free (dirp); @@ -267,16 +263,16 @@ sort_obstack (struct obstack *stk) char *buffer; char **array; char **array_cursor; - + counter = 0; for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1) counter++; - + if (!counter) return NULL; array = obstack_alloc (stk, sizeof (char *) * (counter + 1)); - + array_cursor = array; for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1) *array_cursor++ = cursor; @@ -290,7 +286,7 @@ sort_obstack (struct obstack *stk) for (array_cursor = array; *array_cursor; array_cursor++) { char *string = *array_cursor; - + while ((*cursor++ = *string++)) continue; } @@ -299,13 +295,13 @@ sort_obstack (struct obstack *stk) } char * -get_directory_contents (char *path, dev_t device) +get_directory_contents (char *dir_name, dev_t device) { struct obstack stk; char *buffer; obstack_init (&stk); - scan_path (&stk, path, device); + scan_directory (&stk, dir_name, device); buffer = sort_obstack (&stk); obstack_free (&stk, NULL); return buffer; @@ -357,7 +353,12 @@ read_directory_file (void) ERROR ((0, 0, "%s:1: %s", quotearg_colon (listed_incremental_option), _("Time stamp out of range"))); else - newer_mtime_option = t; + { + /* FIXME: This should also input nanoseconds, but that will be a + change in file format. */ + newer_mtime_option.tv_sec = t; + newer_mtime_option.tv_nsec = 0; + } while (0 < (n = getline (&buf, &bufsize, fp))) { @@ -445,7 +446,9 @@ write_directory_file (void) if (sys_truncate (fileno (fp)) != 0) truncate_error (listed_incremental_option); - fprintf (fp, "%lu\n", (unsigned long) start_time); + /* FIXME: This should also output nanoseconds, but that will be a + change in file format. */ + fprintf (fp, "%lu\n", (unsigned long int) start_time.tv_sec); if (! ferror (fp) && directory_table) hash_do_for_each (directory_table, write_directory_file_entry, fp); if (ferror (fp)) @@ -458,10 +461,9 @@ write_directory_file (void) /* Restoration of incremental dumps. */ /* Examine the directories under directory_name and delete any - files that were not there at the time of the back-up. - FIXME: The function name is obviously a misnomer */ + files that were not there at the time of the back-up. */ void -gnu_restore (char const *directory_name) +purge_directory (char const *directory_name) { char *archive_dir; char *current_dir; @@ -514,13 +516,30 @@ gnu_restore (char const *directory_name) } if (*arc == '\0') { + struct stat st; char *p = new_name (directory_name, cur); + + if (deref_stat (true, p, &st)) + { + stat_diag (p); + WARN((0, 0, _("%s: Not purging directory: unable to stat"), + quotearg_colon (p))); + continue; + } + else if (one_file_system_option && st.st_dev != root_device) + { + WARN((0, 0, + _("%s: directory is on a different device: not purging"), + quotearg_colon (p))); + continue; + } + if (! interactive_option || confirm ("delete", p)) { if (verbose_option) fprintf (stdlis, _("%s: Deleting %s\n"), program_name, quote (p)); - if (! remove_any_file (p, 1)) + if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION)) { int e = errno; ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));