summaryrefslogtreecommitdiff
path: root/src/scandir_posix.c
diff options
context:
space:
mode:
authorGreg Ercolano <erco@seriss.com>2020-07-10 21:49:00 -0700
committerAlbrecht Schlosser <albrechts.fltk@online.de>2020-07-14 12:52:56 +0200
commit0693c70f577624e66fd660a888f2d2bcd3fc180b (patch)
treee3b4161c0516ebacaf84e9b58852f48d4e4b6357 /src/scandir_posix.c
parent9925b0f12852dc37fb7fb773a525486c258d2c62 (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.c103
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;
}