summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/misc/dirent/scandir.c18
-rw-r--r--test/misc/tst-scandir.c21
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;
+}