From 0693c70f577624e66fd660a888f2d2bcd3fc180b Mon Sep 17 00:00:00 2001 From: Greg Ercolano Date: Fri, 10 Jul 2020 21:49:00 -0700 Subject: First pass at fixing issue 99 A lot of code touched because low level functions needed to pass up error messages reliably, and this had to propagate up the entire driver hierarchy. Tested OK *in English* on: > Linux > OSX 10.10.x > Windows VS2017 > Windows mingw64 I have no way to test on Android, but it might work. TODO: Needs testing in other languages to verify proper UTF8 error messages, esp. with Windows VS, due to complexities with FormatMessage() -- see get_ms_errmsg() --- src/scandir_posix.c | 103 +++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 50 deletions(-) (limited to 'src/scandir_posix.c') diff --git a/src/scandir_posix.c b/src/scandir_posix.c index cf58c4195..b311c72e1 100644 --- a/src/scandir_posix.c +++ b/src/scandir_posix.c @@ -128,11 +128,16 @@ readentry(DIR *dirp, struct dirent **entryp, size_t *len) } -/* ========================================================================== */ +/* + * This could use some docs. + * + * Returns -1 on error, errmsg returns error string (if non-NULL) + */ int fl_scandir(const char *dir, struct dirent ***namelist, int (*sel)(struct dirent *), - int (*compar)(struct dirent **, struct dirent **)) + int (*compar)(struct dirent **, struct dirent **), + char *errmsg, int errmsg_sz) { { int result = -1; DIR *dirp; @@ -140,64 +145,62 @@ fl_scandir(const char *dir, struct dirent ***namelist, struct dirent *entryp, **entries, **p; entries = (struct dirent **) malloc(sizeof(*entries) * max); - if (NULL != entries) + if (NULL == entries) { + if (errmsg) fl_snprintf(errmsg, errmsg_sz, "out of memory"); + return -1; + } + + /* Open directory 'dir' (and verify that it really is a directory) */ + dirp = opendir(dir); + if (NULL == dirp) { + if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno)); + return -1; + } + + /* Read next directory entry */ + while (!readentry(dirp, &entryp, &len)) { - /* Open directory 'dir' (and verify that it really is a directory) */ - dirp = opendir(dir); - if (NULL != dirp) + if (NULL == entryp) { - /* Read next directory entry */ - while (!readentry(dirp, &entryp, &len)) - { - if (NULL == entryp) - { - /* EOD => Return number of directory entries */ - result = (int) num; - break; - } - /* Apply select function if there is one provided */ - if (NULL != sel) { if (!sel(entryp)) continue; } - entries[num++] = entryp; - if (num >= max) - { - /* Allocate exponentially increasing sized memory chunks */ - if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; } - else - { - errno = ENOMEM; - break; - } - p = (struct dirent **) realloc((void *) entries, - sizeof(*entries) * max); - if (NULL != p) { entries = p; } - else break; - } - } - closedir(dirp); - /* - * A standard compliant 'closedir()' is allowed to fail with 'EINTR', - * but the state of the directory structure is undefined in this case. - * Therefore we ignore the return value because we can't call 'closedir()' - * again and must hope that the system has released all resources. - */ + /* EOD => Return number of directory entries */ + result = (int) num; + break; } - /* Sort entries in array if there is a compare function provided */ - if (NULL != compar) - { - qsort((void *) entries, num, sizeof(*entries), - (int (*)(const void *, const void *)) compar); + /* Apply select function if there is one provided */ + if (NULL != sel) { if (!sel(entryp)) continue; } + entries[num++] = entryp; + if (num >= max) { + /* Allocate exponentially increasing sized memory chunks */ + if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; } + else { + errno = ENOMEM; + break; + } + p = (struct dirent **) realloc((void *)entries, sizeof(*entries)*max); + if (NULL != p) { entries = p; } + else break; } - *namelist = entries; } - + closedir(dirp); + /* + * A standard compliant 'closedir()' is allowed to fail with 'EINTR', + * but the state of the directory structure is undefined in this case. + * Therefore we ignore the return value because we can't call 'closedir()' + * again and must hope that the system has released all resources. + */ + + /* Sort entries in array if there is a compare function provided */ + if (NULL != compar) { + qsort((void *) entries, num, sizeof(*entries), + (int (*)(const void *, const void *)) compar); + } + *namelist = entries; /* Check for error */ - if (-1 == result) - { + if (-1 == result) { /* Free all memory we have allocated */ while (num--) { free(entries[num]); } free(entries); } - return result; } -- cgit v1.2.3