Do not rely on behaviour undefined by ANSI C, use thunks to adapt
alphasort-like interface to the comparision function required by qsort() and qsort_r(). For opendir() thunk and alphasort(), comment on why we deviated from POSIX by using strcmp() instead of strcoll(). Requested and reviewed by: bde MFC after: 2 weeks
This commit is contained in:
parent
7b331f63c5
commit
f5636f881b
@ -92,6 +92,18 @@ __opendir2(const char *name, int flags)
|
||||
return __opendir_common(fd, name, 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).
|
||||
*/
|
||||
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user