summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkstailey <kstailey@cvs.openbsd.org>1999-09-15 20:41:17 +0000
committerkstailey <kstailey@cvs.openbsd.org>1999-09-15 20:41:17 +0000
commitddb5ef5c9cb1d4a0946100674ff3f9ecc28bf445 (patch)
tree141386bb6b3e11f350bbcafd5062d6f7ac982857
parent7e23bd46da3539da5029e7b8a8d827ba3cb55ab6 (diff)
getdents(2)
-rw-r--r--sys/compat/netbsd/files.netbsd3
-rw-r--r--sys/compat/netbsd/netbsd_getdents.c130
-rw-r--r--sys/compat/netbsd/syscalls.master11
3 files changed, 139 insertions, 5 deletions
diff --git a/sys/compat/netbsd/files.netbsd b/sys/compat/netbsd/files.netbsd
index 81e333d9da0..145b6fd8dc7 100644
--- a/sys/compat/netbsd/files.netbsd
+++ b/sys/compat/netbsd/files.netbsd
@@ -1,4 +1,4 @@
-# $OpenBSD: files.netbsd,v 1.3 1999/09/15 18:36:37 kstailey Exp $
+# $OpenBSD: files.netbsd,v 1.4 1999/09/15 20:41:16 kstailey Exp $
#
# Config.new file description for machine-independent NetBSD compat code.
# Included by ports that need it.
@@ -8,6 +8,7 @@
file compat/netbsd/netbsd_exec.c compat_netbsd
file compat/netbsd/netbsd_getcwd.c compat_netbsd
+file compat/netbsd/netbsd_getdents.c compat_netbsd
file compat/netbsd/netbsd_misc.c compat_netbsd
file compat/netbsd/netbsd_signal.c compat_netbsd
file compat/netbsd/netbsd_stat.c compat_netbsd
diff --git a/sys/compat/netbsd/netbsd_getdents.c b/sys/compat/netbsd/netbsd_getdents.c
new file mode 100644
index 00000000000..2163c15442c
--- /dev/null
+++ b/sys/compat/netbsd/netbsd_getdents.c
@@ -0,0 +1,130 @@
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
+
+#include <compat/netbsd/netbsd_signal.h>
+#include <compat/netbsd/netbsd_syscallargs.h>
+
+static int netbsd_vn_readdir __P((struct file *, char *, int, u_int, int *,
+ struct proc *, off_t **, int *));
+
+static int
+netbsd_vn_readdir(fp, buf, segflg, count, done, p, cookies, ncookies)
+ struct file *fp;
+ char *buf;
+ int segflg, *done, *ncookies;
+ u_int count;
+ struct proc *p;
+ off_t **cookies;
+{
+ struct vnode *vp = (struct vnode *)fp->f_data;
+ struct iovec aiov;
+ struct uio auio;
+ int error, eofflag;
+
+unionread:
+ if (vp->v_type != VDIR)
+ return (EINVAL);
+ aiov.iov_base = buf;
+ aiov.iov_len = count;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = segflg;
+ auio.uio_procp = p;
+ auio.uio_resid = count;
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ auio.uio_offset = fp->f_offset;
+ error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, ncookies,
+ (u_long **)cookies); /* XXX 32-bit? */
+ fp->f_offset = auio.uio_offset;
+ VOP_UNLOCK(vp, 0, p);
+ if (error)
+ return (error);
+
+#ifdef UNION
+{
+ extern int (**union_vnodeop_p) __P((void *));
+ extern struct vnode *union_dircache __P((struct vnode *));
+
+ if (count == auio.uio_resid && (vp->v_op == union_vnodeop_p)) {
+ struct vnode *lvp;
+
+ lvp = union_dircache(vp);
+ if (lvp != NULLVP) {
+ struct vattr va;
+
+ /*
+ * If the directory is opaque,
+ * then don't show lower entries
+ */
+ error = VOP_GETATTR(vp, &va, fp->f_cred, p);
+ if (va.va_flags & OPAQUE) {
+ vput(lvp);
+ lvp = NULL;
+ }
+ }
+
+ if (lvp != NULLVP) {
+ error = VOP_OPEN(lvp, FREAD, fp->f_cred, p);
+ if (error) {
+ vput(lvp);
+ return (error);
+ }
+ VOP_UNLOCK(lvp, 0);
+ fp->f_data = (caddr_t) lvp;
+ fp->f_offset = 0;
+ error = vn_close(vp, FREAD, fp->f_cred, p);
+ if (error)
+ return (error);
+ vp = lvp;
+ goto unionread;
+ }
+ }
+}
+#endif /* UNION */
+
+ if (count == auio.uio_resid && (vp->v_flag & VROOT) &&
+ (vp->v_mount->mnt_flag & MNT_UNION)) {
+ struct vnode *tvp = vp;
+ vp = vp->v_mount->mnt_vnodecovered;
+ VREF(vp);
+ fp->f_data = (caddr_t) vp;
+ fp->f_offset = 0;
+ vrele(tvp);
+ goto unionread;
+ }
+ *done = count - auio.uio_resid;
+ return error;
+}
+
+/*
+ * Read a block of directory entries in a file system independent format.
+ */
+int
+netbsd_sys_getdents(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ register struct netbsd_sys_getdents_args /* {
+ syscallarg(int) fd;
+ syscallarg(char *) buf;
+ syscallarg(size_t) count;
+ } */ *uap = v;
+ struct file *fp;
+ int error, done;
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+ if ((fp->f_flag & FREAD) == 0)
+ return (EBADF);
+ error = netbsd_vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
+ SCARG(uap, count), &done, p, 0, 0);
+ *retval = done;
+ return (error);
+}
+
diff --git a/sys/compat/netbsd/syscalls.master b/sys/compat/netbsd/syscalls.master
index 0d4ecb7f2af..2a06d789fea 100644
--- a/sys/compat/netbsd/syscalls.master
+++ b/sys/compat/netbsd/syscalls.master
@@ -1,4 +1,4 @@
-; $OpenBSD: syscalls.master,v 1.4 1999/09/15 18:36:38 kstailey Exp $
+; $OpenBSD: syscalls.master,v 1.5 1999/09/15 20:41:16 kstailey Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -356,7 +356,11 @@
#endif
172 UNIMPL
173 UNIMPL
+;173 STD { ssize_t sys_pread(int fd, void *buf, \
+; size_t nbyte, int pad, off_t offset); }
174 UNIMPL
+;174 STD { ssize_t sys_pwrite(int fd, const void *buf, \
+; size_t nbyte, int pad, off_t offset); }
#ifdef NTP
175 NOARGS { int sys_ntp_gettime(struct ntptimeval *ntvp); }
176 NOARGS { int sys_ntp_adjtime(struct timex *tp); }
@@ -540,9 +544,8 @@
271 UNIMPL
;271 STD { int netbsd_sys_swapctl(int cmd, const void *arg,
; int misc); }
-272 UNIMPL
-;272 STD { int netbsd_sys_getdents(int fd, char *buf, \
-; size_t count); }
+272 STD { int netbsd_sys_getdents(int fd, char *buf, \
+ size_t count); }
273 NOARGS { int sys_minherit(void *addr, size_t len, \
int inherit); }
274 UNIMPL