This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
Re: readdir.c: d_off instead of d_reclen [PATCH]
- From: Jeff Johnston <jjohnstn at redhat dot com>
- To: Shaun Jackman <sjackman at gmail dot com>
- Cc: newlib at sources dot redhat dot com
- Date: Fri, 03 Jun 2005 15:33:35 -0400
- Subject: Re: readdir.c: d_off instead of d_reclen [PATCH]
- References: <7f45d93905060311385cb36bd@mail.gmail.com>
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