This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
FreeBSD port (13): getdents() called with too small buffer
- From: Bruno Haible <bruno at clisp dot org>
- To: libc-alpha at sources dot redhat dot com
- Date: Wed, 10 Jul 2002 20:05:11 +0200 (CEST)
- Subject: FreeBSD port (13): getdents() called with too small buffer
Hi,
The size of the buffer that opendir() allocates for subsequent getdents()
calls depends on st_blksize of the directory. But on FreeBSD, the kernel
sets st_blksize to 0 for directories, "to catch bogus uses of this field"
(citing the kernel source comment). In this case the allocated buffer size
will be = sizeof (struct dirent), but this is too small: getdents() returns
EINVAL.
Here is a patch that handles this case like the case when there is no
st_blksize at all: size = max (sizeof (struct dirent), BUFSIZ).
On platforms other than FreeBSD, this patch can only increase the readdir()
throughput, because of the increased buffer size.
2002-07-06 Bruno Haible <bruno@clisp.org>
* sysdeps/unix/opendir.c (__opendir): If st_blksize is 0 or too small,
allocate a buffer of at least BUFSIZ bytes, not just of
sizeof (struct dirent).
diff -r -c3 glibc-20020627.bak/sysdeps/unix/opendir.c glibc-20020627/sysdeps/unix/opendir.c
--- glibc-20020627.bak/sysdeps/unix/opendir.c Tue Jul 10 23:01:18 2001
+++ glibc-20020627/sysdeps/unix/opendir.c Fri Jul 5 01:17:11 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1996,98,2000,2001 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1996,98,2000-2002 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
@@ -135,15 +135,13 @@
goto lose;
#ifdef _STATBUF_ST_BLKSIZE
- if (__builtin_expect ((size_t) statbuf.st_blksize < sizeof (struct dirent),
- 0))
- allocation = sizeof (struct dirent);
- else
+ if (__builtin_expect ((size_t) statbuf.st_blksize >= sizeof (struct dirent),
+ 1))
allocation = statbuf.st_blksize;
-#else
- allocation = (BUFSIZ < sizeof (struct dirent)
- ? sizeof (struct dirent) : BUFSIZ);
+ else
#endif
+ allocation = (BUFSIZ < sizeof (struct dirent)
+ ? sizeof (struct dirent) : BUFSIZ);
dirp = (DIR *) calloc (1, sizeof (DIR) + allocation); /* Zero-fill. */
if (dirp == NULL)