summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2010-01-24 12:35:36 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2010-01-24 12:35:36 +0000
commitb3c4be736e48225b08b699ae9200e585441a8d5e (patch)
treec96ffe7ab80950945f7669f3be0d541f0c85f20d /lib/libc
parentbe6797dde88efc84055db6a0661ab512eeabe8a5 (diff)
Notes
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/opendir.c11
-rw-r--r--lib/libc/gen/scandir.313
-rw-r--r--lib/libc/gen/scandir.c35
3 files changed, 39 insertions, 20 deletions
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
index 9625ec690941..b312c89d76a7 100644
--- a/lib/libc/gen/opendir.c
+++ b/lib/libc/gen/opendir.c
@@ -92,6 +92,14 @@ __opendir2(const char *name, int flags)
return __opendir_common(fd, name, flags);
}
+static int
+opendir_compar(const void *p1, const void *p2)
+{
+
+ return (strcmp((*(const struct dirent **)p1)->d_name,
+ (*(const struct dirent **)p2)->d_name));
+}
+
/*
* Common routine for opendir(3), __opendir2(3) and fdopendir(3).
*/
@@ -240,7 +248,8 @@ __opendir_common(int fd, const char *name, int flags)
/*
* This sort must be stable.
*/
- mergesort(dpv, n, sizeof(*dpv), alphasort);
+ mergesort(dpv, n, sizeof(*dpv),
+ opendir_compar);
dpv[n] = NULL;
xp = NULL;
diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3
index 42ccac2465ca..e32b0d819e8c 100644
--- a/lib/libc/gen/scandir.3
+++ b/lib/libc/gen/scandir.3
@@ -28,7 +28,7 @@
.\" @(#)scandir.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd January 3, 2010
.Dt SCANDIR 3
.Os
.Sh NAME
@@ -38,12 +38,11 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In sys/types.h
.In dirent.h
.Ft int
-.Fn scandir "const char *dirname" "struct dirent ***namelist" "int \\*(lp*select\\*(rp\\*(lpstruct dirent *\\*(rp" "int \\*(lp*compar\\*(rp\\*(lpconst void *, const void *\\*(rp"
+.Fn scandir "const char *dirname" "struct dirent ***namelist" "int \\*(lp*select\\*(rp\\*(lpconst struct dirent *\\*(rp" "int \\*(lp*compar\\*(rp\\*(lpconst struct dirent **, const struct dirent **\\*(rp"
.Ft int
-.Fn alphasort "const void *d1" "const void *d2"
+.Fn alphasort "const struct dirent **d1" "const struct dirent **d2"
.Sh DESCRIPTION
The
.Fn scandir
@@ -82,7 +81,8 @@ The
function
is a routine which can be used for the
.Fa compar
-argument to sort the array alphabetically.
+argument to sort the array alphabetically using
+.Xr strcoll 3 .
.Pp
The memory allocated for the array can be deallocated with
.Xr free 3 ,
@@ -95,7 +95,8 @@ cannot allocate enough memory to hold all the data structures.
.Xr directory 3 ,
.Xr malloc 3 ,
.Xr qsort 3 ,
-.Xr dir 5
+.Xr dir 5 ,
+.Xr strcoll 3
.Sh HISTORY
The
.Fn scandir
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 1dae85d12a9c..93bc8523c90d 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include "un-namespace.h"
+static int alphasort_thunk(void *thunk, const void *p1, const void *p2);
+
/*
* The DIRSIZ macro is the minimum record length which will hold the directory
* entry. This requires the amount of space in struct dirent without the
@@ -58,11 +60,9 @@ __FBSDID("$FreeBSD$");
(((dp)->d_namlen + 1 + 3) &~ 3))
int
-scandir(dirname, namelist, select, dcomp)
- const char *dirname;
- struct dirent ***namelist;
- int (*select)(struct dirent *);
- int (*dcomp)(const void *, const void *);
+scandir(const char *dirname, struct dirent ***namelist,
+ int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **,
+ const struct dirent **))
{
struct dirent *d, *p, **names = NULL;
size_t nitems = 0;
@@ -111,26 +111,35 @@ scandir(dirname, namelist, select, dcomp)
}
closedir(dirp);
if (nitems && dcomp != NULL)
- qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ qsort_r(names, nitems, sizeof(struct dirent *),
+ &dcomp, alphasort_thunk);
*namelist = names;
- return(nitems);
+ return (nitems);
fail:
while (nitems > 0)
free(names[--nitems]);
free(names);
closedir(dirp);
- return -1;
+ return (-1);
}
/*
* Alphabetic order comparison routine for those who want it.
+ * POSIX 2008 requires that alphasort() uses strcoll().
*/
int
-alphasort(d1, d2)
- const void *d1;
- const void *d2;
+alphasort(const struct dirent **d1, const struct dirent **d2)
+{
+
+ return (strcoll((*d1)->d_name, (*d2)->d_name));
+}
+
+static int
+alphasort_thunk(void *thunk, const void *p1, const void *p2)
{
- return(strcmp((*(struct dirent **)d1)->d_name,
- (*(struct dirent **)d2)->d_name));
+ int (*dc)(const struct dirent **, const struct dirent **);
+
+ dc = *(int (**)(const struct dirent **, const struct dirent **))thunk;
+ return (dc((const struct dirent **)p1, (const struct dirent **)p2));
}