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