diff options
author | phk <phk@FreeBSD.org> | 2001-08-14 06:42:32 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2001-08-14 06:42:32 +0000 |
commit | 14112e9d98a3497f55ced2ded8fd0fff57ec511c (patch) | |
tree | 23bc8ec4e40acac34e7f5a3f6d4a06733a8f2057 | |
parent | 415090c0c17acad44affb2a6da58b80e0d148c54 (diff) | |
download | FreeBSD-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.c | 26 |
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); |