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}


Reply via email to