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.
This commit is contained in:
Greg Ercolano 2020-07-11 14:35:59 -07:00 committed by Albrecht Schlosser
parent 0693c70f57
commit 4471166f59
1 changed files with 12 additions and 0 deletions

View File

@ -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;
}