Modernize scandir(3) and alphasort(3) interfaces according to the IEEE

Std 1003.1-2008. Both Linux and Solaris conforms to the new definitions,
so we better follow too (older glibc used old BSDish alphasort prototype
and corresponding type of the comparision function for scandir). While
there, change the definitions of the functions to ANSI C and fix several
style issues nearby.

Remove requirement for "sys/types.h" include for functions from manpage.

POSIX also requires that alphasort(3) sorts as if strcoll(3) was used,
but leave the strcmp(3) call in the function for now.

Adapt in-tree callers of scandir(3) to new declaration. The fact that
select_sections() from catman(1) could modify supplied struct dirent is
a bug.

PR:	standards/142255
MFC after:	2 weeks
This commit is contained in:
kib 2010-01-04 15:40:17 +00:00
parent 16db58ba54
commit d061de008a
8 changed files with 30 additions and 26 deletions

View File

@ -95,7 +95,7 @@ typedef void * DIR;
__BEGIN_DECLS
#if __BSD_VISIBLE
DIR *__opendir2(const char *, int);
int alphasort(const void *, const void *);
int alphasort(const struct dirent **, const struct dirent **);
int getdents(int, char *, int);
int getdirentries(int, char *, int, long *);
#endif
@ -109,7 +109,8 @@ int readdir_r(DIR *, struct dirent *, struct dirent **);
void rewinddir(DIR *);
#if __BSD_VISIBLE
int scandir(const char *, struct dirent ***,
int (*)(struct dirent *), int (*)(const void *, const void *));
int (*)(const struct dirent *), int (*)(const struct dirent **,
const struct dirent **));
#endif
#if __XSI_VISIBLE
void seekdir(DIR *, long);

View File

@ -240,7 +240,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), (int (*)(const
void *, const void *))alphasort);
dpv[n] = NULL;
xp = NULL;

View File

@ -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

View File

@ -58,11 +58,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 +109,25 @@ scandir(dirname, namelist, select, dcomp)
}
closedir(dirp);
if (nitems && dcomp != NULL)
qsort(names, nitems, sizeof(struct dirent *), dcomp);
qsort(names, nitems, sizeof(struct dirent *),
(int (*)(const void *, const void *))dcomp);
*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.
*/
int
alphasort(d1, d2)
const void *d1;
const void *d2;
alphasort(const struct dirent **d1, const struct dirent **d2)
{
return(strcmp((*(struct dirent **)d1)->d_name,
(*(struct dirent **)d2)->d_name));
return (strcmp((*d1)->d_name, (*d2)->d_name));
}

View File

@ -589,9 +589,15 @@ process_section(char *mandir, char *section)
}
static int
select_sections(struct dirent *entry)
select_sections(const struct dirent *entry)
{
return directory_type(entry->d_name) == MAN_SECTION_DIR;
char *name;
int ret;
name = strdup(entry->d_name);
ret = directory_type(name) == MAN_SECTION_DIR;
free(name);
return (ret);
}
/*

View File

@ -879,9 +879,9 @@ process_section(char *section_dir)
* Returns whether the directory entry is a man page section.
*/
static int
select_sections(struct dirent *entry)
select_sections(const struct dirent *entry)
{
char *p = &entry->d_name[3];
const char *p = &entry->d_name[3];
if (strncmp(entry->d_name, "man", 3) != 0)
return 0;

View File

@ -280,7 +280,7 @@ void inform(const struct printer *_pp, char *_cf);
void init_printer(struct printer *_pp);
void init_request(struct request *_rp);
int inlist(char *_uname, char *_cfile);
int iscf(struct dirent *_d);
int iscf(const struct dirent *_d);
void ldump(const char *_nfile, const char *_datafile, int _copies);
void lastprinter(void);
int lockchk(struct printer *_pp, char *_slockf);

View File

@ -384,7 +384,7 @@ rmremote(const struct printer *pp)
* Return 1 if the filename begins with 'cf'
*/
int
iscf(struct dirent *d)
iscf(const struct dirent *d)
{
return(d->d_name[0] == 'c' && d->d_name[1] == 'f');
}