standards/142255: scandir prototype in dirent.h isn't compliant with POSIX 2008

Kostik Belousov kostikbel at gmail.com
Sun Jan 3 15:00:12 UTC 2010


The following reply was made to PR standards/142255; it has been noted by GNATS.

From: Kostik Belousov <kostikbel at gmail.com>
To: Kevin Barry <ta0kira at users.berlios.de>
Cc: freebsd-gnats-submit at freebsd.org
Subject: Re: standards/142255: scandir prototype in dirent.h isn't compliant with POSIX 2008
Date: Sun, 3 Jan 2010 16:35:48 +0200

 --XIiC+We3v3zHqZ6Z
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable
 
 The change of the prototype shall also fix alphasort(3). And then, each
 in-tree consumer should be updated.
 
 scandir(3) is historical BSD interface, that only appeared in SUSv4.
 It seems that Solaris and possibly glibc are conforming, so FreeBSD
 should probably follow the route.
 
 Test the patch below.
 
 diff --git a/include/dirent.h b/include/dirent.h
 index 63626b5..8d7e5c1 100644
 --- a/include/dirent.h
 +++ b/include/dirent.h
 @@ -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);
 diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
 index 9625ec6..631c4d6 100644
 --- a/lib/libc/gen/opendir.c
 +++ b/lib/libc/gen/opendir.c
 @@ -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);
 =20
  				dpv[n] =3D NULL;
  				xp =3D NULL;
 diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3
 index 42ccac2..c5367d3 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
 @@ -41,9 +41,9 @@
  .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\\*(lpcons=
 t 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
 diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
 index 1dae85d..47fad1d 100644
 --- a/lib/libc/gen/scandir.c
 +++ b/lib/libc/gen/scandir.c
 @@ -58,11 +58,9 @@ __FBSDID("$FreeBSD$");
  	    (((dp)->d_namlen + 1 + 3) &~ 3))
 =20
  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 =3D NULL;
  	size_t nitems =3D 0;
 @@ -111,26 +109,25 @@ scandir(dirname, namelist, select, dcomp)
  	}
  	closedir(dirp);
  	if (nitems && dcomp !=3D NULL)
 -		qsort(names, nitems, sizeof(struct dirent *), dcomp);
 +		qsort(names, nitems, sizeof(struct dirent *),
 +		    (int (*)(const void *, const void *))dcomp);
  	*namelist =3D names;
 -	return(nitems);
 +	return (nitems);
 =20
  fail:
  	while (nitems > 0)
  		free(names[--nitems]);
  	free(names);
  	closedir(dirp);
 -	return -1;
 +	return (-1);
  }
 =20
  /*
   * 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));
  }
 diff --git a/usr.bin/catman/catman.c b/usr.bin/catman/catman.c
 index ba3ad24..c17a091 100644
 --- a/usr.bin/catman/catman.c
 +++ b/usr.bin/catman/catman.c
 @@ -589,9 +589,15 @@ process_section(char *mandir, char *section)
  }
 =20
  static int
 -select_sections(struct dirent *entry)
 +select_sections(const struct dirent *entry)
  {
 -	return directory_type(entry->d_name) =3D=3D MAN_SECTION_DIR;
 +	char *name;
 +	int ret;
 +
 +	name =3D strdup(entry->d_name);
 +	ret =3D directory_type(name) =3D=3D MAN_SECTION_DIR;
 +	free(name);
 +	return (ret);
  }
 =20
  /*
 diff --git a/usr.bin/makewhatis/makewhatis.c b/usr.bin/makewhatis/makewhati=
 s.c
 index 6b2dce4..f2ae370 100644
 --- a/usr.bin/makewhatis/makewhatis.c
 +++ b/usr.bin/makewhatis/makewhatis.c
 @@ -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 =3D &entry->d_name[3];
 +	const char *p =3D &entry->d_name[3];
 =20
  	if (strncmp(entry->d_name, "man", 3) !=3D 0)
  		return 0;
 diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/l=
 p.h
 index 891ed2f..63f2ff1 100644
 --- a/usr.sbin/lpr/common_source/lp.h
 +++ b/usr.sbin/lpr/common_source/lp.h
 @@ -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);
 diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_sourc=
 e/rmjob.c
 index d6fd614..33fcdac 100644
 --- a/usr.sbin/lpr/common_source/rmjob.c
 +++ b/usr.sbin/lpr/common_source/rmjob.c
 @@ -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] =3D=3D 'c' && d->d_name[1] =3D=3D 'f');
  }
 
 --XIiC+We3v3zHqZ6Z
 Content-Type: application/pgp-signature
 Content-Disposition: inline
 
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (FreeBSD)
 
 iEYEARECAAYFAktAq0MACgkQC3+MBN1Mb4ijXACgwBf2oKjKYmciIoRA00OMiv1B
 vyAAoI/K4gBuYPllsltnen9QS9Uwxu0M
 =aJqd
 -----END PGP SIGNATURE-----
 
 --XIiC+We3v3zHqZ6Z--


More information about the freebsd-standards mailing list