diff options
Diffstat (limited to 'sys/i386')
| -rw-r--r-- | sys/i386/ibcs2/ibcs2_misc.c | 128 | ||||
| -rw-r--r-- | sys/i386/linux/linux_file.c | 63 |
2 files changed, 148 insertions, 43 deletions
diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c index 863f5b087197..423d4c600c5b 100644 --- a/sys/i386/ibcs2/ibcs2_misc.c +++ b/sys/i386/ibcs2/ibcs2_misc.c @@ -45,7 +45,7 @@ * * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 * - * $Id: ibcs2_misc.c,v 1.12 1996/12/05 03:14:14 nate Exp $ + * $Id: ibcs2_misc.c,v 1.10.2.1 1996/12/12 19:39:18 jkh Exp $ */ /* @@ -71,6 +71,7 @@ #include <sys/resourcevar.h> #include <sys/socket.h> #include <sys/stat.h> +#include <sys/dirent.h> #include <sys/time.h> #include <sys/times.h> #include <sys/vnode.h> @@ -79,8 +80,6 @@ #include <sys/utsname.h> #include <sys/unistd.h> -#include <ufs/ufs/dir.h> - #include <netinet/in.h> #include <sys/sysproto.h> @@ -337,8 +336,10 @@ ibcs2_getdents(p, uap, retval) struct iovec aiov; struct ibcs2_dirent idb; off_t off; /* true file offset */ - int buflen, error, eofflag, blockoff; -#define BSD_DIRENT(cp) ((struct direct *)(cp)) + int buflen, error, eofflag; + u_int *cookies = NULL, *cookiep; + int ncookies; +#define BSD_DIRENT(cp) ((struct dirent *)(cp)) #define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) @@ -350,8 +351,8 @@ ibcs2_getdents(p, uap, retval) return (EINVAL); off = fp->f_offset; - blockoff = off % DIRBLKSIZ; - buflen = max(DIRBLKSIZ, SCARG(uap, nbytes) + blockoff); +#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ + buflen = max(DIRBLKSIZ, SCARG(uap, nbytes)); buflen = min(buflen, MAXBSIZE); buf = malloc(buflen, M_TEMP, M_WAITOK); VOP_LOCK(vp); @@ -364,29 +365,59 @@ again: auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = p; auio.uio_resid = buflen; - auio.uio_offset = off - (off_t)blockoff; + auio.uio_offset = off; + + if (cookies) { + free(cookies, M_TEMP); + cookies = NULL; + } + /* * First we read into the malloc'ed buffer, then * we massage it into user space, one record at a time. */ - if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL)) + if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) goto out; inp = buf; - inp += blockoff; outp = SCARG(uap, buf); resid = SCARG(uap, nbytes); - if ((len = buflen - auio.uio_resid - blockoff) == 0) + if ((len = buflen - auio.uio_resid) <= 0) goto eof; + + cookiep = cookies; + + if (cookies) { + /* + * When using cookies, the vfs has the option of reading from + * a different offset than that supplied (UFS truncates the + * offset to a block boundary to make sure that it never reads + * partway through a directory entry, even if the directory + * has been compacted). + */ + while (len > 0 && ncookies > 0 && *cookiep <= off) { + len -= BSD_DIRENT(inp)->d_reclen; + inp += BSD_DIRENT(inp)->d_reclen; + cookiep++; + ncookies--; + } + } + for (; len > 0; len -= reclen) { + if (cookiep && ncookies == 0) + break; reclen = BSD_DIRENT(inp)->d_reclen; if (reclen & 3) { printf("ibcs2_getdents: reclen=%d\n", reclen); error = EFAULT; goto out; } - if (BSD_DIRENT(inp)->d_ino == 0) { + if (BSD_DIRENT(inp)->d_fileno == 0) { inp += reclen; /* it is a hole; squish it out */ - off += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; continue; } if (reclen > len || resid < IBCS2_RECLEN(reclen)) { @@ -399,7 +430,7 @@ again: * we have to worry about touching user memory outside of * the copyout() call). */ - idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_ino; + idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; idb.d_off = (ibcs2_off_t)off; idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || @@ -407,7 +438,11 @@ again: BSD_DIRENT(inp)->d_namlen + 1)) != 0) goto out; /* advance past this real entry */ - off += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; inp += reclen; /* advance output past iBCS2-shaped entry */ outp += IBCS2_RECLEN(reclen); @@ -420,6 +455,8 @@ again: eof: *retval = SCARG(uap, nbytes) - resid; out: + if (cookies) + free(cookies, M_TEMP); VOP_UNLOCK(vp); free(buf, M_TEMP); return (error); @@ -444,7 +481,9 @@ ibcs2_read(p, uap, retval) char name[14]; } idb; off_t off; /* true file offset */ - int buflen, error, eofflag, size, blockoff; + int buflen, error, eofflag, size; + u_int *cookies = NULL, *cookiep; + int ncookies; if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) { if (error == EINVAL) @@ -461,8 +500,7 @@ ibcs2_read(p, uap, retval) DPRINTF(("ibcs2_read: read directory\n")); off = fp->f_offset; - blockoff = off % DIRBLKSIZ; - buflen = max(DIRBLKSIZ, SCARG(uap, nbytes) + blockoff); + buflen = max(DIRBLKSIZ, SCARG(uap, nbytes)); buflen = min(buflen, MAXBSIZE); buf = malloc(buflen, M_TEMP, M_WAITOK); VOP_LOCK(vp); @@ -475,31 +513,61 @@ again: auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = p; auio.uio_resid = buflen; - auio.uio_offset = off - (off_t)blockoff; + auio.uio_offset = off; + + if (cookies) { + free(cookies, M_TEMP); + cookies = NULL; + } + /* * First we read into the malloc'ed buffer, then * we massage it into user space, one record at a time. */ - if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 0, 0)) { + if (error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) { DPRINTF(("VOP_READDIR failed: %d\n", error)); goto out; } inp = buf; - inp += blockoff; outp = SCARG(uap, buf); resid = SCARG(uap, nbytes); - if ((len = buflen - auio.uio_resid - blockoff) == 0) + if ((len = buflen - auio.uio_resid) <= 0) goto eof; + + cookiep = cookies; + + if (cookies) { + /* + * When using cookies, the vfs has the option of reading from + * a different offset than that supplied (UFS truncates the + * offset to a block boundary to make sure that it never reads + * partway through a directory entry, even if the directory + * has been compacted). + */ + while (len > 0 && ncookies > 0 && *cookiep <= off) { + len -= BSD_DIRENT(inp)->d_reclen; + inp += BSD_DIRENT(inp)->d_reclen; + cookiep++; + ncookies--; + } + } + for (; len > 0 && resid > 0; len -= reclen) { + if (cookiep && ncookies == 0) + break; reclen = BSD_DIRENT(inp)->d_reclen; if (reclen & 3) { printf("ibcs2_read: reclen=%d\n", reclen); error = EFAULT; goto out; } - if (BSD_DIRENT(inp)->d_ino == 0) { + if (BSD_DIRENT(inp)->d_fileno == 0) { inp += reclen; /* it is a hole; squish it out */ - off += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; continue; } if (reclen > len || resid < sizeof(struct ibcs2_direct)) { @@ -515,14 +583,18 @@ again: * TODO: if length(filename) > 14, then break filename into * multiple entries and set inode = 0xffff except last */ - idb.ino = (BSD_DIRENT(inp)->d_ino > 0xfffe) ? 0xfffe : - BSD_DIRENT(inp)->d_ino; + idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : + BSD_DIRENT(inp)->d_fileno; (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); bzero(idb.name + size, 14 - size); if (error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) goto out; /* advance past this real entry */ - off += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; inp += reclen; /* advance output past iBCS2-shaped entry */ outp += sizeof(struct ibcs2_direct); @@ -535,6 +607,8 @@ again: eof: *retval = SCARG(uap, nbytes) - resid; out: + if (cookies) + free(cookies, M_TEMP); VOP_UNLOCK(vp); free(buf, M_TEMP); return (error); diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c index bf28b2c552cf..357e587c124b 100644 --- a/sys/i386/linux/linux_file.c +++ b/sys/i386/linux/linux_file.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_file.c,v 1.6 1996/03/02 19:37:53 peter Exp $ + * $Id: linux_file.c,v 1.7 1996/03/10 22:27:51 peter Exp $ */ #include <sys/param.h> @@ -36,17 +36,12 @@ #include <sys/filedesc.h> #include <sys/proc.h> #include <sys/ioctl.h> -#include <sys/stat.h> #include <sys/vnode.h> #include <sys/malloc.h> -#include <sys/exec.h> #include <sys/dirent.h> -#include <sys/sysproto.h> #include <sys/conf.h> #include <sys/tty.h> -#include <ufs/ufs/dir.h> - #include <i386/linux/linux.h> #include <i386/linux/linux_proto.h> #include <i386/linux/linux_util.h> @@ -415,7 +410,9 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval) struct vattr va; off_t off; struct linux_dirent linux_dirent; - int buflen, error, eofflag, nbytes, justone, blockoff; + int buflen, error, eofflag, nbytes, justone; + u_int *cookies = NULL, *cookiep; + int ncookies; #ifdef DEBUG printf("Linux-emul(%d): getdents(%d, *, %d)\n", @@ -446,8 +443,8 @@ linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval) justone = 0; off = fp->f_offset; - blockoff = off % DIRBLKSIZ; - buflen = max(DIRBLKSIZ, nbytes + blockoff); +#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ + buflen = max(DIRBLKSIZ, nbytes); buflen = min(buflen, MAXBSIZE); buf = malloc(buflen, M_TEMP, M_WAITOK); VOP_LOCK(vp); @@ -460,23 +457,47 @@ again: auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = p; auio.uio_resid = buflen; - auio.uio_offset = off - (off_t)blockoff; + auio.uio_offset = off; + + if (cookies) { + free(cookies, M_TEMP); + cookies = NULL; + } - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (int *) NULL, - (u_int **) NULL); + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies); if (error) { goto out; } inp = buf; - inp += blockoff; outp = (caddr_t) args->dent; resid = nbytes; - if ((len = buflen - auio.uio_resid - blockoff) == 0) { + if ((len = buflen - auio.uio_resid) <= 0) { goto eof; } + cookiep = cookies; + + if (cookies) { + /* + * When using cookies, the vfs has the option of reading from + * a different offset than that supplied (UFS truncates the + * offset to a block boundary to make sure that it never reads + * partway through a directory entry, even if the directory + * has been compacted). + */ + while (len > 0 && ncookies > 0 && *cookiep <= off) { + bdp = (struct dirent *) inp; + len -= bdp->d_reclen; + inp += bdp->d_reclen; + cookiep++; + ncookies--; + } + } + while (len > 0) { + if (cookiep && ncookies == 0) + break; bdp = (struct dirent *) inp; reclen = bdp->d_reclen; if (reclen & 3) { @@ -487,7 +508,11 @@ again: if (bdp->d_fileno == 0) { inp += reclen; - off += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; len -= reclen; continue; } @@ -512,7 +537,11 @@ again: goto out; } inp += reclen; - off += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; outp += linuxreclen; resid -= linuxreclen; len -= reclen; @@ -529,6 +558,8 @@ again: eof: *retval = nbytes - resid; + if (cookies) + free(cookies, M_TEMP); out: VOP_UNLOCK(vp); free(buf, M_TEMP); |
