X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=628ff296dc13036c7d22f3271a19b700ca1c1991;hb=777042e024d4bf7357ffd060ad05763d463fe441;hp=e61eb79739e9a6bd607ee226cbea63cfb4eb6ce4;hpb=f6edb92580aa886a2a0189463c19189a050dc62d;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index e61eb79..628ff29 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -43,7 +43,7 @@ enum children #define DIR_IS_INITED(d) ((d)->flags & DIRF_INIT) #define DIR_IS_NFS(d) ((d)->flags & DIRF_NFS) #define DIR_IS_FOUND(d) ((d)->flags & DIRF_FOUND) -#define DIR_IS_NEW(d) ((d)->flags & DIRF_NEW) +/* #define DIR_IS_NEW(d) ((d)->flags & DIRF_NEW) FIXME: not used */ #define DIR_IS_RENAMED(d) ((d)->flags & DIRF_RENAMED) #define DIR_SET_FLAG(d,f) (d)->flags |= (f) @@ -77,7 +77,7 @@ struct directory char *name; /* file name of directory */ }; -struct dumpdir * +static struct dumpdir * dumpdir_create0 (const char *contents, const char *cmask) { struct dumpdir *dump; @@ -108,13 +108,13 @@ dumpdir_create0 (const char *contents, const char *cmask) return dump; } -struct dumpdir * +static struct dumpdir * dumpdir_create (const char *contents) { return dumpdir_create0 (contents, "YND"); } -void +static void dumpdir_free (struct dumpdir *dump) { free (dump->elv); @@ -131,7 +131,7 @@ compare_dirnames (const void *first, const void *second) /* Locate NAME in the dumpdir array DUMP. Return pointer to the slot in DUMP->contents, or NULL if not found */ -char * +static char * dumpdir_locate (struct dumpdir *dump, const char *name) { char **ptr; @@ -150,7 +150,7 @@ struct dumpdir_iter size_t next; /* Index of the next element */ }; -char * +static char * dumpdir_next (struct dumpdir_iter *itr) { size_t cur = itr->next; @@ -172,7 +172,7 @@ dumpdir_next (struct dumpdir_iter *itr) return ret; } -char * +static char * dumpdir_first (struct dumpdir *dump, int all, struct dumpdir_iter **pitr) { struct dumpdir_iter *itr = xmalloc (sizeof (*itr)); @@ -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 (fstat (parent->fd, &st) != 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); @@ -723,7 +704,7 @@ scan_directory (char *dir, dev_t device, bool cmdline) if (dirp && directory->children != NO_CHILDREN) { char *entry; /* directory entry being scanned */ - dumpdir_iter_t itr; + struct dumpdir_iter *itr; makedumpdir (directory, dirp); @@ -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) @@ -891,7 +890,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); @@ -1386,7 +1386,7 @@ write_directory_file_entry (void *entry, void *data) if (directory->dump) { const char *p; - dumpdir_iter_t itr; + struct dumpdir_iter *itr; for (p = dumpdir_first (directory->dump, 0, &itr); p; @@ -1452,7 +1452,7 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info) to = archive_dir; set_next_block_after (current_header); - mv_begin (stat_info); + mv_begin_read (stat_info); for (; size > 0; size -= copied) { @@ -1668,7 +1668,7 @@ try_purge_directory (char const *directory_name) 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? */