diff options
| author | Greg Ercolano <erco@seriss.com> | 2020-07-10 21:49:00 -0700 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2020-07-14 12:52:56 +0200 |
| commit | 0693c70f577624e66fd660a888f2d2bcd3fc180b (patch) | |
| tree | e3b4161c0516ebacaf84e9b58852f48d4e4b6357 /src/scandir_posix.c | |
| parent | 9925b0f12852dc37fb7fb773a525486c258d2c62 (diff) | |
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()
Diffstat (limited to 'src/scandir_posix.c')
| -rw-r--r-- | src/scandir_posix.c | 103 |
1 files changed, 53 insertions, 50 deletions
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; } |
