|
From: | Richard Nolde |
Subject: | [Bug-tar] Additional info and possible patch for error in earlier report from Richard Nolde |
Date: | Wed, 09 Feb 2011 18:19:11 -0700 |
User-agent: | Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.15) Gecko/20101027 Fedora/3.0.10-1.fc12 Thunderbird/3.0.10 |
I compiled tar 1.25 locally with optimizations turned off. The problem
seems to be in the all_names_found function where the for loop
incorrectly returns true after the first file within the directory has
been read. I'm not familar with the tar code so I cannot say how it
should work, but I would think that there needs to be some way to track
the fact that the requested item was a directory and this function
should not return true until all the elements in the directory have
been read. I've provided a suggested alternative test that works in my
testing for listing and extracting the directory: eg tar -[tx]v
--strip-components=2 --occurrence=1 -f /tmp/nmon.tar
archive/fedora/nmon. I realize that the ISSLASH macro handles the two
tests, but the slash in the file name may not be at the position tested
in the original code. If the adjusted file name contains a slash at any
point, I'm guessing that the current file is within a subdirectory that
is being extracted. Richard Nolde names.c bool all_names_found (struct tar_stat_info *p) { struct name const *cursor; size_t len; if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash) return false; len = strlen (p->file_name); for (cursor = namelist; cursor; cursor = cursor->next) { if ((cursor->name[0] && !WASFOUND (cursor)) || (len >= cursor->length && ((strchr (p->file_name, '/'))|| (strchr(p->file_name, '\\'))))) /* original code here that does not work || (len >= cursor->length && ISSLASH (p->file_name[cursor->length]))) */ return false; } return true; } for (cursor = namelist; cursor; cursor = cursor->next) { if ((cursor->name[0] && !WASFOUND (cursor)) || (len >= cursor->length && ((strchr (p->file_name, '/')) || (strchr(p->file_name, '\\'))))) /* || (len >= cursor->length && ISSLASH (p->file_name[cursor->length]))) */ return false; } (gdb) p *namelist $18 = {next = 0x0, prev = 0x0, name = 0x808f950 "archive/fedora/nmon", length = 19, matching_flags = 1073741832, cmdline = true, change_dir = 0, found_count = 1, directory = 0x0, parent = 0x0, child = 0x0, sibling = 0x0, caname = 0x0} ... (gdb) p *p $20 = {orig_file_name = 0x8090508 "archive/fedora/nmon/nmon_x86_64_rhel4", file_name = 0x808f968 "nmon/nmon_x86_64_rhel4", had_trailing_slash = false, link_name = 0x808f9c8 "", uname = 0x808f9b8 "nolde",gname = 0x808f9a8 "nolde", stat = {st_dev = 0, __pad1 = 0, __st_ino = 0, st_mode = 438, st_nlink = 0, st_uid = 500, st_gid = 500, st_rdev = 0, __pad2 = 0, st_size = 217828, st_blksize = 0, st_blocks = 0, st_atim = {tv_sec = 0, tv_nsec = 0}, st_mtim = {tv_sec = 0, tv_nsec = 0}, st_ctim = {tv_sec = 0, tv_nsec = 0}, st_ino = 0}, atime = {tv_sec = 1297296281, tv_nsec = 763835143}, mtime = {tv_sec = 1290574642, tv_nsec = 0}, ctime = {tv_sec = 1297296281, tv_nsec = 763835143}, archive_file_size = 217828, is_sparse = false, sparse_major = 0, sparse_minor = 0, sparse_map_avail = 0, sparse_map_size = 0, sparse_map = 0x0, xhdr = {stk = 0x0, size = 0, buffer = 0x0, string_length = 0}, is_dumpdir = false, skipped = false, dumpdir = 0x0, parent = 0x0, dirstream = 0x0, fd = 0} |
[Prev in Thread] | Current Thread | [Next in Thread] |