X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=69cbd59a470687af78ba9623c8e5696853b9fa90;hb=03858cf583ce299b836d8a848967ce290a6bf303;hp=afd19af66ae7e67db457669f3c1e4d1579d345ad;hpb=de328a580ab6f5ff4a3237ce21f1ef0b7dd12984;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index afd19af..69cbd59 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -300,6 +300,24 @@ dirlist_replace_prefix (const char *pref, const char *repl) replace_prefix (&dp->name, pref, pref_len, repl, repl_len); } +void +clear_directory_table (void) +{ + struct directory *dp; + + if (directory_table) + hash_clear (directory_table); + if (directory_meta_table) + hash_clear (directory_meta_table); + for (dp = dirhead; dp; ) + { + struct directory *next = dp->next; + free_directory (dp); + dp = next; + } + dirhead = dirtail = NULL; +} + /* Create and link a new directory entry for directory NAME, having a device number DEV and an inode number INO, with NFS indicating whether it is an NFS device and FOUND indicating whether we have @@ -327,7 +345,8 @@ note_directory (char const *name, struct timespec mtime, if (! ((directory_table || (directory_table = hash_initialize (0, 0, hash_directory_canonical_name, - compare_directory_canonical_names, 0))) + compare_directory_canonical_names, + 0))) && hash_insert (directory_table, directory))) xalloc_die (); @@ -408,7 +427,7 @@ update_parent_directory (struct tar_stat_info *parent) if (directory) { struct stat st; - if (fstatat (parent->fd, ".", &st, fstatat_flags) != 0) + if (fstat (parent->fd, &st) != 0) stat_diag (directory->name); else directory->mtime = get_stat_mtime (&st); @@ -426,8 +445,6 @@ procdir (const char *name_buffer, struct tar_stat_info *st, { struct directory *directory; struct stat *stat_data = &st->stat; - int fd = st->fd; - dev_t device = st->parent ? st->parent->stat.st_dev : 0; bool nfs = NFS_FILE_STAT (*stat_data); if ((directory = find_directory (name_buffer)) != NULL) @@ -541,11 +558,8 @@ procdir (const char *name_buffer, struct tar_stat_info *st, } } - /* If the directory is on another device and --one-file-system was given, - omit it... */ - if (one_file_system_option && device != stat_data->st_dev - /* ... except if it was explicitely given in the command line */ - && !is_individual_file (name_buffer)) + if (one_file_system_option && st->parent + && stat_data->st_dev != st->parent->stat.st_dev) /* FIXME: WARNOPT (WARN_XDEV, (0, 0, @@ -566,7 +580,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, { const char *tag_file_name; - switch (check_exclusion_tags (fd, &tag_file_name)) + switch (check_exclusion_tags (st, &tag_file_name)) { case exclusion_tag_all: /* This warning can be duplicated by code in dump_file0, but only @@ -680,8 +694,7 @@ struct directory * scan_directory (struct tar_stat_info *st) { char const *dir = st->orig_file_name; - int fd = st->fd; - char *dirp = 0; + char *dirp = get_directory_entries (st); dev_t device = st->stat.st_dev; bool cmdline = ! st->parent; namebuf_t nbuf; @@ -689,18 +702,6 @@ scan_directory (struct tar_stat_info *st) struct directory *directory; char ch; - int dupfd = dup (fd); - if (0 <= dupfd) - { - dirp = fdsavedir (dupfd); - if (! dirp) - { - int e = errno; - close (dupfd); - errno = e; - } - } - if (! dirp) savedir_error (dir); @@ -734,19 +735,29 @@ scan_directory (struct tar_stat_info *st) *entry = 'N'; else { + int fd = st->fd; void (*diag) (char const *) = 0; struct tar_stat_info stsub; tar_stat_init (&stsub); - if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0) + if (fd < 0) + { + errno = - fd; + diag = open_diag; + } + else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0) diag = stat_diag; else if (S_ISDIR (stsub.stat.st_mode)) { - stsub.fd = openat (fd, entry + 1, open_read_flags); - if (stsub.fd < 0) + int subfd = subfile_open (st, entry + 1, open_read_flags); + if (subfd < 0) diag = open_diag; - else if (fstat (stsub.fd, &stsub.stat) != 0) - diag = stat_diag; + else + { + stsub.fd = subfd; + if (fstat (subfd, &stsub.stat) != 0) + diag = stat_diag; + } } if (diag) @@ -762,7 +773,10 @@ scan_directory (struct tar_stat_info *st) else if (directory->children == ALL_CHILDREN) pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; *entry = 'D'; + + stsub.parent = st; procdir (full_name, &stsub, pd_flag, entry); + restore_parent_fd (&stsub); } else if (one_file_system_option && device != stsub.stat.st_dev) *entry = 'N'; @@ -784,8 +798,7 @@ scan_directory (struct tar_stat_info *st) namebuf_free (nbuf); - if (dirp) - free (dirp); + free (dirp); return directory; } @@ -891,7 +904,8 @@ append_incremental_renames (struct directory *dir) for (dp = dirhead; dp; dp = dp->next) store_rename (dp, &stk); - if (obstack_object_size (&stk) != size) + /* FIXME: Is this the right thing to do when DIR is null? */ + if (dir && obstack_object_size (&stk) != size) { obstack_1grow (&stk, 0); dumpdir_free (dir->dump); @@ -1352,8 +1366,7 @@ read_directory_file (void) if (ferror (listed_incremental_stream)) read_error (listed_incremental_option); - if (buf) - free (buf); + free (buf); } /* Output incremental data for the directory ENTRY to the file DATA. @@ -1664,11 +1677,10 @@ try_purge_directory (char const *directory_name) { const char *entry; struct stat st; - if (p) - free (p); + free (p); p = new_name (directory_name, cur); - if (deref_stat (false, p, &st)) + if (deref_stat (p, &st) != 0) { if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed dirs and check it here? */