From 4471166f59499e011477a68c65141adf802d8cf4 Mon Sep 17 00:00:00 2001 From: Greg Ercolano Date: Sat, 11 Jul 2020 14:35:59 -0700 Subject: [PATCH] Extra fool-proofing, and suggested use of strerror_r() strerror_r() sounds like the better thing to use, but if you read the man page carefully, there are pitfalls of competing GNU vs POSIX versions of the same function, with different return values. GNU version returns a pointer to the error string, which may or may not use the error string supplied to use. Makes no sense. Why not use the buffer the user prepared? Makes returning errors hard. One thing GNU does underline is the string is always NUL terminated. POSIX version doesn't return a string at all, it returns an int, making handling the GNU cases impossible. POSIX /doesn't/ say one way or the other about the string being NUL terminated, so you have to make sure when you use it. I trawled the net, seems this is a big annoying issue. For now, leaving the code with strerror(), but we should change it. --- src/scandir_posix.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/scandir_posix.c b/src/scandir_posix.c index b311c72e1..7295d7e7d 100644 --- a/src/scandir_posix.c +++ b/src/scandir_posix.c @@ -144,6 +144,7 @@ fl_scandir(const char *dir, struct dirent ***namelist, size_t len, num = 0, max = ENTRIES_MIN; struct dirent *entryp, **entries, **p; + if (errmsg && errmsg_sz>0) errmsg[0] = '\0'; entries = (struct dirent **) malloc(sizeof(*entries) * max); if (NULL == entries) { if (errmsg) fl_snprintf(errmsg, errmsg_sz, "out of memory"); @@ -154,6 +155,17 @@ fl_scandir(const char *dir, struct dirent ***namelist, dirp = opendir(dir); if (NULL == dirp) { if (errmsg) fl_snprintf(errmsg, errmsg_sz, "%s", strerror(errno)); + + // XXX: This would be a thread safe alternative to the above, but commented + // out because we can get either GNU or POSIX versions on linux, + // which AFAICT are incompatible: GNU doesn't guarantee errmsg is used + // at all, whereas POSIX /only/ fills buffer. The two calls are not really + // compatible but have the same name and different return values.. wtf? + // + // if (errmsg && errmsg_sz > 0) { + // strerror_r(errno, errmsg, errmsg_sz); // thread safe. Might be GNU, might be POSIX + // errmsg[errmsg_sz-1] = '\0'; // force null term b/c XSI does not specify + // } return -1; }