Bug 70925

Summary: The getdents(2) page has multiple problems
Product: [Retired] Red Hat Linux Reporter: Need Real Name <rocombs>
Component: man-pagesAssignee: Eido Inoue <havill>
Status: CLOSED UPSTREAM QA Contact: Ben Levenson <benl>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.2   
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-08-20 19:35:14 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Need Real Name 2002-08-06 22:55:30 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.78 [en] (X11; U; Linux 2.4.17 i686)

Description of problem:
The described structure and prototype do not match the kernel, the include list
is incorrect, the 64bit call and structure are not documented, and the comment
for the offset field is incorrect.

Also, the array length is incorrect (the page should probably mention that this
field is actually dynamic), the fact that the offset is only a cookie is not
mentioned.



Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1. read manpage
2. try to use the information
3. end up reading kernel source and searching google for better info
	

Actual Results:  See below.

Expected Results:  See below.

Additional info:

Bug 1:

getdents(2) should describe the kernel system call interface.
The types do not match the kernel version in signedness.

/* from Linux 2.4.18 */
struct linux_dirent {
    unsigned long   d_ino;   /* inode number */
    unsigned long   d_off;   /* offset from the start of the directory */
    unsigned short  d_reclen; /* length of this record */
    char            d_name[1]; /* filename with null-termination, length is
variable */
};


Bug 2:

The d_off field is misdocumented as being the offset to the next directory entry
in the current manpage.


Bug 3:

The name field is misdocumented as being limited to NAME_MAX+1 chars in the
current manpage.  That bug has a sub-bug which is that there should be no +1
since NAME_MAX should already include room for the NUL termination.


Bug 4:

The return type should be "long" instead of "int".
The syscall prototype from 2.4.18:

long sys_getdents(unsigned int fd, void * dirent, unsigned int count);
(You can substitute "struct dirent" in place of "void".)


Bug 5:

getdents64() is not documented nor is the structure.

struct linux_dirent64 {
    __u64           d_ino;     /* inode number */
    __s64           d_off;     /* offset from start of directory */
    unsigned short  d_reclen;  /* length of this record */
    unsigned char   d_type;    /* hint for type of inode (file,directory,etc.)
*/
    char            d_name[0]; /* filename including null-termination, variable
length */
}

Bug 6:

The manpage should describe how to use the function.

The first thing to note is that one needs to allocate more space than
given by struct dirent so that the kernel can fill in the file name.

The second thing to note is that the return value does not give
enough information to tell how many structures have been read
without counting the d_reclen fields.  It should also mention that
the C library may have its own version of struct dirent which may
conflict with the kernel version.

The third thing to note is that the d_off field should not be treated
as an offset in bytes (though it usually is) but as a cookie.  This
means doing to math on it.  It may only be fed to lseek(64) as-is.
This is especially important on non-POSIX filesystems like NFS.


Bug 7:

The list of includes is not correct.  Including unistd.h may conflict
with kernel headers (mixing glibc and kernel headers is usually a
bad idea).  The man page should probably warn against including
unistd.h or sys/types.h from the C library since they also define a
different struct dirent.

The only headers which need to be included are:

#include <linux/unistd.h>
#include <linux/types.h>

There is a linux/dirent.h header with what seem to be kernel
structures, but they limit filenames to 256 characters.
However, neither of those will define the kernel getdents structure.
The manpage should make it clear that you will need to define it
yourself.



Summary:

This man page has several factual problems and several omissions.
If you would rather I report this bug directly to the LDP then I
would be glad to do so.  Please CC me on any updates or information
requests.

Comment 1 Trond Eivind Glomsrxd 2002-08-09 16:23:29 UTC
The best place to submit this is the man-page author, aeb