This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
FreeBSD port (12): wrong use of struct dirent
- From: Bruno Haible <bruno at clisp dot org>
- To: libc-alpha at sources dot redhat dot com
- Date: Wed, 10 Jul 2002 20:04:49 +0200 (CEST)
- Subject: FreeBSD port (12): wrong use of struct dirent
Hi,
For the FreeBSD port, I decided to use a 'struct dirent' with a d_name array
of length 1, similar to what is suggested by sysdeps/generic/bits/dirent.h.
According to SUSV3 basedefs/dirent.h.html, d_name[] can be of small size:
"The character array d_name is of unspecified size, but the number of bytes
preceding the terminating null byte shall not exceed {NAME_MAX}."
And according to SUSV3 functions/readdir.html
"The storage pointed to by entry shall be large enough for a dirent with an
array of char d_name members containing at least {NAME_MAX}+1 elements."
which means that it's the responsibility of the caller of readdir_r() to
provide a large enough buffer, i.e. sometimes larger than 'struct dirent'.
The glibc manual's description of readdir_r() says the same thing.
But there is one place in the code and two occurrences in the testsuite
where this rule is not followed.
2002-07-06 Bruno Haible <bruno@clisp.org>
* sysdeps/generic/glob.c: Include <limits.h>.
(NAME_MAX): Define a fallback.
(glob_in_dir): Allocate enough room for a 'struct dirent64' on the
stack.
* posix/tst-dir.c: Include <stddef.h>, for offsetof.
(main): Allocate enough room for a 'struct dirent64' on the stack.
* posix/tst-gnuglob.c (my_DIR): Allocate enough room for a
'struct dirent'.
diff -r -c3 glibc-20020627.bak/sysdeps/generic/glob.c glibc-20020627/sysdeps/generic/glob.c
--- glibc-20020627.bak/sysdeps/generic/glob.c Sat May 4 00:00:59 2002
+++ glibc-20020627/sysdeps/generic/glob.c Fri Jul 5 01:17:07 2002
@@ -191,6 +191,14 @@
#endif /* Standard headers. */
+/* NAME_MAX is usually defined in <dirent.h> or <limits.h>. */
+#if defined HAVE_LIMITS_H || defined __GNU_LIBRARY__
+# include <limits.h>
+#endif
+#ifndef NAME_MAX
+# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
+#endif
+
#ifndef ANSI_STRING
# ifndef bzero
@@ -1324,15 +1332,21 @@
size_t len;
#if defined HAVE_DIRENT64 && !defined COMPILE_GLOB64
struct dirent64 *d;
- struct dirent64 d64;
+ union
+ {
+ struct dirent64 d64;
+ char room [offsetof (struct dirent64, d_name[0])
+ + NAME_MAX + 1];
+ }
+ d64buf;
if (flags & GLOB_ALTDIRFUNC)
{
struct dirent *d32 = (*pglob->gl_readdir) (stream);
if (d32 != NULL)
{
- CONVERT_DIRENT_DIRENT64 (&d64, d32);
- d = &d64;
+ CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
+ d = &d64buf.d64;
}
else
d = NULL;
diff -r -c3 glibc-20020627.bak/posix/tst-dir.c glibc-20020627/posix/tst-dir.c
--- glibc-20020627.bak/posix/tst-dir.c Tue Jul 10 22:59:47 2001
+++ glibc-20020627/posix/tst-dir.c Fri Jul 5 01:17:06 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
#include <mcheck.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -48,7 +49,12 @@
DIR *dir2;
int result = 0;
struct dirent64 *d;
- struct dirent64 direntbuf;
+ union
+ {
+ struct dirent64 d;
+ char room [offsetof (struct dirent64, d_name[0]) + NAME_MAX + 1];
+ }
+ direntbuf;
char *objdir_copy1;
char *objdir_copy2;
char *buf;
@@ -316,7 +322,7 @@
/* Try to find the new directory. */
rewinddir (dir1);
- while (readdir64_r (dir1, &direntbuf, &d) == 0 && d != NULL)
+ while (readdir64_r (dir1, &direntbuf.d, &d) == 0 && d != NULL)
{
#ifdef _DIRENT_HAVE_D_TYPE
if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
@@ -436,7 +442,7 @@
/* We now should have a directory and a file in the new directory. */
rewinddir (dir2);
- while (readdir64_r (dir2, &direntbuf, &d) == 0 && d != NULL)
+ while (readdir64_r (dir2, &direntbuf.d, &d) == 0 && d != NULL)
{
if (strcmp (d->d_name, ".") == 0
|| strcmp (d->d_name, "..") == 0
diff -r -c3 glibc-20020627.bak/posix/tst-gnuglob.c glibc-20020627/posix/tst-gnuglob.c
--- glibc-20020627.bak/posix/tst-gnuglob.c Tue Jul 10 22:59:47 2001
+++ glibc-20020627/posix/tst-gnuglob.c Fri Jul 5 01:17:06 2002
@@ -1,6 +1,6 @@
/* Test the GNU extensions in glob which allow the user to provide callbacks
for the filesystem access functions.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -93,6 +93,7 @@
int level;
int idx;
struct dirent d;
+ char room_for_dirent[NAME_MAX];
} my_DIR;