[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
readdir_r again
From: |
Kevin Ryde |
Subject: |
readdir_r again |
Date: |
Fri, 24 Feb 2006 11:43:28 +1100 |
User-agent: |
Gnus/5.110004 (No Gnus v0.4) Emacs/21.4 (gnu/linux) |
I had another go at the readdir_r pathconf biz, below, this time
actually tested a bit. I'm inclined to use NAME_MAX rather than
fpathconf when there's a choice, because NAME_MAX is probably a
constant, but I'm open to arguments the other way.
When using pathconf it'd be possible to make the syscall to get the
size just once in opendir and store that in the smob (becoming a
double cell). Not sure if that's worth doing.
The plain readdir() case is protected by a mutex, but I'm wondering if
that's really necessary. It could be easier to assume that if you've
got posix threads then you've got readdir_r. Likewise with a lot of
these choices between plain and "_r" funcs.
SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
(SCM port),
"Return (as a string) the next directory entry from the directory
stream\n"
"@var{stream}. If there is no remaining entry to be read then
the\n"
"end of file object is returned.")
#define FUNC_NAME s_scm_readdir
{
struct dirent *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
{
DIR *ds = (DIR *) SCM_CELL_WORD_1 (port);
struct dirent de; /* just for sizeof */
size_t name_max, dirent_size, namlen;
char *buf;
int old_errno;
/* On solaris 10 there's no NAME_MAX constant, it's obligatory to use
pathconf(). */
#ifdef NAME_MAX
name_max = NAME_MAX;
#else
name_max = fpathconf (dirfd (ds), _PC_NAME_MAX);
if (name_max == -1)
SCM_SYSERROR;
#endif
/* 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 buffer
for readdir_r based on NAME_MAX. So the following effectively uses the
bigger of sizeof(d_name) or NAME_MAX. */
dirent_size = SCM_MAX (sizeof (de),
sizeof (de) - sizeof (de.d_name) + name_max + 1);
/* NAME_MAX is typically 255, so alloca on the stack is good */
buf = alloca (dirent_size);
errno = 0;
SCM_SYSCALL (readdir_r (ds, (struct dirent *) buf, &rdent));
if (errno != 0)
SCM_SYSERROR;
if (! rdent)
return SCM_EOF_VAL;
namlen = NAMLEN (rdent);
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 ((DIR *) SCM_CELL_WORD_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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- readdir_r again,
Kevin Ryde <=