diff options
| author | Doug Rabson <dfr@FreeBSD.org> | 1997-05-14 08:19:35 +0000 | 
|---|---|---|
| committer | Doug Rabson <dfr@FreeBSD.org> | 1997-05-14 08:19:35 +0000 | 
| commit | 7877839a2284d0e299b306b069ff12c2aaaad5fb (patch) | |
| tree | 4bdc3ad79d5dc9b6724b63916234bf5f8a25e963 /sys/i386/linux/linux_file.c | |
| parent | a53a472ff45ef555aba613ffd352246bc46a2c48 (diff) | |
Notes
Diffstat (limited to 'sys/i386/linux/linux_file.c')
| -rw-r--r-- | sys/i386/linux/linux_file.c | 63 | 
1 files changed, 47 insertions, 16 deletions
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);  | 
