/*
* load_directory()
*
- * Returns count of files that meet the selection criteria coded in
- * the function pointed to by selector. Creates an array of pointers
- * to dirent structures. Address of array returned in namelist.
+ * Read all the file names in the specified directory, and return them as
+ * an array of "struct dirent" pointers. The array address is returned in
+ * *namelist, and the function result is the count of file names.
*
- * Note that the number of dirent structures needed is dynamically
- * allocated using realloc. Realloc can be inefficient if invoked a
- * large number of times.
+ * To free the result data, free each namelist array member, then free the
+ * namelist array itself.
*/
int
load_directory(const char *dirname, struct dirent *** namelist)
DIR *dirdesc;
struct dirent *direntry;
int count = 0;
- int name_num = 0;
+ int allocsize = 64;
size_t entrysize;
- if ((dirdesc = opendir(dirname)) == NULL)
- pg_log(PG_FATAL, "could not open directory \"%s\": %s\n", dirname, getErrorText(errno));
+ *namelist = (struct dirent **)
+ pg_malloc(allocsize * sizeof(struct dirent *));
- *namelist = NULL;
+ if ((dirdesc = opendir(dirname)) == NULL)
+ pg_log(PG_FATAL, "could not open directory \"%s\": %s\n",
+ dirname, getErrorText(errno));
- while ((direntry = readdir(dirdesc)) != NULL)
+ while (errno = 0, (direntry = readdir(dirdesc)) != NULL)
{
- count++;
-
- *namelist = (struct dirent **) realloc((void *) (*namelist),
- (size_t) ((name_num + 1) * sizeof(struct dirent *)));
-
- if (*namelist == NULL)
+ if (count >= allocsize)
{
- closedir(dirdesc);
- return -1;
+ allocsize *= 2;
+ *namelist = (struct dirent **)
+ pg_realloc(*namelist, allocsize * sizeof(struct dirent *));
}
- entrysize = sizeof(struct dirent) - sizeof(direntry->d_name) +
+ entrysize = offsetof(struct dirent, d_name) +
strlen(direntry->d_name) + 1;
- (*namelist)[name_num] = (struct dirent *) malloc(entrysize);
-
- if ((*namelist)[name_num] == NULL)
- {
- closedir(dirdesc);
- return -1;
- }
+ (*namelist)[count] = (struct dirent *) pg_malloc(entrysize);
- memcpy((*namelist)[name_num], direntry, entrysize);
+ memcpy((*namelist)[count], direntry, entrysize);
- name_num++;
+ count++;
}
+#ifdef WIN32
+ /*
+ * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
+ * released version
+ */
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ errno = 0;
+#endif
+
+ if (errno)
+ pg_log(PG_FATAL, "could not read directory \"%s\": %s\n",
+ dirname, getErrorText(errno));
+
closedir(dirdesc);
return count;