1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-09 13:30:26 +02:00

Use readdir instead of readdir_r

* libguile/filesys.c:
* configure.ac: Remove readdir_r / readdir64_r checks and usage.
  glibc's impls are thread-safe, the _r variants are squirrely and now
  deprecated in glibc, and it is expected that POSIX will mandate that
  readdir{,64} be thread-safe already.  See
  https://sourceware.org/ml/libc-alpha/2016-02/msg00093.html.
This commit is contained in:
Andy Wingo 2016-12-06 23:02:28 +01:00
parent 8e20a991a9
commit 7ff3d3834d
2 changed files with 12 additions and 65 deletions

View file

@ -773,7 +773,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h])
AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid \
fesetround ftime ftruncate fchown fchmod getcwd geteuid getsid \
gettimeofday getuid getgid gmtime_r ioctl lstat mkdir mknod nice \
readdir_r readdir64_r readlink rename rmdir setegid seteuid \
readlink rename rmdir setegid seteuid \
setlocale setuid setgid setpgid setsid sigaction siginterrupt stat64 \
strptime symlink sync sysconf tcgetpgrp tcsetpgrp uname waitpid \
strdup system usleep atexit on_exit chown link fcntl ttyname getpwent \

View file

@ -26,9 +26,6 @@
/* See stime.c for comments on why _POSIX_C_SOURCE is not always defined. */
#define _LARGEFILE64_SOURCE /* ask for stat64 etc */
#ifdef __hpux
#define _POSIX_C_SOURCE 199506L /* for readdir_r */
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
@ -1723,12 +1720,6 @@ SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
#undef FUNC_NAME
/* FIXME: The glibc manual has a portability note that readdir_r may not
null-terminate its return string. The circumstances outlined for this
are not clear, nor is it clear what should be done about it. Lets use
NAMLEN and worry about what else should be done if/when someone can
figure it out. */
SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
(SCM port),
"Return (as a string) the next directory entry from the directory stream\n"
@ -1736,70 +1727,26 @@ SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
"end of file object is returned.")
#define FUNC_NAME s_scm_readdir
{
SCM ret;
struct dirent_or_dirent64 *rdent;
SCM_VALIDATE_DIR (1, port);
if (!SCM_DIR_OPEN_P (port))
SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
#if HAVE_READDIR_R
/* As noted in the glibc manual, on various systems (such as Solaris)
the d_name[] field is only 1 char and you're expected to size the
dirent buffer for readdir_r based on NAME_MAX. The MAX expressions
below effectively give either sizeof(d_name) or NAME_MAX+1,
whichever is bigger.
scm_dynwind_begin (0);
scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
On solaris 10 there's no NAME_MAX constant, it's necessary to use
pathconf(). We prefer NAME_MAX though, since it should be a constant
and will therefore save a system call. We also prefer it since dirfd()
is not available everywhere.
errno = 0;
SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_SMOB_DATA_1 (port)));
if (errno != 0)
SCM_SYSERROR;
An alternative to dirfd() would be to open() the directory and then use
fdopendir(), if the latter is available. That'd let us hold the fd
somewhere in the smob, or just the dirent size calculated once. */
{
struct dirent_or_dirent64 de; /* just for sizeof */
DIR *ds = (DIR *) SCM_SMOB_DATA_1 (port);
#ifdef NAME_MAX
char buf [MAX (sizeof (de),
sizeof (de) - sizeof (de.d_name) + NAME_MAX + 1)];
#else
char *buf;
long name_max = fpathconf (dirfd (ds), _PC_NAME_MAX);
if (name_max == -1)
SCM_SYSERROR;
buf = alloca (MAX (sizeof (de),
sizeof (de) - sizeof (de.d_name) + name_max + 1));
#endif
ret = (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
: SCM_EOF_VAL);
errno = 0;
SCM_SYSCALL (readdir_r_or_readdir64_r (ds, (struct dirent_or_dirent64 *) buf, &rdent));
if (errno != 0)
SCM_SYSERROR;
if (! rdent)
return SCM_EOF_VAL;
return (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
: SCM_EOF_VAL);
}
#else
{
SCM ret;
scm_dynwind_begin (0);
scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
errno = 0;
SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_SMOB_DATA_1 (port)));
if (errno != 0)
SCM_SYSERROR;
ret = (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
: SCM_EOF_VAL);
scm_dynwind_end ();
return ret;
}
#endif
scm_dynwind_end ();
return ret;
}
#undef FUNC_NAME