add mutex locking for directories and readdir_r(3). Influenced by FreeBSD.

This commit is contained in:
christos 2003-05-28 20:03:37 +00:00
parent cb9a14ea0b
commit 9af7135771
7 changed files with 160 additions and 41 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile.inc,v 1.120 2003/02/13 03:00:51 nathanw Exp $
# $NetBSD: Makefile.inc,v 1.121 2003/05/28 20:03:37 christos Exp $
# from: @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
# gen sources
@ -62,8 +62,8 @@ MAN+= alarm.3 arc4random.3 basename.3 bswap.3 clock.3 confstr.3 \
MLINKS+=bswap.3 bswap16.3 bswap.3 bswap32.3 bswap.3 bswap64.3
MLINKS+=directory.3 closedir.3 directory.3 dirfd.3 directory.3 opendir.3 \
directory.3 readdir.3 directory.3 rewinddir.3 directory.3 seekdir.3 \
directory.3 telldir.3
directory.3 readdir.3 directory.3 readdir_r.3 directory.3 \
rewinddir.3 directory.3 seekdir.3 directory.3 telldir.3
MLINKS+=endutxent.3 getutxent.3 endutxent.3 getutxid.3 \
endutxent.3 getutxline.3 endutxent.3 pututxline.3 \
endutxent.3 setutxent.3

View File

@ -1,4 +1,4 @@
/* $NetBSD: closedir.c,v 1.10 2000/01/22 22:19:09 mycroft Exp $ */
/* $NetBSD: closedir.c,v 1.11 2003/05/28 20:03:37 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -38,11 +38,12 @@
#if 0
static char sccsid[] = "@(#)closedir.c 8.1 (Berkeley) 6/10/93";
#else
__RCSID("$NetBSD: closedir.c,v 1.10 2000/01/22 22:19:09 mycroft Exp $");
__RCSID("$NetBSD: closedir.c,v 1.11 2003/05/28 20:03:37 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include "reentrant.h"
#include <sys/types.h>
#include <assert.h>
@ -66,11 +67,22 @@ closedir(dirp)
_DIAGASSERT(dirp != NULL);
seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */
#ifdef _REENTRANT
if (__isthreaded)
mutex_lock((mutex_t *)dirp->dd_lock);
#endif
__seekdir(dirp, dirp->dd_rewind); /* free seekdir storage */
fd = dirp->dd_fd;
dirp->dd_fd = -1;
dirp->dd_loc = 0;
free((void *)dirp->dd_buf);
free((void *)dirp);
#ifdef _REENTRANT
if (__isthreaded) {
mutex_unlock((mutex_t *)dirp->dd_lock);
mutex_destroy((mutex_t *)dirp->dd_lock);
free(dirp->dd_lock);
}
#endif
return(close(fd));
}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: directory.3,v 1.20 2003/04/16 13:34:36 wiz Exp $
.\" $NetBSD: directory.3,v 1.21 2003/05/28 20:03:37 christos Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -33,12 +33,13 @@
.\"
.\" @(#)directory.3 8.1 (Berkeley) 6/4/93
.\"
.Dd August 10, 2002
.Dd May 28, 2003
.Dt DIRECTORY 3
.Os
.Sh NAME
.Nm opendir ,
.Nm readdir ,
.Nm readdir_r ,
.Nm telldir ,
.Nm seekdir ,
.Nm rewinddir ,
@ -53,6 +54,8 @@
.Fn opendir "const char *filename"
.Ft struct dirent *
.Fn readdir "DIR *dirp"
.Ft int
.Fn readdir_r "DIR *dirp" "struct dirent *entry" "struct dirent **result"
.Ft long
.Fn telldir "const DIR *dirp"
.Ft void
@ -94,6 +97,26 @@ upon reaching the end of the directory or detecting an invalid
.Fn seekdir
operation.
.Pp
The
.Fn readdir_r
function
provides the same functionality as
.Fn readdir ,
but the caller must provide a directory
.Fa entry
buffer to store the results in. If the read succeeds,
.Fa result
is pointed at the
.Fa entry ;
upon reaching the end of the directory
.Fa result
is set to
.Dv NULL .
The
.Fn readdir_r
function
returns 0 on success or an error number to indicate failure.
.Pp
The
.Fn telldir
function

View File

@ -1,4 +1,4 @@
/* $NetBSD: opendir.c,v 1.21 2003/03/02 14:17:07 enami Exp $ */
/* $NetBSD: opendir.c,v 1.22 2003/05/28 20:03:37 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -38,11 +38,12 @@
#if 0
static char sccsid[] = "@(#)opendir.c 8.7 (Berkeley) 12/10/94";
#else
__RCSID("$NetBSD: opendir.c,v 1.21 2003/03/02 14:17:07 enami Exp $");
__RCSID("$NetBSD: opendir.c,v 1.22 2003/05/28 20:03:37 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include "reentrant.h"
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
@ -77,8 +78,9 @@ __opendir2(name, flags)
const char *name;
int flags;
{
DIR *dirp;
DIR *dirp = NULL;
int fd;
int serrno;
struct stat sb;
int pagesz;
int incr;
@ -90,15 +92,15 @@ __opendir2(name, flags)
if ((fd = open(name, O_RDONLY | O_NONBLOCK)) == -1)
return (NULL);
if (fstat(fd, &sb) || !S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
close(fd);
errno = ENOTDIR;
return (NULL);
}
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1 ||
(dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
close(fd);
return (NULL);
goto error;
}
dirp->dd_buf = NULL;
/*
* If the machine's page size is an exact multiple of DIRBLKSIZ,
@ -115,11 +117,8 @@ __opendir2(name, flags)
* Determine whether this directory is the top of a union stack.
*/
if (fstatfs(fd, &sfb) < 0) {
free(dirp);
close(fd);
return (NULL);
}
if (fstatfs(fd, &sfb) < 0)
goto error;
if (flags & DTF_NODUP)
unionstack = !(strncmp(sfb.f_fstypename, MOUNT_UNION,
@ -167,10 +166,8 @@ retry:
len += incr;
nbuf = realloc(buf, len);
if (nbuf == NULL) {
free(buf);
free(dirp);
close(fd);
return (NULL);
dirp->dd_buf = buf;
goto error;
}
buf = nbuf;
ddptr = buf + (len - space);
@ -208,9 +205,8 @@ retry:
if (flags & DTF_REWIND) {
(void) close(fd);
if ((fd = open(name, O_RDONLY)) == -1) {
free(buf);
free(dirp);
return (NULL);
dirp->dd_buf = buf;
goto error;
}
}
@ -296,11 +292,8 @@ retry:
} else {
dirp->dd_len = incr;
dirp->dd_buf = malloc((size_t)dirp->dd_len);
if (dirp->dd_buf == NULL) {
free(dirp);
close(fd);
return (NULL);
}
if (dirp->dd_buf == NULL)
goto error;
dirp->dd_seek = 0;
flags &= ~DTF_REWIND;
}
@ -313,6 +306,22 @@ retry:
* Set up seek point for rewinddir.
*/
dirp->dd_rewind = telldir(dirp);
#ifdef _REENTRANT
if (__isthreaded) {
if ((dirp->dd_lock = malloc(sizeof(mutex_t))) == NULL)
goto error;
mutex_init((mutex_t *)dirp->dd_lock, NULL);
}
#endif
return (dirp);
error:
serrno = errno;
if (dirp && dirp->dd_buf)
free(dirp->dd_buf);
if (dirp)
free(dirp);
if (fd != -1)
(void)close(fd);
errno = serrno;
return NULL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: readdir.c,v 1.15 2000/01/22 22:19:12 mycroft Exp $ */
/* $NetBSD: readdir.c,v 1.16 2003/05/28 20:03:37 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -38,11 +38,12 @@
#if 0
static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94";
#else
__RCSID("$NetBSD: readdir.c,v 1.15 2000/01/22 22:19:12 mycroft Exp $");
__RCSID("$NetBSD: readdir.c,v 1.16 2003/05/28 20:03:37 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include "reentrant.h"
#include <sys/param.h>
#include <dirent.h>
@ -51,14 +52,14 @@ __RCSID("$NetBSD: readdir.c,v 1.15 2000/01/22 22:19:12 mycroft Exp $");
#ifdef __weak_alias
__weak_alias(readdir,_readdir)
__weak_alias(readdir_r,_readdir_r)
#endif
/*
* get next entry in a directory.
*/
struct dirent *
readdir(dirp)
DIR *dirp;
static struct dirent *
_readdir_unlocked(DIR *dirp)
{
struct dirent *dp;
@ -91,3 +92,58 @@ readdir(dirp)
return (dp);
}
}
struct dirent *
readdir(dirp)
DIR *dirp;
{
struct dirent *dp;
#ifdef _REENTRANT
if (__isthreaded) {
mutex_lock((mutex_t *)dirp->dd_lock);
dp = _readdir_unlocked(dirp);
mutex_unlock((mutex_t *)dirp->dd_lock);
}
else
#endif
dp = _readdir_unlocked(dirp);
return (dp);
}
int
readdir_r(dirp, entry, result)
DIR *dirp;
struct dirent *entry;
struct dirent **result;
{
struct dirent *dp;
int saved_errno;
saved_errno = errno;
errno = 0;
#ifdef _REENTRANT
if (__isthreaded) {
mutex_lock((mutex_t *)dirp->dd_lock);
if ((dp = _readdir_unlocked(dirp)) != NULL)
memcpy(entry, dp, DIRENT_SIZE(dp));
mutex_unlock((mutex_t *)dirp->dd_lock);
}
else
#endif
if ((dp = _readdir_unlocked(dirp)) != NULL)
memcpy(entry, dp, DIRENT_SIZE(dp));
if (errno != 0) {
if (dp == NULL)
return (errno);
} else
errno = saved_errno;
if (dp != NULL)
*result = entry;
else
*result = NULL;
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: seekdir.c,v 1.9 2000/01/22 22:19:12 mycroft Exp $ */
/* $NetBSD: seekdir.c,v 1.10 2003/05/28 20:03:37 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -38,11 +38,12 @@
#if 0
static char sccsid[] = "@(#)seekdir.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: seekdir.c,v 1.9 2000/01/22 22:19:12 mycroft Exp $");
__RCSID("$NetBSD: seekdir.c,v 1.10 2003/05/28 20:03:37 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include "reentrant.h"
#include <sys/param.h>
#include <dirent.h>
@ -61,6 +62,15 @@ seekdir(dirp, loc)
long loc;
{
#ifdef _REENTRANT
if (__isthreaded)
mutex_lock((mutex_t *)dirp->dd_lock);
#endif
__seekdir(dirp, loc);
#ifdef _REENTRANT
if (__isthreaded)
mutex_unlock((mutex_t *)dirp->dd_lock);
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: telldir.c,v 1.13 2001/12/30 19:27:42 thorpej Exp $ */
/* $NetBSD: telldir.c,v 1.14 2003/05/28 20:03:37 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@ -38,11 +38,12 @@
#if 0
static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: telldir.c,v 1.13 2001/12/30 19:27:42 thorpej Exp $");
__RCSID("$NetBSD: telldir.c,v 1.14 2003/05/28 20:03:37 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include "namespace.h"
#include "reentrant.h"
#include <sys/param.h>
#include <assert.h>
@ -90,6 +91,10 @@ telldir(dirp)
long idx;
struct ddloc *lp;
#ifdef _REENTRANT
if (__isthreaded)
mutex_lock((mutex_t *)dirp->dd_lock);
#endif
if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
return (-1);
@ -99,6 +104,10 @@ telldir(dirp)
lp->loc_loc = dirp->dd_loc;
lp->loc_next = dd_hash[LOCHASH(idx)];
dd_hash[LOCHASH(idx)] = lp;
#ifdef _REENTRANT
if (__isthreaded)
mutex_unlock((mutex_t *)dirp->dd_lock);
#endif
return (idx);
}