diff options
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/gen/opendir.c | 16 | ||||
-rw-r--r-- | lib/libc/gen/scandir.c | 21 |
2 files changed, 33 insertions, 4 deletions
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c index 631c4d6..c192ab2 100644 --- a/lib/libc/gen/opendir.c +++ b/lib/libc/gen/opendir.c @@ -93,6 +93,18 @@ __opendir2(const char *name, int flags) } /* + * POSIX 2008 and XSI 7 require alphasort() to call strcoll() for + * directory entries ordering. Use local copy that uses strcmp(). + */ +static int +opendir_alphasort(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). */ static DIR * @@ -240,8 +252,8 @@ __opendir_common(int fd, const char *name, int flags) /* * This sort must be stable. */ - mergesort(dpv, n, sizeof(*dpv), (int (*)(const - void *, const void *))alphasort); + mergesort(dpv, n, sizeof(*dpv), + opendir_alphasort); dpv[n] = NULL; xp = NULL; diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index 47fad1d..b6f76ba 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 @@ -109,8 +111,8 @@ scandir(const char *dirname, struct dirent ***namelist, } closedir(dirp); if (nitems && dcomp != NULL) - qsort(names, nitems, sizeof(struct dirent *), - (int (*)(const void *, const void *))dcomp); + qsort_r(names, nitems, sizeof(struct dirent *), + &dcomp, alphasort_thunk); *namelist = names; return (nitems); @@ -124,6 +126,12 @@ fail: /* * Alphabetic order comparison routine for those who want it. + * + * XXXKIB POSIX 2008 requires the alphasort() to use strcoll(). Keep + * strcmp() for now, since environment locale settings could have no + * relevance for the byte sequence of the file name. Moreover, it + * might be even invalid sequence in current locale, and then + * behaviour of alphasort would be undefined. */ int alphasort(const struct dirent **d1, const struct dirent **d2) @@ -131,3 +139,12 @@ alphasort(const struct dirent **d1, const struct dirent **d2) return (strcmp((*d1)->d_name, (*d2)->d_name)); } + +static int +alphasort_thunk(void *thunk, const void *p1, const void *p2) +{ + 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)); +} |