parser: Fix return value of dirat_for_each()

Seth pointed out that dirat_for_each() didn't correctly handle the
return value from readdir_r(). On error, it directly returns a positive
errno value. This would have resulted in that positive errno value being
returned, with an undefined errno value set, from dirat_for_each().
However, the dirat_for_each() documentation states that -1 is returned,
with errno set, on error.

This patch results in readdir_r()'s return value being handled
appropriately. In addition, it ensures that 0 is always returned on
success.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Reported-by: Seth Arnold <seth.arnold@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
This commit is contained in:
Tyler Hicks 2015-03-02 09:50:07 -06:00
parent cec9b0d09f
commit 65b0048aae

View file

@ -62,9 +62,9 @@
int dirat_for_each(DIR *dir, const char *name, void *data,
int (* cb)(DIR *, const char *, struct stat *, void *))
{
struct dirent *dirent = NULL, *ent;
struct dirent *dirent = NULL;
DIR *d = NULL;
int error = 0;
int error;
if (!cb || (!dir && !name)) {
errno = EINVAL;
@ -102,11 +102,19 @@ int dirat_for_each(DIR *dir, const char *name, void *data,
d = dir;
}
for (error = readdir_r(d, dirent, &ent);
error == 0 && ent != NULL;
error = readdir_r(d, dirent, &ent)) {
for (;;) {
struct dirent *ent;
struct stat my_stat;
error = readdir_r(d, dirent, &ent);
if (error) {
PDEBUG("readdir_r failed");
errno = error; /* readdir_r directly returns an errno */
goto fail;
} else if (!ent) {
break;
}
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
continue;
@ -126,7 +134,7 @@ int dirat_for_each(DIR *dir, const char *name, void *data,
closedir(d);
free(dirent);
return error;
return 0;
fail:
error = errno;