summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2001-08-14 06:42:32 +0000
committerphk <phk@FreeBSD.org>2001-08-14 06:42:32 +0000
commit14112e9d98a3497f55ced2ded8fd0fff57ec511c (patch)
tree23bc8ec4e40acac34e7f5a3f6d4a06733a8f2057
parent415090c0c17acad44affb2a6da58b80e0d148c54 (diff)
downloadFreeBSD-src-14112e9d98a3497f55ced2ded8fd0fff57ec511c.zip
FreeBSD-src-14112e9d98a3497f55ced2ded8fd0fff57ec511c.tar.gz
linux ls fails on DEVFS /dev because linux_getdents fails because
linux_getdents uses VOP_READDIR( ..., &ncookies, &cookies ) instead of VOP_READDIR( ..., NULL, NULL ) because it seems to need the offsets for linux_dirent and sizeof(dirent) != sizeof(linux_dirent)... PR: 29467 Submitted by: Michael Reifenberger <root@nihil.plaut.de> Reviewed by: phk
-rw-r--r--sys/fs/devfs/devfs_vnops.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index b8d5cce..bafc3b3 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -499,14 +499,14 @@ devfs_readdir(ap)
struct devfs_dirent *dd;
struct devfs_dirent *de;
struct devfs_mount *dmp;
- off_t off;
+ off_t off, oldoff;
+ int ncookies = 0;
+ u_long *cookiebuf, *cookiep;
+ struct dirent *dps, *dpe;
if (ap->a_vp->v_type != VDIR)
return (ENOTDIR);
- if (ap->a_ncookies)
- return (EOPNOTSUPP);
-
uio = ap->a_uio;
if (uio->uio_offset < 0)
return (EINVAL);
@@ -517,6 +517,7 @@ devfs_readdir(ap)
error = 0;
de = ap->a_vp->v_data;
off = 0;
+ oldoff = uio->uio_offset;
TAILQ_FOREACH(dd, &de->de_dlist, de_list) {
if (dd->de_flags & DE_WHITEOUT)
continue;
@@ -529,12 +530,29 @@ devfs_readdir(ap)
break;
dp->d_fileno = de->de_inode;
if (off >= uio->uio_offset) {
+ ncookies++;
error = uiomove((caddr_t)dp, dp->d_reclen, uio);
if (error)
break;
}
off += dp->d_reclen;
}
+ if( !error && ap->a_ncookies != NULL && ap->a_cookies != NULL ) {
+ MALLOC(cookiebuf, u_long *, ncookies * sizeof(u_long),
+ M_TEMP, M_WAITOK);
+ cookiep = cookiebuf;
+ dps = (struct dirent *)
+ (uio->uio_iov->iov_base - (uio->uio_offset - oldoff));
+ dpe = (struct dirent *) uio->uio_iov->iov_base;
+ for( dp = dps;
+ dp < dpe;
+ dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
+ oldoff += dp->d_reclen;
+ *cookiep++ = (u_long) oldoff;
+ }
+ *ap->a_ncookies = ncookies;
+ *ap->a_cookies = cookiebuf;
+ }
lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curproc);
uio->uio_offset = off;
return (error);
OpenPOWER on IntegriCloud