From: Sergey Poznyakoff Date: Tue, 1 Oct 2013 18:48:30 +0000 (+0300) Subject: Revamp tar_getcwd/normalize_filename stuff. X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Ftar;a=commitdiff_plain;h=d28eee6b4f16d0fb847ee57771a42062259405b8 Revamp tar_getcwd/normalize_filename stuff. The changes are based on the discussion with Nathan. * src/common.h (normalize_filename): Take two arguments. All callers updated. (tar_getcwd): Replaced with .. (tar_getcdpath): New proto. * src/misc.c (normalize_filename): Take two arguments. (chdir_arg): Populate cwd along with creating the structure. (tar_getcwd): Removed. (tar_getcdpath): New function. * tests/incr09.at: New test case. * tests/Makefile.am: Add new tests. * tests/testsuite.at: Likewise. --- diff --git a/src/common.h b/src/common.h index c2cad54..eb801bb 100644 --- a/src/common.h +++ b/src/common.h @@ -596,7 +596,7 @@ void skip_member (void); void assign_string (char **dest, const char *src); int unquote_string (char *str); char *zap_slashes (char *name); -char *normalize_filename (const char *name); +char *normalize_filename (int cdidx, const char *name); void normalize_filename_x (char *name); void replace_prefix (char **pname, const char *samp, size_t slen, const char *repl, size_t rlen); @@ -609,7 +609,7 @@ 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); -const char *tar_getcwd (void); +const char *tar_getcdpath (int); const char *tar_dirname (void); /* Represent N using a signed integer I such that (uintmax_t) I == N. diff --git a/src/incremen.c b/src/incremen.c index 07e757a..f6b311e 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -280,7 +280,7 @@ free_directory (struct directory *dir) static struct directory * attach_directory (const char *name) { - char *cname = normalize_filename (name); + char *cname = normalize_filename (chdir_current, name); struct directory *dir = make_directory (name, cname); if (dirtail) dirtail->next = dir; @@ -370,7 +370,7 @@ find_directory (const char *name) return 0; else { - char *caname = normalize_filename (name); + char *caname = normalize_filename (chdir_current, name); struct directory *dir = make_directory (name, caname); struct directory *ret = hash_lookup (directory_table, dir); free_directory (dir); diff --git a/src/misc.c b/src/misc.c index 343d5f9..5264952 100644 --- a/src/misc.c +++ b/src/misc.c @@ -273,7 +273,7 @@ normalize_filename_x (char *file_name) Return a normalized newly-allocated copy. */ char * -normalize_filename (const char *name) +normalize_filename (int cdidx, const char *name) { char *copy = NULL; @@ -285,7 +285,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? */ - const char *cwd = tar_getcwd (); + const char *cwd = tar_getcdpath (cdidx); size_t copylen; bool need_separator; @@ -888,7 +888,7 @@ chdir_arg (char const *dir) if (! wd_count) { wd[wd_count].name = "."; - wd[wd_count].cwd = NULL; + wd[wd_count].cwd = xgetcwd (); wd[wd_count].fd = AT_FDCWD; wd_count++; } @@ -906,7 +906,14 @@ chdir_arg (char const *dir) } wd[wd_count].name = dir; - wd[wd_count].cwd = NULL; + if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name)) + wd[wd_count].cwd = xstrdup (wd[wd_count].name); + else + { + namebuf_t nbuf = namebuf_create (wd[wd_count - 1].cwd); + namebuf_add_dir (nbuf, wd[wd_count].name); + wd[wd_count].cwd = namebuf_finish (nbuf); + } wd[wd_count].fd = 0; return wd_count++; } @@ -987,37 +994,16 @@ tar_dirname (void) } const char * -tar_getcwd (void) +tar_getcdpath (int idx) { - static char *cwd; - namebuf_t nbuf; - int i; - - if (!cwd) - cwd = xgetcwd (); if (!wd) - return cwd; - - if (0 == chdir_current || !wd[chdir_current].cwd) { - if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name)) - { - wd[chdir_current].cwd = xstrdup (wd[chdir_current].name); - return wd[chdir_current].cwd; - } - if (!wd[0].cwd) - wd[0].cwd = cwd; - - for (i = chdir_current - 1; i > 0; i--) - if (wd[i].cwd) - break; - - nbuf = namebuf_create (wd[i].cwd); - for (i++; i <= chdir_current; i++) - namebuf_add_dir (nbuf, wd[i].name); - wd[chdir_current].cwd = namebuf_finish (nbuf); + static char *cwd; + if (!cwd) + cwd = xgetcwd (); + return cwd; } - return wd[chdir_current].cwd; + return wd[idx].cwd; } void diff --git a/src/names.c b/src/names.c index 8b32de1..32403b3 100644 --- a/src/names.c +++ b/src/names.c @@ -1238,13 +1238,11 @@ collect_and_sort_names (void) namelist = merge_sort (namelist, num_names, compare_names); num_names = 0; - nametab = hash_initialize (0, 0, - name_hash, - name_compare, NULL); + nametab = hash_initialize (0, 0, name_hash, name_compare, NULL); for (name = namelist; name; name = next_name) { next_name = name->next; - name->caname = normalize_filename (name->name); + name->caname = normalize_filename (name->change_dir, name->name); if (prev_name) { struct name *p = hash_lookup (nametab, name); diff --git a/tests/Makefile.am b/tests/Makefile.am index f40c664..940c94f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -113,6 +113,7 @@ TESTSUITE_AT = \ incr06.at\ incr07.at\ incr08.at\ + incr09.at\ indexfile.at\ ignfail.at\ label01.at\ diff --git a/tests/incr09.at b/tests/incr09.at new file mode 100644 index 0000000..b6130a6 --- /dev/null +++ b/tests/incr09.at @@ -0,0 +1,59 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- +# Test suite for GNU tar. +# Copyright 2013 Free Software Foundation, Inc. +# +# GNU tar is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +AT_SETUP([incremental with alternating -C]) +AT_KEYWORDS([incremental create incr09]) + +AT_TAR_CHECK([ +AT_SORT_PREREQ +mkdir foo bar middle +echo foo/foo_file > foo/foo_file +echo bar/bar_file > bar/bar_file +echo middle/file > middle/middle_file +decho A +tar -cvf foo.tar --incremental -C foo . -C `pwd` middle -C bar . + +rm foo.tar +>toplevel_file +decho B +tar -cvf foo.tar --incremental -C foo . -C `pwd` toplevel_file -C bar . +], +[0], +[A +./ +./ +middle/ +./bar_file +./foo_file +middle/middle_file +B +./ +./ +toplevel_file +./bar_file +./foo_file +], +[A +tar: .: Directory is new +tar: middle: Directory is new +tar: .: Directory is new +B +tar: .: Directory is new +tar: .: Directory is new +],[],[],[gnu]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index e28513e..7856287 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -298,6 +298,7 @@ m4_include([incr05.at]) m4_include([incr06.at]) m4_include([incr07.at]) m4_include([incr08.at]) +m4_include([incr09.at]) AT_BANNER([Files removed while archiving]) m4_include([filerem01.at])