From: Sergey Poznyakoff Date: Tue, 24 Sep 2013 11:01:13 +0000 (+0300) Subject: Fix normalize_filename. X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Ftar;a=commitdiff_plain;h=e3d28d84bda24a45c239b398e7b42ccd9be2d0c2 Fix normalize_filename. The function did not take into account eventual -C options, which in particular led to various problems when using -C and --remove-files together. * src/common.h (namebuf_add_dir,namebuf_finish) (tar_getcwd): New prototypes. * src/misc.c (namebuf_add_dir,namebuf_finish) (tar_getcwd): New functions. (normalize_filename): Use tar_getcwd. --- diff --git a/src/common.h b/src/common.h index e65e647..ac96f26 100644 --- a/src/common.h +++ b/src/common.h @@ -605,6 +605,10 @@ typedef struct namebuf *namebuf_t; namebuf_t namebuf_create (const char *dir); void namebuf_free (namebuf_t buf); char *namebuf_name (namebuf_t buf, const char *name); +void namebuf_add_dir (namebuf_t buf, const char *name); +char *namebuf_finish (namebuf_t buf); + +char *tar_getcwd (void); /* Represent N using a signed integer I such that (uintmax_t) I == N. With a good optimizing compiler, this is equivalent to (intmax_t) i diff --git a/src/misc.c b/src/misc.c index d68d806..b8ef6ea 100644 --- a/src/misc.c +++ b/src/misc.c @@ -283,7 +283,7 @@ normalize_filename (const char *name) getcwd is slow, it might fail, and it does not necessarily return a canonical name even when it succeeds. Perhaps we can use dev+ino pairs instead of names? */ - copy = xgetcwd (); + copy = tar_getcwd (); if (copy) { size_t copylen = strlen (copy); @@ -976,6 +976,21 @@ chdir_do (int i) } } +char * +tar_getcwd (void) +{ + static char *cwd; + namebuf_t nbuf; + int i; + + if (!cwd) + cwd = xgetcwd (); + nbuf = namebuf_create (cwd); + for (i = 1; i <= chdir_current; i++) + namebuf_add_dir (nbuf, wd[i].name); + return namebuf_finish (nbuf); +} + void close_diag (char const *name) { @@ -1145,6 +1160,30 @@ namebuf_name (namebuf_t buf, const char *name) return buf->buffer; } +void +namebuf_add_dir (namebuf_t buf, const char *name) +{ + static char dirsep[] = { DIRECTORY_SEPARATOR, 0 }; + if (!ISSLASH (buf->buffer[buf->dir_length - 1])) + { + namebuf_name (buf, dirsep); + buf->dir_length++; + } + namebuf_name (buf, name); + buf->dir_length += strlen (name); +} + +char * +namebuf_finish (namebuf_t buf) +{ + char *res = buf->buffer; + + if (ISSLASH (buf->buffer[buf->dir_length - 1])) + buf->buffer[buf->dir_length] = 0; + free (buf); + return res; +} + /* Return the filenames in directory NAME, relative to the chdir_fd. If the directory does not exist, report error if MUST_EXIST is true.