NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/43310: dirent(5) standard compliance



The following reply was made to PR lib/43310; it has been noted by GNATS.

From: Jukka Ruohonen <jruohonen%iki.fi@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: lib/43310: dirent(5) standard compliance
Date: Sat, 15 May 2010 13:26:38 +0300

 Actually this appears to be more involved.
 
 The d_name is statically allocated:
 
 > struct dirent {
 >         ino_t d_fileno;                 /* file number of entry */
 >         uint16_t d_reclen;              /* length of this record */
 >         uint16_t d_namlen;              /* length of string in d_name */
 >         uint8_t  d_type;                /* file type, see below */
 > #if defined(_NETBSD_SOURCE)
 > #define MAXNAMLEN       511
 >         char    d_name[MAXNAMLEN + 1];  /* name must be no longer than this
 > #*/
 > #else
 >         char    d_name[511 + 1];        /* name must be no longer than this
 > #*/
 > #endif
 > };
 
 While the standard specifically stresses that:
 
        "The array of char d_name is not a fixed size. Implementations may
         need to declare struct dirent with an array size for d_name of 1,
         but the actual number of characters provided matches (or only
         slightly exceeds) the length of the filename."
 
 To my reading this means that some implementations may define only a pointer
 to d_name and then allocate it dynamically.
 
 Consider what the Linux manual page recommends:
 
        "Since POSIX.1 does not specify the size of the d_name field, and other
        nonstandard fields may precede that field within the dirent structure,
        portable  applications  that use readdir_r() should allocate the buffer
        whose address is passed in entry as follows:
 
            len = offsetof(struct dirent, d_name) +
                      pathconf(dirpath, _PC_NAME_MAX) + 1
            entryp = malloc(len);
 
        (POSIX.1 requires that d_name is the last field in a struct dirent.)"
 
 And indeed glibc goes and defines this as:
 
        struct linux_dirent64 {
                u64             d_ino;
                s64             d_off;
                unsigned short  d_reclen;
                unsigned char   d_type;
                char            d_name[0];
        };
 
 I do not know how severely this affects portability, but at least the
 readdir_r(3) function, where the dirent is supplied by the caller, is
 affected.
 


Home | Main Index | Thread Index | Old Index