Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com Message-Id: <199905231651.LAA03799@mercury.xraylith.wisc.edu> To: cygwin-developers AT sourceware DOT cygnus DOT com Subject: (patch) errno and misc changes for scandir Date: Sun, 23 May 1999 11:51:10 -0500 From: Mumit Khan 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 * 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 #include +#include +#include +#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); } +