summaryrefslogtreecommitdiff
path: root/sys/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/ibcs2/ibcs2_misc.c128
-rw-r--r--sys/i386/linux/linux_file.c63
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);