+static void
+add_hierarchy_to_namelist (struct name *name, off_t dirsize, dev_t device)
+{
+ char *path = name->name;
+ char *buffer = get_directory_contents (path, dirsize, device);
+
+ if (! buffer)
+ name->dir_contents = "\0\0\0\0";
+ else
+ {
+ size_t name_length = name->length;
+ size_t allocated_length = (name_length >= NAME_FIELD_SIZE
+ ? name_length + NAME_FIELD_SIZE
+ : NAME_FIELD_SIZE);
+ char *name_buffer = xmalloc (allocated_length + 1);
+ /* FIXME: + 2 above? */
+ char *string;
+ size_t string_length;
+ int change_dir = name->change_dir;
+
+ name->dir_contents = buffer;
+ strcpy (name_buffer, path);
+ if (name_buffer[name_length - 1] != '/')
+ {
+ name_buffer[name_length++] = '/';
+ name_buffer[name_length] = '\0';
+ }
+
+ for (string = buffer; *string; string += string_length + 1)
+ {
+ string_length = strlen (string);
+ if (*string == 'D')
+ {
+ if (name_length + string_length >= allocated_length)
+ {
+ while (name_length + string_length >= allocated_length)
+ allocated_length += NAME_FIELD_SIZE;
+ name_buffer = xrealloc (name_buffer, allocated_length + 1);
+ }
+ strcpy (name_buffer + name_length, string + 1);
+ add_hierarchy_to_namelist (addname (name_buffer, change_dir),
+ -1, device);
+ }
+ }
+
+ free (name_buffer);
+ }
+}
+\f
+/* Collect all the names from argv[] (or whatever), expand them into a
+ directory tree, and sort them. This gets only subdirectories, not
+ all files. */
+
+void
+collect_and_sort_names (void)
+{
+ struct name *name;
+ struct name *next_name;
+ int num_names;
+ struct stat statbuf;
+
+ name_gather ();
+
+ if (listed_incremental_option)
+ read_directory_file ();
+
+ if (!namelist)
+ addname (".", 0);
+
+ for (name = namelist; name; name = next_name)
+ {
+ next_name = name->next;
+ if (name->found || name->dir_contents)
+ continue;
+ if (name->regexp) /* FIXME: just skip regexps for now */
+ continue;
+ chdir_do (name->change_dir);
+ if (name->fake)
+ continue;
+
+ if (deref_stat (dereference_option, name->name, &statbuf) != 0)
+ {
+ stat_error (name->name);
+ continue;
+ }
+ if (S_ISDIR (statbuf.st_mode))
+ {
+ name->found = 1;
+ add_hierarchy_to_namelist (name, statbuf.st_size, statbuf.st_dev);
+ }
+ }
+
+ num_names = 0;
+ for (name = namelist; name; name = name->next)
+ num_names++;
+ namelist = merge_sort (namelist, num_names, compare_names);
+
+ for (name = namelist; name; name = name->next)
+ name->found = 0;
+}
+
+/* This is like name_match, except that it returns a pointer to the
+ name it matched, and doesn't set FOUND in structure. The caller
+ will have to do that if it wants to. Oh, and if the namelist is
+ empty, it returns null, unlike name_match, which returns TRUE. */