X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=7cad838a8e6e2d26b1b09e65801a2415a75de547;hb=c3fa22fc8023ad21ad32b13f934c3324756c9236;hp=f5631a142282c7639b8f76affa3e7b6972d11970;hpb=df59690240b9a41d59ebe9e809faffd93f340020;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index f5631a1..7cad838 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -290,24 +290,6 @@ attach_directory (const char *name) } -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) { @@ -389,18 +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) - replace_prefix (&dir->name, old_prefix, old_prefix_len, - new_prefix, strlen (new_prefix)); + 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 @@ -434,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); } @@ -570,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) { @@ -696,14 +685,15 @@ 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; @@ -711,38 +701,28 @@ scan_directory (char *dir, dev_t device, bool cmdline) 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); + tmp = xstrdup (dir); + zap_slashes (tmp); - if (deref_stat (dereference_option, name_buffer, &stat_data)) + 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); @@ -751,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; } @@ -782,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) @@ -804,17 +776,35 @@ 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 * -get_directory_contents (char *dir, dev_t device, bool force) +directory_contents (struct directory *dir) { - return scan_directory (dir, device, force); + if (!dir) + return NULL; + return dir->dump ? dir->dump->contents : NULL; +} + +/* A "safe" version of directory_contents, which never returns NULL. */ +const char * +safe_directory_contents (struct directory *dir) +{ + 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); } @@ -877,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; @@ -902,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); } @@ -931,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; @@ -1291,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) @@ -1315,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;