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:
parent
8e20a991a9
commit
7ff3d3834d
2 changed files with 12 additions and 65 deletions
|
@ -773,7 +773,7 @@ AC_CHECK_HEADERS([assert.h crt_externs.h])
|
||||||
AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid \
|
AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid \
|
||||||
fesetround ftime ftruncate fchown fchmod getcwd geteuid getsid \
|
fesetround ftime ftruncate fchown fchmod getcwd geteuid getsid \
|
||||||
gettimeofday getuid getgid gmtime_r ioctl lstat mkdir mknod nice \
|
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 \
|
setlocale setuid setgid setpgid setsid sigaction siginterrupt stat64 \
|
||||||
strptime symlink sync sysconf tcgetpgrp tcsetpgrp uname waitpid \
|
strptime symlink sync sysconf tcgetpgrp tcsetpgrp uname waitpid \
|
||||||
strdup system usleep atexit on_exit chown link fcntl ttyname getpwent \
|
strdup system usleep atexit on_exit chown link fcntl ttyname getpwent \
|
||||||
|
|
|
@ -26,9 +26,6 @@
|
||||||
|
|
||||||
/* See stime.c for comments on why _POSIX_C_SOURCE is not always defined. */
|
/* See stime.c for comments on why _POSIX_C_SOURCE is not always defined. */
|
||||||
#define _LARGEFILE64_SOURCE /* ask for stat64 etc */
|
#define _LARGEFILE64_SOURCE /* ask for stat64 etc */
|
||||||
#ifdef __hpux
|
|
||||||
#define _POSIX_C_SOURCE 199506L /* for readdir_r */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
|
@ -1723,12 +1720,6 @@ SCM_DEFINE (scm_opendir, "opendir", 1, 0, 0,
|
||||||
#undef FUNC_NAME
|
#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_DEFINE (scm_readdir, "readdir", 1, 0, 0,
|
||||||
(SCM port),
|
(SCM port),
|
||||||
"Return (as a string) the next directory entry from the directory stream\n"
|
"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.")
|
"end of file object is returned.")
|
||||||
#define FUNC_NAME s_scm_readdir
|
#define FUNC_NAME s_scm_readdir
|
||||||
{
|
{
|
||||||
|
SCM ret;
|
||||||
struct dirent_or_dirent64 *rdent;
|
struct dirent_or_dirent64 *rdent;
|
||||||
|
|
||||||
SCM_VALIDATE_DIR (1, port);
|
SCM_VALIDATE_DIR (1, port);
|
||||||
if (!SCM_DIR_OPEN_P (port))
|
if (!SCM_DIR_OPEN_P (port))
|
||||||
SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
|
SCM_MISC_ERROR ("Directory ~S is not open.", scm_list_1 (port));
|
||||||
|
|
||||||
#if HAVE_READDIR_R
|
scm_dynwind_begin (0);
|
||||||
/* As noted in the glibc manual, on various systems (such as Solaris)
|
scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex);
|
||||||
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.
|
|
||||||
|
|
||||||
On solaris 10 there's no NAME_MAX constant, it's necessary to use
|
errno = 0;
|
||||||
pathconf(). We prefer NAME_MAX though, since it should be a constant
|
SCM_SYSCALL (rdent = readdir_or_readdir64 ((DIR *) SCM_SMOB_DATA_1 (port)));
|
||||||
and will therefore save a system call. We also prefer it since dirfd()
|
if (errno != 0)
|
||||||
is not available everywhere.
|
SCM_SYSERROR;
|
||||||
|
|
||||||
An alternative to dirfd() would be to open() the directory and then use
|
ret = (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
|
||||||
fdopendir(), if the latter is available. That'd let us hold the fd
|
: SCM_EOF_VAL);
|
||||||
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
|
|
||||||
|
|
||||||
errno = 0;
|
scm_dynwind_end ();
|
||||||
SCM_SYSCALL (readdir_r_or_readdir64_r (ds, (struct dirent_or_dirent64 *) buf, &rdent));
|
return ret;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue