summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog64
-rw-r--r--stdlib/mbstowcs.c2
-rw-r--r--stdlib/wcstombs.c2
-rw-r--r--sysdeps/gnu/errlist.c147
-rw-r--r--sysdeps/mach/hurd/closedir.c20
-rw-r--r--sysdeps/mach/hurd/dirstream.h5
-rw-r--r--sysdeps/mach/hurd/opendir.c6
-rw-r--r--sysdeps/mach/hurd/readdir.c19
-rw-r--r--sysdeps/mach/hurd/seekdir.c4
-rw-r--r--sysdeps/mach/libc-lock.h60
-rw-r--r--sysdeps/stub/libc-lock.h10
-rw-r--r--sysdeps/unix/bsd/telldir.c30
-rw-r--r--sysdeps/unix/closedir.c6
-rw-r--r--sysdeps/unix/dirstream.h4
-rw-r--r--sysdeps/unix/opendir.c3
-rw-r--r--sysdeps/unix/readdir.c9
-rw-r--r--sysdeps/unix/rewinddir.c2
-rw-r--r--sysdeps/unix/seekdir.c2
18 files changed, 371 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index e21f365e1f..a619747dbf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,67 @@
+Tue Jul 9 09:37:55 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+
+ * sysdeps/mach/libc-lock.h: New file.
+ * sysdeps/unix/readdir.c: Do locking.
+ * sysdeps/unix/seekdir.c: Likewise.
+ * sysdeps/unix/rewinddir.c: Likewise.
+ * sysdeps/unix/closedir.c: Likewise.
+ * sysdeps/unix/bsd/telldir.c: Likewise.
+ * sysdeps/mach/hurd/seekdir.c: Likewise.
+ * sysdeps/mach/hurd/readdir.c: Likewise.
+ * sysdeps/mach/hurd/closedir.c: Likewise.
+ * sysdeps/mach/hurd/opendir.c: Initialize the lock.
+ * sysdeps/unix/opendir.c: Likewise.
+ * sysdeps/mach/hurd/dirstream.h: Include <libc-lock.h>.
+ (struct __dirstream): Add lock member using __libc_lock_define.
+ * sysdeps/unix/dirstream.h: Likewise.
+
+ * sysdeps/stub/libc-lock.h (__libc_lock_fini): New macro.
+
+ * stdlib/mbstowcs.c: Pass address of pointer to mbsrtowcs.
+
+ * stdlib/wcstombs.c: Use wcsrtombs instead of mbsrtowcs.
+
+Thu Jul 4 01:34:04 1996 Ulrich Drepper <drepper@cygnus.com>
+
+ * locale/programs/stringtrans.c: Fix typo in copyright.
+
+ * stdio-common/printf-prs.c: Add casts to prevent
+ signed<->unsigned warnings.
+
+ * stdio-common/printf-parse.h: Initialize state variable before
+ calling mbrlen.
+ * stdio-common/printf-prs.c: Don't initialize state variable here.
+ * stdio-common/vfprintf.c: Don't initialize state variable.
+ (vfprintf): While determining length of multibyte string don't
+ try to be clever in determining characters to use for first
+ call.
+
+ Add real implementation of multibyte<->wide char conversion
+ functions. The functions always convert between the fixed wide
+ char format (ISO 10646 in UCS4) and the UTF8 representation of
+ this character set. Conversion between the currently used
+ 8bit character set and ISO 10646 will not take place. This is
+ what iconv() is for.
+ * wcsmbs/wchar.h (mbstate_t): Define as structure to replace
+ dummy definition.
+ Add optimized version of `mbrlen' function.
+ * wcsmbs/btowc.c (btowc): Restrict range of legal characters
+ to 0...0x7f.
+ * wcsmbs/wctob.c (wctob): Restrict range of legal characters
+ to 0..0x7f.
+ * wcsmbs/mbrlen.c: Make mbrlen a weak alias of __mbrlen.
+ This is needed in the wchar.h header.
+ * wcsmbs/mbrtowc.c: Replace dummy implementation. Convert UTF8
+ encoded character to UCS4.
+ * wcsmbs/mbsinit.c: Replace dummy implementation. Test COUNT
+ element of `mbstate_t' for initial state.
+ * wcsmbs/mbsrtowcs.c: Replace dummy implementation. Convert UTF8
+ encoded string to UCS4 string.
+ * wcsmbs/wcrtomb.c: Replace dummy implementation. Convert UCS4
+ character to UTF8 encoded form.
+ * wcsmbs/wcsrtombs.c: Replace dummy implementation. Convert UCS4
+ encoded string to UTF8 encoded form.
+
Tue Jul 9 06:19:29 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* sysdeps/unix/sysv/linux/configure.in: Use version number in cache
diff --git a/stdlib/mbstowcs.c b/stdlib/mbstowcs.c
index 8eda3ba41d..da3ae6b19d 100644
--- a/stdlib/mbstowcs.c
+++ b/stdlib/mbstowcs.c
@@ -36,7 +36,7 @@ mbstowcs (wchar_t *pwcs, const char *s, size_t n)
mbstate_t save_shift = __no_r_state;
size_t written;
- written = mbsrtowcs (pwcs, s, n, &__no_r_state);
+ written = mbsrtowcs (pwcs, &s, n, &__no_r_state);
/* Restore the old shift state. */
__no_r_state = save_shift;
diff --git a/stdlib/wcstombs.c b/stdlib/wcstombs.c
index 6518308181..73f015bf7e 100644
--- a/stdlib/wcstombs.c
+++ b/stdlib/wcstombs.c
@@ -36,7 +36,7 @@ wcstombs (char *s, const wchar_t *pwcs, size_t n)
mbstate_t save_shift = __no_r_state;
size_t written;
- written = mbsrtowcs (pwcs, s, n, &__no_r_state);
+ written = wcsrtombs (s, &pwcs, n, &__no_r_state);
/* Restore the old shift state. */
__no_r_state = save_shift;
diff --git a/sysdeps/gnu/errlist.c b/sysdeps/gnu/errlist.c
index dd2593bdc7..fa56553712 100644
--- a/sysdeps/gnu/errlist.c
+++ b/sysdeps/gnu/errlist.c
@@ -110,6 +110,9 @@ const char *_sys_errlist[] =
#ifdef EAGAIN
[EAGAIN] = N_("Resource temporarily unavailable"),
#endif
+#if defined (EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ [EWOULDBLOCK] = N_("Operation would block"),
+#endif
#ifdef EINPROGRESS
[EINPROGRESS] = N_("Operation now in progress"),
#endif
@@ -269,6 +272,150 @@ const char *_sys_errlist[] =
#ifdef EGRATUITOUS
[EGRATUITOUS] = N_("Gratuitous error"),
#endif
+#ifdef ERESTART
+ [ERESTART] = N_("Interrupted system call should be restarted"),
+#endif
+#ifdef ENOMSG
+ [ENOMSG] = N_("No message of desired type"),
+#endif
+#ifdef EIDRM
+ [EIDRM] = N_("Identifier removed"),
+#endif
+#ifdef ECHRNG
+ [ECHRNG] = N_("Channel number out of range"),
+#endif
+#ifdef EL2NSYNC
+ [EL2NSYNC] = N_("Level 2 not synchronized"),
+#endif
+#ifdef EL3HLT
+ [EL3HLT] = N_("Level 3 halted"),
+#endif
+#ifdef EL3RST
+ [EL3RST] = N_("Level 3 reset"),
+#endif
+#ifdef ELNRNG
+ [ELNRNG] = N_("Link number out of range"),
+#endif
+#ifdef EUNATCH
+ [EUNATCH] = N_("Protocol driver not attached"),
+#endif
+#ifdef ENOCSI
+ [ENOCSI] = N_("No CSI structure available"),
+#endif
+#ifdef EL2HLT
+ [EL2HLT] = N_("Level 2 halted"),
+#endif
+#ifdef EBADE
+ [EBADE] = N_("Invalid exchange"),
+#endif
+#ifdef EBADR
+ [EBADR] = N_("Invalid request descriptor"),
+#endif
+#ifdef EXFULL
+ [EXFULL] = N_("Exchange full"),
+#endif
+#ifdef ENOANO
+ [ENOANO] = N_("No anode"),
+#endif
+#ifdef EBADRQC
+ [EBADRQC] = N_("Invalid request code"),
+#endif
+#ifdef EBADSLT
+ [EBADSLT] = N_("Invalid slot"),
+#endif
+#if defined (EDEADLOCK) && EDEADLOCK != EDEADLK
+ [EDEADLOCK] = N_("File locking deadlock error"),
+#endif
+#ifdef EBFONT
+ [EBFONT] = N_("Bad font file format"),
+#endif
+#ifdef ENOSTR
+ [ENOSTR] = N_("Device not a stream"),
+#endif
+#ifdef ENODATA
+ [ENODATA] = N_("No data available"),
+#endif
+#ifdef ETIME
+ [ETIME] = N_("Timer expired"),
+#endif
+#ifdef ENOSR
+ [ENOSR] = N_("Out of streams resources"),
+#endif
+#ifdef ENONET
+ [ENONET] = N_("Machine is not on the network"),
+#endif
+#ifdef ENOPKG
+ [ENOPKG] = N_("Package not installed"),
+#endif
+#ifdef ENOLINK
+ [ENOLINK] = N_("Link has been severed"),
+#endif
+#ifdef EADV
+ [EADV] = N_("Advertise error"),
+#endif
+#ifdef ESRMNT
+ [ESRMNT] = N_("Srmount error"),
+#endif
+#ifdef ECOMM
+ [ECOMM] = N_("Communication error on send"),
+#endif
+#ifdef EPROTO
+ [EPROTO] = N_("Protocol error"),
+#endif
+#ifdef EMULTIHOP
+ [EMULTIHOP] = N_("Multihop attempted"),
+#endif
+#ifdef EDOTDOT
+ [EDOTDOT] = N_("RFS specific error"),
+#endif
+#ifdef EBADMSG
+ [EBADMSG] = N_("Not a data message"),
+#endif
+#ifdef EOVERFLOW
+ [EOVERFLOW] = N_("Value too large for defined data type"),
+#endif
+#ifdef ENOTUNIQ
+ [ENOTUNIQ] = N_("Name not unique on network"),
+#endif
+#ifdef EBADFD
+ [EBADFD] = N_("File descriptor in bad state"),
+#endif
+#ifdef EREMCHG
+ [EREMCHG] = N_("Remote address changed"),
+#endif
+#ifdef ELIBACC
+ [ELIBACC] = N_("Can not access a needed shared library"),
+#endif
+#ifdef ELIBBAD
+ [ELIBBAD] = N_("Accessing a corrupted shared library"),
+#endif
+#ifdef ELIBSCN
+ [ELIBSCN] = N_(".lib section in a.out corrupted"),
+#endif
+#ifdef ELIBMAX
+ [ELIBMAX] = N_("Attempting to link in too many shared libraries"),
+#endif
+#ifdef ELIBEXEC
+ [ELIBEXEC] = N_("Cannot exec a shared library directly"),
+#endif
+#ifdef ESTRPIPE
+ [ESTRPIPE] = N_("Streams pipe error"),
+#endif
+#ifdef EUCLEAN
+ [EUCLEAN] = N_("Structure needs cleaning"),
+#endif
+#ifdef ENOTNAM
+ [ENOTNAM] = N_("Not a XENIX named type file"),
+#endif
+#ifdef ENAVAIL
+ [ENAVAIL] = N_("No XENIX semaphores available"),
+#endif
+#ifdef EISNAM
+ [EISNAM] = N_("Is a named type file"),
+#endif
+#ifdef EREMOTEIO
+ [EREMOTEIO] = N_("Remote I/O error"),
+#endif
};
const int _sys_nerr = sizeof _sys_errlist / sizeof _sys_errlist[0];
diff --git a/sysdeps/mach/hurd/closedir.c b/sysdeps/mach/hurd/closedir.c
index 521787d02d..4c62783584 100644
--- a/sysdeps/mach/hurd/closedir.c
+++ b/sysdeps/mach/hurd/closedir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -39,14 +39,22 @@ DEFUN(closedir, (dirp), DIR *dirp)
return -1;
}
- if (err = __vm_deallocate (__mach_task_self (),
- (vm_address_t) dirp->__data, dirp->__allocation))
- return __hurd_fail (err);
+ __libc_lock_lock (dirp->__lock);
+ err = __vm_deallocate (__mach_task_self (),
+ (vm_address_t) dirp->__data, dirp->__allocation);
dirp->__data = NULL;
+ err = _hurd_fd_close (dirp->__fd);
- if (err = _hurd_fd_close (dirp->__fd))
- return __hurd_fail (err);
+ if (err)
+ {
+ /* Unlock the DIR. A failing closedir can be repeated (and may fail
+ again, but shouldn't deadlock). */
+ __libc_lock_unlock (dirp->__lock);
+ return __hurd_fail (err);
+ }
+ /* Clean up the lock and free the structure. */
+ __libc_lock_fini (dirp->__lock);
free (dirp);
return 0;
diff --git a/sysdeps/mach/hurd/dirstream.h b/sysdeps/mach/hurd/dirstream.h
index a8c5fd12cb..d17baf2b03 100644
--- a/sysdeps/mach/hurd/dirstream.h
+++ b/sysdeps/mach/hurd/dirstream.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,6 +20,8 @@ Cambridge, MA 02139, USA. */
#define _DIRSTREAM_H 1
+#include <libc-lock.h>
+
/* Directory stream type.
The Hurd directory format is the same as `struct dirent', so `readdir'
@@ -34,6 +36,7 @@ struct __dirstream
int __entry_ptr; /* Entry number `__ptr' corresponds to. */
unsigned long int __allocation; /* Space allocated for the block. */
unsigned long int __size; /* Total valid data in the block. */
+ __libc_lock_define (, __lock); /* Mutex lock for this structure. */
};
#endif /* dirstream.h */
diff --git a/sysdeps/mach/hurd/opendir.c b/sysdeps/mach/hurd/opendir.c
index 8ab964a11d..bab84d52f0 100644
--- a/sysdeps/mach/hurd/opendir.c
+++ b/sysdeps/mach/hurd/opendir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -49,7 +49,7 @@ DEFUN(opendir, (name), CONST char *name)
{
__close (fd);
return NULL;
- }
+ }
/* Extract the pointer to the descriptor structure. */
__mutex_lock (&_hurd_dtable_lock);
@@ -66,5 +66,7 @@ DEFUN(opendir, (name), CONST char *name)
dirp->__allocation = 0;
dirp->__size = 0;
+ __libc_lock_init (dirp->__lock);
+
return dirp;
}
diff --git a/sysdeps/mach/hurd/readdir.c b/sysdeps/mach/hurd/readdir.c
index 3c17d248e1..715f9278a2 100644
--- a/sysdeps/mach/hurd/readdir.c
+++ b/sysdeps/mach/hurd/readdir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -41,6 +41,8 @@ DEFUN(readdir, (dirp), DIR *dirp)
return NULL;
}
+ __libc_lock_lock (dirp->__lock);
+
do
{
if (dirp->__ptr - dirp->__data >= dirp->__size)
@@ -56,7 +58,11 @@ DEFUN(readdir, (dirp), DIR *dirp)
&data, &dirp->__size,
dirp->__entry_ptr,
-1, 0, &nentries)))
- return __hurd_fail (err), NULL;
+ {
+ __hurd_fail (err);
+ dp = NULL;
+ break;
+ }
/* DATA now corresponds to entry index DIRP->__entry_ptr. */
dirp->__entry_data = dirp->__entry_ptr;
@@ -77,8 +83,11 @@ DEFUN(readdir, (dirp), DIR *dirp)
dirp->__ptr = dirp->__data;
if (nentries == 0)
- /* End of file. */
- return NULL;
+ {
+ /* End of file. */
+ dp = NULL;
+ break;
+ }
/* We trust the filesystem to return correct data and so we
ignore NENTRIES. */
@@ -91,5 +100,7 @@ DEFUN(readdir, (dirp), DIR *dirp)
/* Loop to ignore deleted files. */
} while (dp->d_fileno == 0);
+ __libc_lock_unlock (dirp->__lock);
+
return dp;
}
diff --git a/sysdeps/mach/hurd/seekdir.c b/sysdeps/mach/hurd/seekdir.c
index fa4f1f4f52..a44ac7d246 100644
--- a/sysdeps/mach/hurd/seekdir.c
+++ b/sysdeps/mach/hurd/seekdir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,10 +27,12 @@ Cambridge, MA 02139, USA. */
void
DEFUN(seekdir, (dirp, pos), DIR *dirp AND __off_t pos)
{
+ __libc_lock_lock (dirp->__lock);
/* Change our entry index pointer to POS and discard any data already
read. The next `readdir' call will notice the empty block and read
anew from the location in DIRP->__entry_ptr and reset the other state
variables. */
dirp->__entry_ptr = pos;
dirp->__size = 0;
+ __libc_lock_unlock (dirp->__lock);
}
diff --git a/sysdeps/mach/libc-lock.h b/sysdeps/mach/libc-lock.h
new file mode 100644
index 0000000000..0639fc6b22
--- /dev/null
+++ b/sysdeps/mach/libc-lock.h
@@ -0,0 +1,60 @@
+/* libc-internal interface for mutex locks. Mach cthreads version.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _LIBC_LOCK_H
+#define _LIBC_LOCK_H 1
+
+#ifdef _LIBC
+#include <cthreads.h>
+#define __libc_lock_t struct mutex
+#else
+typedef struct __libc_lock_opaque__ __libc_lock_t;
+#endif
+
+/* Define a lock variable NAME with storage class CLASS. The lock must be
+ initialized with __libc_lock_init before it can be used (or define it
+ with __libc_lock_define_initialized, below). Use `extern' for CLASS to
+ declare a lock defined in another module. In public structure
+ definitions, the lock element must come last, because its storage size
+ will not be known outside of libc. (Or you can use a pointer to the
+ lock structure; i.e. NAME begins with a `*'.) */
+#define __libc_lock_define(CLASS,NAME)
+ CLASS __libc_lock_t NAME;
+
+/* Define an initialized lock variable NAME with storage class CLASS. */
+#define __libc_lock_define_initialized(CLASS,NAME) \
+ CLASS __libc_lock_t NAME = MUTEX_INITIALIZER;
+
+/* Initialize the named lock variable, leaving it in a consistent, unlocked
+ state. */
+#define __libc_lock_init(NAME) __mutex_init (&(NAME))
+
+/* Finalize the named lock variable, which must be locked. It cannot be
+ used again until __libc_lock_init is called again on it. This must be
+ called on a lock variable before the containing storage is reused. */
+#define __libc_lock_fini(NAME) __mutex_unlock (&(NAME))
+
+/* Lock the named lock variable. */
+#define __libc_lock_lock(NAME) __mutex_lock (&(NAME))
+
+/* Unlock the named lock variable. */
+#define __libc_lock_unlock(NAME) __mutex_unlock (&(NAME))
+
+
+#endif /* libc-lock.h */
diff --git a/sysdeps/stub/libc-lock.h b/sysdeps/stub/libc-lock.h
index ce6cab0f3f..a8608df791 100644
--- a/sysdeps/stub/libc-lock.h
+++ b/sysdeps/stub/libc-lock.h
@@ -24,7 +24,10 @@ Cambridge, MA 02139, USA. */
/* Define a lock variable NAME with storage class CLASS. The lock must be
initialized with __libc_lock_init before it can be used (or define it
with __libc_lock_define_initialized, below). Use `extern' for CLASS to
- declare a lock defined in another module. */
+ declare a lock defined in another module. In public structure
+ definitions, the lock element must come last, because its storage size
+ will not be known outside of libc. (Or you can use a pointer to the
+ lock structure; i.e. NAME begins with a `*'.) */
#define __libc_lock_define(CLASS,NAME)
/* Define an initialized lock variable NAME with storage class CLASS. */
@@ -34,6 +37,11 @@ Cambridge, MA 02139, USA. */
state. */
#define __libc_lock_init(NAME)
+/* Finalize the named lock variable, which must be locked. It cannot be
+ used again until __libc_lock_init is called again on it. This must be
+ called on a lock variable before the containing storage is reused. */
+#define __libc_lock_fini(NAME)
+
/* Lock the named lock variable. */
#define __libc_lock_lock(NAME)
diff --git a/sysdeps/unix/bsd/telldir.c b/sysdeps/unix/bsd/telldir.c
index 06580937e4..4400883357 100644
--- a/sysdeps/unix/bsd/telldir.c
+++ b/sysdeps/unix/bsd/telldir.c
@@ -36,6 +36,7 @@ struct record
#define NBUCKETS 32
static struct record *records[32];
static off_t lastpos;
+__libc_lock_define_initialized(static, lock); /* Locks above data. */
/* Return the current position of DIRP. */
@@ -43,6 +44,9 @@ off_t
DEFUN(telldir, (dirp), DIR *dirp)
{
struct record *new;
+ off_t pos;
+
+ __libc_lock_lock (lock);
new = malloc (sizeof *new);
if (new == NULL)
@@ -54,7 +58,11 @@ DEFUN(telldir, (dirp), DIR *dirp)
new->next = records[new->cookie % NBUCKETS];
records[new->cookie % NBUCKETS] = new;
- return new->cookie;
+ pos = new->cookie;
+
+ __libc_lock_unlock (lock);
+
+ return pos;
}
@@ -65,11 +73,14 @@ DEFUN(seekdir, (dirp, pos), DIR *dirp AND __off_t pos)
{
struct record *r, **prevr;
+ __libc_lock_lock (lock);
+
for (prevr = &records[pos % NBUCKETS], r = *prevr;
r != NULL;
prevr = &r->next, r = r->next)
if (r->cookie == pos)
{
+ __libc_lock_lock (dirp->__lock);
if (dirp->filepos != r->pos || dirp->offset != r->offset)
{
dirp->size = 0; /* Must read a fresh buffer. */
@@ -79,16 +90,25 @@ DEFUN(seekdir, (dirp, pos), DIR *dirp AND __off_t pos)
dirp->offset = 0;
/* Read entries until we reach the saved offset. */
while (dirp->offset < r->offset)
- if (readdir (dirp) == NULL)
- break;
+ {
+ struct dirent *scan;
+ __libc_lock_unlock (dirp->__lock);
+ scan = readdir (dirp);
+ __libc_lock_lock (dirp->__lock);
+ if (! scan)
+ break;
+ }
}
+ __libc_lock_unlock (dirp->__lock);
/* To prevent leaking memory, cookies returned from telldir
can only be used once. So free this one's record now. */
*prevr = r->next;
free (r);
- return;
+ break;
}
- /* We lost, but have no way to indicate it. Oh well. */
+ __libc_lock_unlock (lock);
+
+ /* If we lost there is no way to indicate it. Oh well. */
}
diff --git a/sysdeps/unix/closedir.c b/sysdeps/unix/closedir.c
index 791eaad250..1d4fd8eef0 100644
--- a/sysdeps/unix/closedir.c
+++ b/sysdeps/unix/closedir.c
@@ -37,9 +37,13 @@ DEFUN(closedir, (dirp), DIR *dirp)
return -1;
}
- fd = dirp->fd;
+ __libc_lock_lock (dirp->lock);
+ fd = dirp->fd;
free ((PTR) dirp->data);
+
+ __libc_lock_fini (dirp->lock);
+
free ((PTR) dirp);
return __close (fd);
diff --git a/sysdeps/unix/dirstream.h b/sysdeps/unix/dirstream.h
index 87e78b61ad..3d2796778a 100644
--- a/sysdeps/unix/dirstream.h
+++ b/sysdeps/unix/dirstream.h
@@ -22,6 +22,8 @@ Cambridge, MA 02139, USA. */
#include <sys/types.h>
+#include <libc-lock.h>
+
/* Directory stream type.
The miscellaneous Unix `readdir' implementations read directory data
@@ -37,6 +39,8 @@ struct __dirstream
size_t offset; /* Current offset into the block. */
off_t filepos; /* Position of next entry to read. */
+
+ __libc_lock_define (, lock); /* Mutex lock for this structure. */
};
#define _DIR_dirfd(dirp) ((dirp)->fd)
diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c
index df20b9c131..8dca80b3ae 100644
--- a/sysdeps/unix/opendir.c
+++ b/sysdeps/unix/opendir.c
@@ -90,5 +90,8 @@ opendir (const char *name)
}
dirp->fd = fd;
+
+ __libc_lock_init (dirp->lock);
+
return dirp;
}
diff --git a/sysdeps/unix/readdir.c b/sysdeps/unix/readdir.c
index 00446a2d2b..5d0c40fdc1 100644
--- a/sysdeps/unix/readdir.c
+++ b/sysdeps/unix/readdir.c
@@ -40,6 +40,8 @@ readdir (DIR *dirp)
return NULL;
}
+ __libc_lock_lock (dirp->lock);
+
do
{
size_t reclen;
@@ -62,7 +64,10 @@ readdir (DIR *dirp)
base = dirp->filepos;
bytes = __getdirentries (dirp->fd, dirp->data, maxread, &base);
if (bytes <= 0)
- return NULL;
+ {
+ dp = NULL;
+ break;
+ }
dirp->size = (size_t) bytes;
/* Reset the offset into the buffer. */
@@ -96,5 +101,7 @@ readdir (DIR *dirp)
/* Skip deleted files. */
} while (dp->d_ino == 0);
+ __libc_lock_unlock (dirp->lock);
+
return dp;
}
diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
index 791ecc1a4b..3a91b06f4a 100644
--- a/sysdeps/unix/rewinddir.c
+++ b/sysdeps/unix/rewinddir.c
@@ -27,7 +27,9 @@ Cambridge, MA 02139, USA. */
void
DEFUN(rewinddir, (dirp), DIR *dirp)
{
+ __libc_lock_lock (dirp->lock);
(void) lseek(dirp->fd, (off_t) 0, SEEK_SET);
dirp->offset = 0;
dirp->size = 0;
+ __libc_lock_unlock (dirp->lock);
}
diff --git a/sysdeps/unix/seekdir.c b/sysdeps/unix/seekdir.c
index 9ce332b400..b1201f6b6c 100644
--- a/sysdeps/unix/seekdir.c
+++ b/sysdeps/unix/seekdir.c
@@ -27,7 +27,9 @@ Cambridge, MA 02139, USA. */
void
DEFUN(seekdir, (dirp, pos), DIR *dirp AND __off_t pos)
{
+ __libc_lock_lock (dirp->lock);
(void) __lseek(dirp->fd, pos, SEEK_SET);
dirp->size = 0;
dirp->offset = 0;
+ __libc_lock_unlock (dirp->lock);
}