readdir.c: d_off instead of d_reclen [PATCH]

Jeff Johnston jjohnstn@redhat.com
Fri Jun 3 19:33:00 GMT 2005


Shaun,

   The d_off field is not an offset to the next entry from the current entry; it 
is instead from the start of the directory: "d_off is the distance from the 
start of the directory to the start of the next dirent."  I have seen a 
different definition of this field being the current directory entry as 
illustrated below:

   Is there a problem you are solving with this change whereby the d_reclen 
field calculation did not give you a correct entry and if so, what system?

-- Jeff J.

DIRENT(4)                                                         DIRENT(4)
                              Standard Extension



  NAME
       dirent - file system independent directory entry

  SYNOPSIS
       #include <sys/types.h>
       #include <sys/dirent.h>

  DESCRIPTION
       Different file system types may have different directory entries.  The
       dirent structure defines a file system independent directory entry,
       which contains information common to directory entries in different
       file system types.  A set of these structures is returned by the
       getdents(2) system call.

       The dirent structure is defined below.
       struct    dirent    {
                      long           d_ino;
                      off_t               d_off;
                      unsigned short      d_reclen;
                      char           d_name[1];
                 };

       The field d_ino is a number which is unique for each file in the file
       system.  The field d_off represents an offset of that directory entry
       in the actual file system directory.  The field d_name is the
       beginning of the character array giving the name of the directory
       entry.  This name is null terminated and may have at most NAME_MAX
       characters in addition to the null terminator.  This results in file
       system independent directory entries being variable-length entities.
       The value of d_reclen is the record length of this entry.  This length
       is defined to be the number of bytes between the beginning of the
       current entry and the next one, adjusted so that the next entry will
       start on a long boundary.

  FILES
       /usr/include/sys/dirent.h

  SEE ALSO
       getdents(2).

  WARNING
       The field d_off does not have a simple interpretation for some file
       system types and should not be used directly by applications.



Shaun Jackman wrote:
> The getdents(2) manual page indicates d_off should be used as the
> offset to the next dirent.
> 
> Cheers,
> Shaun
> 
> 2005-06-03  Shaun Jackman  <sjackman@gmail.com>
> 
> 	* newlib/libc/posix/readdir.c (readdir): Use d_off as the offset
> 	to the next dirent instead of d_reclen.
> 	* newlib/libc/posix/readdir_r.c (readdir_r): Ditto.
> 
> --- newlib/libc/posix/readdir.c-	2005-06-03 11:21:42.000000000 -0700
> +++ newlib/libc/posix/readdir.c	2005-06-03 11:25:09.000000000 -0700
> @@ -81,14 +81,14 @@
>   #endif
>        return NULL;
>      }
> -    if (dp->d_reclen <= 0 ||
> +    if (dp->d_reclen <= 0 || dp->d_off <= 0 ||
>   	dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) {
>   #ifdef HAVE_DD_LOCK
>        __lock_release_recursive(dirp->dd_lock);
>   #endif
>        return NULL;
>      }
> -    dirp->dd_loc += dp->d_reclen;
> +    dirp->dd_loc += dp->d_off;
>      if (dp->d_ino == 0)
>        continue;
>   #ifdef HAVE_DD_LOCK
> --- newlib/libc/posix/readdir_r.c-	2003-06-06 12:57:51.000000000 -0700
> +++ newlib/libc/posix/readdir_r.c	2005-06-03 11:25:05.000000000 -0700
> @@ -86,7 +86,7 @@
>      tmpdp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
>      memcpy (dp, tmpdp, sizeof(struct dirent));
>  
> -    if (dp->d_reclen <= 0 ||
> +    if (dp->d_reclen <= 0 || dp->d_off <= 0 ||
>   	dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) {
>   #ifdef HAVE_DD_LOCK
>        __lock_release_recursive(dirp->dd_lock);
> @@ -94,7 +94,7 @@
>        *dpp = NULL;
>        return -1;
>      }
> -    dirp->dd_loc += dp->d_reclen;
> +    dirp->dd_loc += dp->d_off;
>      if (dp->d_ino == 0)
>        continue;
>   #ifdef HAVE_DD_LOCK



More information about the Newlib mailing list