summaryrefslogtreecommitdiff
path: root/sys/i386/linux/linux_file.c
diff options
context:
space:
mode:
authorDoug Rabson <dfr@FreeBSD.org>1997-05-14 08:19:35 +0000
committerDoug Rabson <dfr@FreeBSD.org>1997-05-14 08:19:35 +0000
commit7877839a2284d0e299b306b069ff12c2aaaad5fb (patch)
tree4bdc3ad79d5dc9b6724b63916234bf5f8a25e963 /sys/i386/linux/linux_file.c
parenta53a472ff45ef555aba613ffd352246bc46a2c48 (diff)
Notes
Diffstat (limited to 'sys/i386/linux/linux_file.c')
-rw-r--r--sys/i386/linux/linux_file.c63
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);