X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=e61eb79739e9a6bd607ee226cbea63cfb4eb6ce4;hb=f6edb92580aa886a2a0189463c19189a050dc62d;hp=564121796d7b2e8023c44580373e44c4f982fb63;hpb=1bcbbcf1ff2c537ffa970dbf82e3843d4ad110e5;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index 5641217..e61eb79 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -84,7 +84,7 @@ dumpdir_create0 (const char *contents, const char *cmask) size_t i, total, ctsize, len; char *p; const char *q; - + for (i = 0, total = 0, ctsize = 1, q = contents; *q; total++, q += len) { len = strlen (q) + 1; @@ -146,7 +146,7 @@ dumpdir_locate (struct dumpdir *dump, const char *name) struct dumpdir_iter { struct dumpdir *dump; /* Dumpdir being iterated */ - int all; /* Iterate over all entries, not only D/N/Y */ + int all; /* Iterate over all entries, not only D/N/Y */ size_t next; /* Index of the next element */ }; @@ -155,7 +155,7 @@ dumpdir_next (struct dumpdir_iter *itr) { size_t cur = itr->next; char *ret = NULL; - + if (itr->all) { ret = itr->dump->contents + cur; @@ -258,7 +258,7 @@ make_directory (const char *name, char *caname) directory->dump = directory->idump = NULL; directory->orig = NULL; directory->flags = false; - if (namelen && ISSLASH (name[namelen - 1])) + if (namelen > 1 && ISSLASH (name[namelen - 1])) namelen--; directory->name = xmalloc (namelen + 1); memcpy (directory->name, name, namelen); @@ -288,27 +288,9 @@ attach_directory (const char *name) dirtail = dir; return dir; } - + static void -replace_prefix (char **pname, const char *samp, size_t slen, - const char *repl, size_t rlen) -{ - char *name = *pname; - size_t nlen = strlen (name); - if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen])) - { - if (rlen > slen) - { - name = xrealloc (name, nlen - slen + rlen + 1); - *pname = name; - } - memmove (name + rlen, name + slen, nlen - slen + 1); - memcpy (name, repl, rlen); - } -} - -void dirlist_replace_prefix (const char *pref, const char *repl) { struct directory *dp; @@ -389,28 +371,15 @@ remove_directory (const char *caname) } #endif -/* Find a directory entry for NAME. If first OLD_PREFIX_LEN - bytes of its name match OLD_PREFIX, replace them with - NEW_PREFIX. */ +/* If first OLD_PREFIX_LEN bytes of DIR->NAME name match OLD_PREFIX, + replace them with NEW_PREFIX. */ void -rebase_directory (const char *name, size_t old_prefix_len, - const char *old_prefix, - const char *new_prefix) +rebase_directory (struct directory *dir, + const char *old_prefix, size_t old_prefix_len, + const char *new_prefix, size_t new_prefix_len) { - struct directory *dir = find_directory (name); - if (dir) - { - size_t len = strlen (dir->name); - if (len > old_prefix_len - && memcmp (dir->name, old_prefix, old_prefix_len) == 0) - { - char *newp = xmalloc (len - old_prefix_len + strlen (new_prefix)); - strcpy (newp, new_prefix); - strcat (newp, dir->name + old_prefix_len); - free (dir->name); - dir->name = newp; - } - } + replace_prefix (&dir->name, old_prefix, old_prefix_len, + new_prefix, new_prefix_len); } /* Return a directory entry for a given combination of device and inode @@ -444,7 +413,11 @@ update_parent_directory (const char *name) { struct stat st; if (deref_stat (dereference_option, p, &st) != 0) - stat_diag (name); + { + if (errno != ENOENT) + stat_diag (directory->name); + /* else: should have been already reported */ + } else directory->mtime = get_stat_mtime (&st); } @@ -484,14 +457,14 @@ procdir (const char *name_buffer, struct stat *stat_data, *entry = 'N'; return directory; } - + /* With NFS, the same file can have two different devices if an NFS directory is mounted in multiple locations, which is relatively common when automounting. To avoid spurious incremental redumping of directories, consider all NFS devices as equal, relying on the i-node to establish differences. */ - + if (! ((!check_device_option || (DIR_IS_NFS (directory) && nfs) || directory->device_number == stat_data->st_dev) @@ -529,14 +502,14 @@ procdir (const char *name_buffer, struct stat *stat_data, } else directory->children = CHANGED_CHILDREN; - + DIR_SET_FLAG (directory, DIRF_FOUND); } else { struct directory *d = find_directory_meta (stat_data->st_dev, stat_data->st_ino); - + directory = note_directory (name_buffer, get_stat_mtime(stat_data), stat_data->st_dev, @@ -580,6 +553,12 @@ procdir (const char *name_buffer, struct stat *stat_data, 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)) + /* FIXME: + WARNOPT (WARN_XDEV, + (0, 0, + _("%s: directory is on a different filesystem; not dumped"), + quotearg_colon (directory->name))); + */ directory->children = NO_CHILDREN; else if (flag & PD_FORCE_CHILDREN) { @@ -587,7 +566,7 @@ procdir (const char *name_buffer, struct stat *stat_data, if (directory->children == NO_CHILDREN) *entry = 'N'; } - + DIR_SET_FLAG (directory, DIRF_INIT); if (directory->children != NO_CHILDREN) @@ -611,13 +590,13 @@ procdir (const char *name_buffer, struct stat *stat_data, _("contents not dumped")); directory->children = NO_CHILDREN; break; - + case exclusion_tag_under: exclusion_tag_warning (name_buffer, tag_file_name, _("contents not dumped")); directory->tagfile = tag_file_name; break; - + case exclusion_tag_none: break; } @@ -637,7 +616,7 @@ procdir (const char *name_buffer, struct stat *stat_data, DIRECTORY->dump is replaced with the created template. Each entry is prefixed with ' ' if it was present in DUMP and with 'Y' otherwise. */ -void +static void makedumpdir (struct directory *directory, const char *dir) { size_t i, @@ -706,53 +685,44 @@ makedumpdir (struct directory *directory, const char *dir) /* 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. */ -const char * + command line. + Unless *PDIR is NULL, store there a pointer to the struct directory + describing DIR. */ +struct directory * scan_directory (char *dir, dev_t device, bool cmdline) { char *dirp = savedir (dir); /* for scanning directory */ - char *name_buffer; /* directory, `/', and directory member */ - size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */ - size_t name_length; /* used length in name_buffer */ + namebuf_t nbuf; + char *tmp; struct stat stat_data; struct directory *directory; char ch; - + if (! dirp) savedir_error (dir); - name_buffer_size = strlen (dir) + NAME_FIELD_SIZE; - name_buffer = xmalloc (name_buffer_size + 2); - strcpy (name_buffer, dir); - zap_slashes (name_buffer); - - if (deref_stat (dereference_option, name_buffer, &stat_data)) + tmp = xstrdup (dir); + zap_slashes (tmp); + + if (deref_stat (dereference_option, tmp, &stat_data)) { - stat_diag (name_buffer); - /* FIXME: used to be - children = CHANGED_CHILDREN; - but changed to: */ - free (name_buffer); + dir_removed_diag (tmp, cmdline, stat_diag); + free (tmp); free (dirp); return NULL; } - directory = procdir (name_buffer, &stat_data, device, + directory = procdir (tmp, &stat_data, device, (cmdline ? PD_FORCE_INIT : 0), &ch); - - name_length = strlen (name_buffer); - if (! ISSLASH (name_buffer[name_length - 1])) - { - name_buffer[name_length] = DIRECTORY_SEPARATOR; - /* name_buffer has been allocated an extra slot */ - name_buffer[++name_length] = 0; - } + + free (tmp); + + nbuf = namebuf_create (dir); if (dirp && directory->children != NO_CHILDREN) { char *entry; /* directory entry being scanned */ - size_t entrylen; /* length of directory entry */ dumpdir_iter_t itr; makedumpdir (directory, dirp); @@ -761,25 +731,17 @@ scan_directory (char *dir, dev_t device, bool cmdline) entry; entry = dumpdir_next (itr)) { - entrylen = strlen (entry); - if (name_buffer_size <= entrylen - 1 + name_length) - { - do - name_buffer_size += NAME_FIELD_SIZE; - while (name_buffer_size <= entrylen - 1 + name_length); - name_buffer = xrealloc (name_buffer, name_buffer_size + 2); - } - strcpy (name_buffer + name_length, entry + 1); + char *full_name = namebuf_name (nbuf, entry + 1); if (*entry == 'I') /* Ignored entry */ *entry = 'N'; - else if (excluded_name (name_buffer)) + else if (excluded_name (full_name)) *entry = 'N'; else { - if (deref_stat (dereference_option, name_buffer, &stat_data)) + if (deref_stat (dereference_option, full_name, &stat_data)) { - stat_diag (name_buffer); + file_removed_diag (full_name, false, stat_diag); *entry = 'N'; continue; } @@ -792,7 +754,7 @@ 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 (name_buffer, &stat_data, device, pd_flag, entry); + procdir (full_name, &stat_data, device, pd_flag, entry); } else if (one_file_system_option && device != stat_data.st_dev) @@ -814,24 +776,42 @@ scan_directory (char *dir, dev_t device, bool cmdline) free (itr); } - free (name_buffer); + namebuf_free (nbuf); + if (dirp) free (dirp); - return directory->dump ? directory->dump->contents : NULL; + return directory; +} + +/* Return pointer to the contents of the directory DIR */ +const char * +directory_contents (struct directory *dir) +{ + if (!dir) + return NULL; + return dir->dump ? dir->dump->contents : NULL; } +/* A "safe" version of directory_contents, which never returns NULL. */ const char * -get_directory_contents (char *dir, dev_t device, bool force) +safe_directory_contents (struct directory *dir) { - return scan_directory (dir, device, force); + const char *ret = directory_contents (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 *from, char *to) +obstack_code_rename (struct obstack *stk, char const *from, char const *to) { - char *s; + char const *s; s = from[0] == 0 ? from : safer_name_suffix (from, false, absolute_names_option); @@ -887,17 +867,19 @@ store_rename (struct directory *dir, struct obstack *stk) } } -const char * -append_incremental_renames (const char *dump) +void +append_incremental_renames (struct directory *dir) { struct obstack stk; size_t size; struct directory *dp; - + const char *dump; + if (dirhead == NULL) - return dump; + return; obstack_init (&stk); + dump = directory_contents (dir); if (dump) { size = dumpdir_size (dump) - 1; @@ -912,11 +894,10 @@ append_incremental_renames (const char *dump) if (obstack_object_size (&stk) != size) { obstack_1grow (&stk, 0); - dump = obstack_finish (&stk); + dumpdir_free (dir->dump); + dir->dump = dumpdir_create (obstack_finish (&stk)); } - else - obstack_free (&stk, NULL); - return dump; + obstack_free (&stk, NULL); } @@ -941,8 +922,8 @@ read_incr_db_01 (int version, const char *initbuf) uintmax_t u; time_t sec; long int nsec; - char *buf = 0; - size_t bufsize; + char *buf = NULL; + size_t bufsize = 0; char *ebuf; long lineno = 1; @@ -1236,7 +1217,7 @@ read_timespec (FILE *fp, struct timespec *pval) /* Read incremental snapshot format 2 */ static void -read_incr_db_2 () +read_incr_db_2 (void) { uintmax_t u; struct obstack stk; @@ -1301,8 +1282,8 @@ void read_directory_file (void) { int fd; - char *buf = 0; - size_t bufsize; + char *buf = NULL; + size_t bufsize = 0; int flags = O_RDWR | O_CREAT; if (incremental_level == 0) @@ -1325,6 +1306,13 @@ read_directory_file (void) return; } + /* Consume the first name from the name list and reset the + list afterwards. This is done to change to the new + directory, if the first name is a chdir request (-C dir), + which is necessary to recreate absolute file names. */ + name_from_list (); + blank_name_list (); + if (0 < getline (&buf, &bufsize, listed_incremental_stream)) { char *ebuf; @@ -1379,7 +1367,7 @@ write_directory_file_entry (void *entry, void *data) if (DIR_IS_FOUND (directory)) { char buf[UINTMAX_STRSIZE_BOUND]; - char *s; + char const *s; s = DIR_IS_NFS (directory) ? "1" : "0"; fwrite (s, 2, 1, fp); @@ -1422,7 +1410,7 @@ write_directory_file (void) if (! fp) return; - if (fseek (fp, 0L, SEEK_SET) != 0) + if (fseeko (fp, 0L, SEEK_SET) != 0) seek_error (listed_incremental_option); if (sys_truncate (fileno (fp)) != 0) truncate_error (listed_incremental_option); @@ -1719,7 +1707,7 @@ try_purge_directory (char const *directory_name) } free (p); dumpdir_free (dump); - + free (current_dir); return true; }