This is the mail archive of the cygwin-developers@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

(patch) errno and misc changes for scandir



The following change to scandir is needed to avoid setting errno incorrectly.
There is one more change that I didn't include -- comparison function that
takes void*, not struct dirent* to be glibc2.1 compatible. It's not a big
deal either way since scandir/alphasort is not part of POSIX; I just didn't 
feel like changing the headers as well.

Sat May 22 21:45:01 1999  Mumit Khan  <khan@xraylith.wisc.edu>

	* scandir.cc (scandir): Handle errno correctly. Do preallocation to 
	reduce realloc calls.
	(alphasort): Use strcoll, not strcmp.

Index: scandir.cc
===================================================================
RCS file: /home/khan/CVSROOT/cygwin/cygwin-dev/winsup/scandir.cc,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 scandir.cc
--- scandir.cc	1999/05/21 23:51:13	1.1.1.1
+++ scandir.cc	1999/05/23 02:47:05
@@ -12,6 +12,9 @@
 
 #include <dirent.h>
 #include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "winsup.h"
 
 extern "C"
 int
@@ -23,45 +26,76 @@ scandir (const char *dir,
   DIR *dirp;
   struct dirent *ent, *etmp, **nl = NULL, **ntmp;
   int count = 0;
+  int allocated = 0;
 
   if (!(dirp = opendir (dir)))
     return -1;
+
+  int prior_errno = get_errno ();
+  set_errno (0);
+
   while ((ent = readdir (dirp)))
     {
       if (!select || select (ent))
 	{
+
+	  /* Ignore error from readdir/select. See POSIX specs. */
+	  set_errno (0);
+
+	  if (count == allocated)
+	    {
+
+	      if (allocated == 0)
+		allocated = 10;
+	      else
+		allocated *= 2;
+
+	      ntmp = (struct dirent **) realloc (nl, allocated * sizeof *nl);
+	      if (!ntmp)
+		{
+		  set_errno (ENOMEM);
+		  break;
+		}
+	      nl = ntmp;
+	  }
+
 	  if (!(etmp = (struct dirent *) malloc (sizeof *ent)))
-	    goto error;
-	  *etmp = *ent;
-	  ntmp = (struct dirent **) realloc (nl, (count + 1) * sizeof *nl);
-	  if (!ntmp)
 	    {
-	      free (etmp);
-	      goto error;
+	      set_errno (ENOMEM);
+	      break;
 	    }
-	  nl = ntmp;
+	  *etmp = *ent;
 	  nl[count++] = etmp;
 	}
     }
+
+  if ((prior_errno = get_errno ()) != 0)
+    {
+      closedir (dirp);
+      if (nl)
+        {
+          while (count > 0)
+            free (nl[--count]);
+          free (nl);
+        }
+      /* Ignore errors from closedir() and what not else. */
+      set_errno (prior_errno);
+      return -1;
+    }
+
   closedir (dirp);
+  set_errno (prior_errno);
+
   qsort (nl, count, sizeof *nl, (int (*)(const void *, const void *)) compar);
   if (namelist)
     *namelist = nl;
   return count;
-
-error:
-  if (nl)
-    {
-      while (count > 0)
-	free (nl[--count]);
-      free (nl);
-    }
-  return -1;
 }
 
 extern "C"
 int
 alphasort (const struct dirent **a, const struct dirent **b)
 {
-  return strcmp ((*a)->d_name, (*b)->d_name);
+  return strcoll ((*a)->d_name, (*b)->d_name);
 }
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]