add mutex locking for directories and readdir_r(3). Influenced by FreeBSD.
This commit is contained in:
parent
cb9a14ea0b
commit
9af7135771
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user