diff options
Diffstat (limited to 'contrib/pg_upgrade/file.c')
-rw-r--r-- | contrib/pg_upgrade/file.c | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c index 1dd3722142c..962cbaccc53 100644 --- a/contrib/pg_upgrade/file.c +++ b/contrib/pg_upgrade/file.c @@ -224,13 +224,12 @@ copy_file(const char *srcfile, const char *dstfile, bool force) /* * 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) @@ -238,43 +237,48 @@ 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; |