X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=c6d4f4c5849a2ecdb5e9633a36e718c95e195f93;hb=8da503cad6e883b30c05749149084d24319063b4;hp=96d0e40a3929296edeb5812930d8f538e07dabaa;hpb=fbc54fa3378b6ee5bbf9ad735dce47eee606317c;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index 96d0e40..c6d4f4c 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -402,26 +402,17 @@ find_directory_meta (dev_t dev, ino_t ino) } void -update_parent_directory (const char *name) +update_parent_directory (struct tar_stat_info *parent) { - struct directory *directory; - char *p; - - p = dir_name (name); - directory = find_directory (p); + struct directory *directory = find_directory (parent->orig_file_name); if (directory) { struct stat st; - if (deref_stat (dereference_option, p, &st) != 0) - { - if (errno != ENOENT) - stat_diag (directory->name); - /* else: should have been already reported */ - } + if (fstatat (parent->fd, ".", &st, fstatat_flags) != 0) + stat_diag (directory->name); else directory->mtime = get_stat_mtime (&st); } - free (p); } #define PD_FORCE_CHILDREN 0x10 @@ -429,12 +420,13 @@ update_parent_directory (const char *name) #define PD_CHILDREN(f) ((f) & 3) static struct directory * -procdir (const char *name_buffer, struct stat *stat_data, - dev_t device, +procdir (const char *name_buffer, struct tar_stat_info *st, int flag, char *entry) { struct directory *directory; + struct stat *stat_data = &st->stat; + 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) @@ -573,7 +565,7 @@ procdir (const char *name_buffer, struct stat *stat_data, { const char *tag_file_name; - switch (check_exclusion_tags (name_buffer, &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 @@ -682,19 +674,16 @@ makedumpdir (struct directory *directory, const char *dir) free (array); } -/* Recursively scan the given directory DIR. - DEVICE is the device number where DIR resides (for --one-file-system). - If CMDLINE is true, the directory name was explicitly listed in the - command line. - Unless *PDIR is NULL, store there a pointer to the struct directory - describing DIR. */ +/* Recursively scan the directory identified by ST. */ struct directory * -scan_directory (char *dir, dev_t device, bool cmdline) +scan_directory (struct tar_stat_info *st) { - char *dirp = savedir (dir); /* for scanning directory */ + char const *dir = st->orig_file_name; + char *dirp = get_directory_entries (st); + dev_t device = st->stat.st_dev; + bool cmdline = ! st->parent; namebuf_t nbuf; char *tmp; - struct stat stat_data; struct directory *directory; char ch; @@ -704,15 +693,7 @@ scan_directory (char *dir, dev_t device, bool cmdline) tmp = xstrdup (dir); zap_slashes (tmp); - if (deref_stat (dereference_option, tmp, &stat_data)) - { - dir_removed_diag (tmp, cmdline, stat_diag); - free (tmp); - free (dirp); - return NULL; - } - - directory = procdir (tmp, &stat_data, device, + directory = procdir (tmp, st, (cmdline ? PD_FORCE_INIT : 0), &ch); @@ -739,14 +720,37 @@ scan_directory (char *dir, dev_t device, bool cmdline) *entry = 'N'; else { - if (deref_stat (dereference_option, full_name, &stat_data)) + int fd = st->fd; + void (*diag) (char const *) = 0; + struct tar_stat_info stsub; + tar_stat_init (&stsub); + + if (fd < 0) { - file_removed_diag (full_name, false, stat_diag); - *entry = 'N'; - continue; + 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)) + { + int subfd = subfile_open (st, entry + 1, open_read_flags); + if (subfd < 0) + diag = open_diag; + else + { + stsub.fd = subfd; + if (fstat (subfd, &stsub.stat) != 0) + diag = stat_diag; + } } - if (S_ISDIR (stat_data.st_mode)) + if (diag) + { + file_removed_diag (full_name, false, diag); + *entry = 'N'; + } + else if (S_ISDIR (stsub.stat.st_mode)) { int pd_flag = 0; if (!recursion_option) @@ -754,23 +758,24 @@ scan_directory (char *dir, dev_t device, bool cmdline) else if (directory->children == ALL_CHILDREN) pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; *entry = 'D'; - procdir (full_name, &stat_data, device, pd_flag, entry); - } - else if (one_file_system_option && device != stat_data.st_dev) + 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'; - else if (*entry == 'Y') /* New entry, skip further checks */; - /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */ - - else if (OLDER_STAT_TIME (stat_data, m) + else if (OLDER_STAT_TIME (stsub.stat, m) && (!after_date_option - || OLDER_STAT_TIME (stat_data, c))) + || OLDER_STAT_TIME (stsub.stat, c))) *entry = 'N'; else *entry = 'Y'; + + tar_stat_destroy (&stsub); } } free (itr); @@ -801,12 +806,6 @@ safe_directory_contents (struct directory *dir) return ret ? ret : "\0\0\0\0"; } -void -name_fill_directory (struct name *name, dev_t device, bool cmdline) -{ - name->directory = scan_directory (name->name, device, cmdline); -} - static void obstack_code_rename (struct obstack *stk, char const *from, char const *to)