This is the mail archive of the
libc-alpha@cygnus.com
mailing list for the glibc project.
[Jamie Lokier <jamie.lokier@cern.ch>] libc/1068: [glibc] Possible erroneous return code from Linux __getdirentries
- To: libc-alpha@cygnus.com
- Subject: [Jamie Lokier <jamie.lokier@cern.ch>] libc/1068: [glibc] Possible erroneous return code from Linux __getdirentries
- From: Andreas Jaeger <aj@arthur.rhein-neckar.de>
- Date: 07 Apr 1999 13:32:48 +0200
- Cc: Jamie Lokier <jamie.lokier@cern.ch>
- Mail-Copies-To: never
We've received the appended bug report about a problem with
getdirentries.
The linux man page states:
RETURN VALUE
getdirentries returns the number of bytes read or zero
when at the end of the directory. If an error occurs, -1
is returned, and errno is set appropriately.
and <dirent.h> has:
/* Read directory entries from FD into BUF, reading at most NBYTES.
Reading starts at offset *BASEP, and *BASEP is updated with the new
position after reading. Returns the number of bytes read; zero when at
end of directory; or -1 for errors. */
We could (as my appended patch does) directly return the -1 from
getdents for errors. Is this the right semantic?
Andreas
1999-04-07 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* sysdeps/unix/sysv/linux/getdents.c (__getdirentries): Return
directly if getdents returns with error set.
--- sysdeps/unix/sysv/linux/getdents.c.~1~ Thu Oct 22 07:37:46 1998
+++ sysdeps/unix/sysv/linux/getdents.c Wed Apr 7 13:29:55 1999
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 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
@@ -82,6 +82,9 @@
retval = INLINE_SYSCALL (getdents, 3, fd, (char *) kdp, red_nbytes);
+ if (retval == -1)
+ return -1;
+
while ((char *) kdp < (char *) skdp + retval)
{
const size_t alignment = __alignof__ (struct dirent);
- To: bugs@gnu.org
- Subject: libc/1068: [glibc] Possible erroneous return code from Linux __getdirentries
- From: Jamie Lokier <jamie.lokier@cern.ch>
- Date: Wed, 7 Apr 1999 05:32:54 +0200
- Xref: arthur.rhein-neckar.de mail.gnats-libc-bugs:2925
>Number: 1068
>Category: libc
>Synopsis: Possible erroneous return code from Linux __getdirentries
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: libc-gnats
>State: open
>Class: sw-bug
>Submitter-Id: unknown
>Arrival-Date: Tue Apr 06 23:40:02 EDT 1999
>Last-Modified:
>Originator: Jamie Lokier
>Organization:
CERN, Geneva
>Release: libc-2.1.1
>Environment:
Host type: i386-redhat-linux-gnu
System: Linux pcep-jamie 2.2.5 #9 Wed Mar 31 18:35:38 CEST 1999 i686 unknown
Architecture: i686
Addons: crypt glibc-compat linuxthreads
Build CFLAGS: -O3 -Wall -Winline -Wstrict-prototypes -Wwrite-strings -g
Build CC: egcs
Compiler version: egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
Kernel headers: 2.2.5
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: yes
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio
>Description:
(On Linux).
When __getdirentries is called with a buffer that is too small
for even one directory entry, it correctly sets errno to EINVAL.
However it then returns 0, which is the same as it returns when
there are no more directory entries to read.
As luck would have it, the code happens to do this even though
the getdents system call, which it calls, returns -1. It is the
system call that sets errno.
>How-To-Repeat:
Call __getdirentries with a very small buffer size, for example 1.
Or ltrace a program reading a directory with an obscenely large
name in it. See the zero return value.
>Fix:
The workaround for an application is to set errno to zero first,
and check it afterwards if __getdirentries returns zero.
But perhaps __getdirentries should be returning -1 in this case,
like the getdents system call it uses?
I'm not entirely sure this is required. __getdirentries is not
very well documented (only in the <dirent.h> header, not the
manual). And other targets, for example BSD, simply call __read
to implement __getdirentries. For all I know, _those_ calls
may return zero when there isn't room.
>Audit-Trail:
>Unformatted:
--
Andreas Jaeger aj@arthur.rhein-neckar.de jaeger@informatik.uni-kl.de
for pgp-key finger ajaeger@aixd1.rhrk.uni-kl.de