/* Return a freshly allocated string containing the filenames in directory DIR, separated by '\0' characters; the end is marked by two '\0' characters in a row. NAME_SIZE is the number of bytes to initially allocate for the string; it will be enlarged as needed. Return NULL if DIR cannot be opened or if out of memory. */ char * savedir (const char *dir, off_t name_size, struct exclude *included_patterns, struct exclude *excluded_patterns) { DIR *dirp; struct dirent *dp; char *name_space; char *namep; dirp = opendir (dir); if (dirp == NULL) return NULL; /* Be sure name_size is at least `1' so there's room for the final NUL byte. */ if (name_size <= 0) name_size = 1; name_space = (char *) malloc (name_size); if (name_space == NULL) { closedir (dirp); return NULL; } namep = name_space; while ((dp = readdir (dirp)) != NULL) { /* Skip "." and ".." (some NFS filesystems' directories lack them). */ if (dp->d_name[0] != '.' || (dp->d_name[1] != '\0' && (dp->d_name[1] != '.' || dp->d_name[2] != '\0'))) { off_t size_needed = (namep - name_space) + NAMLEN (dp) + 2; if ((included_patterns || excluded_patterns) && !isdir1 (dir, dp->d_name)) { if (included_patterns && !excluded_filename (included_patterns, path, 0)) continue; if (excluded_patterns && excluded_filename (excluded_patterns, path, 0)) continue; } if (size_needed > name_size) { char *new_name_space; while (size_needed > name_size) name_size += 1024; new_name_space = realloc (name_space, name_size); if (new_name_space == NULL) { closedir (dirp); return NULL; } namep += new_name_space - name_space; name_space = new_name_space; } namep = stpcpy (namep, dp->d_name) + 1; } } *namep = '\0'; if (CLOSEDIR (dirp)) { free (name_space); return NULL; } if (path) { free (path); path = NULL; pathlen = 0; } return name_space; }
static bool dir_read (struct file_data const *dir, struct dirdata *dirdata) { register struct dirent *next; register size_t i; /* Address of block containing the files that are described. */ char const **names; /* Number of files in directory. */ size_t nnames; /* Allocated and used storage for file name data. */ char *data; size_t data_alloc, data_used; dirdata->names = 0; dirdata->data = 0; nnames = 0; data = 0; if (dir->desc != -1) { /* Open the directory and check for errors. */ register DIR *reading = opendir (dir->name); if (!reading) return false; /* Initialize the table of filenames. */ data_alloc = 512; data_used = 0; dirdata->data = data = xmalloc (data_alloc); /* Read the directory entries, and insert the subfiles into the `data' table. */ while ((errno = 0, (next = readdir (reading)) != 0)) { char *d_name = next->d_name; size_t d_size = NAMLEN (next) + 1; /* Ignore "." and "..". */ if (d_name[0] == '.' && (d_name[1] == 0 || (d_name[1] == '.' && d_name[2] == 0))) continue; if (excluded_filename (excluded, d_name)) continue; while (data_alloc < data_used + d_size) { if (PTRDIFF_MAX / 2 <= data_alloc) xalloc_die (); dirdata->data = data = xrealloc (data, data_alloc *= 2); } memcpy (data + data_used, d_name, d_size); data_used += d_size; nnames++; } if (errno) { int e = errno; closedir (reading); errno = e; return false; } #if CLOSEDIR_VOID closedir (reading); #else if (closedir (reading) != 0) return false; #endif } /* Create the `names' table from the `data' table. */ if (PTRDIFF_MAX / sizeof *names - 1 <= nnames) xalloc_die (); dirdata->names = names = xmalloc ((nnames + 1) * sizeof *names); dirdata->nnames = nnames; for (i = 0; i < nnames; i++) { names[i] = data; data += strlen (data) + 1; } names[nnames] = 0; return true; }