}
\f
-/* Add all the dirs under NAME, which names a directory, to the namelist.
- If any of the files is a directory, recurse on the subdirectory.
- DEVICE is the device not to leave, if the -l option is specified.
- CMDLINE is true, if the NAME appeared on the command line. */
+/* Add all the dirs under ST to the namelist NAME, descending the
+ directory hierarchy recursively. */
static void
-add_hierarchy_to_namelist (struct name *name, dev_t device, bool cmdline)
+add_hierarchy_to_namelist (struct tar_stat_info *st, struct name *name)
{
const char *buffer;
- name_fill_directory (name, device, cmdline);
+ name->directory = scan_directory (st);
buffer = directory_contents (name->directory);
if (buffer)
{
if (*string == 'D')
{
struct name *np;
+ struct tar_stat_info subdir;
+ int subfd;
if (allocated_length <= name_length + string_length)
{
else
child_tail->sibling = np;
child_tail = np;
- add_hierarchy_to_namelist (np, device, false);
+
+ tar_stat_init (&subdir);
+ subdir.parent = st;
+ if (st->fd < 0)
+ {
+ subfd = -1;
+ errno = - st->fd;
+ }
+ else
+ subfd = subfile_open (st, string + 1,
+ open_read_flags | O_DIRECTORY);
+ if (subfd < 0)
+ open_diag (namebuf);
+ else
+ {
+ subdir.fd = subfd;
+ if (fstat (subfd, &subdir.stat) != 0)
+ stat_diag (namebuf);
+ else if (! (O_DIRECTORY || S_ISDIR (subdir.stat.st_mode)))
+ {
+ errno = ENOTDIR;
+ open_diag (namebuf);
+ }
+ else
+ {
+ subdir.orig_file_name = xstrdup (namebuf);
+ add_hierarchy_to_namelist (&subdir, np);
+ restore_parent_fd (&subdir);
+ }
+ }
+
+ tar_stat_destroy (&subdir);
}
}
struct name *name;
struct name *next_name, *prev_name = NULL;
int num_names;
- struct stat statbuf;
Hash_table *nametab;
name_gather ();
num_names = 0;
for (name = namelist; name; name = name->next, num_names++)
{
+ struct tar_stat_info st;
+
if (name->found_count || name->directory)
continue;
if (name->matching_flags & EXCLUDE_WILDCARDS)
if (name->name[0] == 0)
continue;
- if (deref_stat (dereference_option, name->name, &statbuf) != 0)
+ tar_stat_init (&st);
+
+ if (deref_stat (dereference_option, name->name, &st.stat) != 0)
{
stat_diag (name->name);
continue;
}
- if (S_ISDIR (statbuf.st_mode))
+ if (S_ISDIR (st.stat.st_mode))
{
- name->found_count++;
- add_hierarchy_to_namelist (name, statbuf.st_dev, true);
+ int dir_fd = openat (chdir_fd, name->name,
+ open_read_flags | O_DIRECTORY);
+ if (dir_fd < 0)
+ open_diag (name->name);
+ else
+ {
+ st.fd = dir_fd;
+ if (fstat (dir_fd, &st.stat) != 0)
+ stat_diag (name->name);
+ else if (O_DIRECTORY || S_ISDIR (st.stat.st_mode))
+ {
+ st.orig_file_name = xstrdup (name->name);
+ name->found_count++;
+ add_hierarchy_to_namelist (&st, name);
+ }
+ }
}
+
+ tar_stat_destroy (&st);
}
namelist = merge_sort (namelist, num_names, compare_names);