diff options
-rw-r--r-- | libc/misc/dirent/scandir.c | 18 | ||||
-rw-r--r-- | test/misc/tst-scandir.c | 21 |
2 files changed, 37 insertions, 2 deletions
diff --git a/libc/misc/dirent/scandir.c b/libc/misc/dirent/scandir.c index aba63f20b..ad997b121 100644 --- a/libc/misc/dirent/scandir.c +++ b/libc/misc/dirent/scandir.c @@ -35,8 +35,21 @@ int scandir(const char *dir, struct dirent ***namelist, __set_errno (0); pos = 0; - while ((current = readdir (dp)) != NULL) - if (selector == NULL || (*selector) (current)) + while ((current = readdir (dp)) != NULL) { + int use_it = selector == NULL; + + if (! use_it) + { + use_it = (*selector) (current); + /* + * The selector function might have changed errno. + * It was zero before and it need to be again to make + * the latter tests work. + */ + if (! use_it) + __set_errno (0); + } + if (use_it) { struct dirent *vnew; size_t dsize; @@ -64,6 +77,7 @@ int scandir(const char *dir, struct dirent ***namelist, names[pos++] = (struct dirent *) memcpy (vnew, current, dsize); } + } if (unlikely(errno != 0)) { diff --git a/test/misc/tst-scandir.c b/test/misc/tst-scandir.c new file mode 100644 index 000000000..6e4646142 --- /dev/null +++ b/test/misc/tst-scandir.c @@ -0,0 +1,21 @@ +#include <dirent.h> +#include <errno.h> + +int skip_all(const struct dirent *dirbuf) +{ + __set_errno(EBADF); + return 0; +} + +int main() +{ + struct dirent **namelist; + int n; + + n = scandir(".", &namelist, skip_all, 0); + if (n < 0) { + perror("scandir"); + return 1; + } + return 0; +} |