Browse Source

Fix scandir function to reset the errno when the
selector returns zero(no entries) modifying the errno.
The attached test case implements a dummy filter that returns
alway no entries, but change the errno. scandir is not expected
to fail, just returning 0 entries.

Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>

Carmelo Amoroso 16 years ago
parent
commit
ab49004709
2 changed files with 37 additions and 2 deletions
  1. 16 2
      libc/misc/dirent/scandir.c
  2. 21 0
      test/misc/tst-scandir.c

+ 16 - 2
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))
     {

+ 21 - 0
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;
+}