summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/compat/freebsd/freebsd_misc.c71
-rw-r--r--sys/compat/freebsd/syscalls.master5
2 files changed, 73 insertions, 3 deletions
diff --git a/sys/compat/freebsd/freebsd_misc.c b/sys/compat/freebsd/freebsd_misc.c
index 07af316e21a..a045df91e4d 100644
--- a/sys/compat/freebsd/freebsd_misc.c
+++ b/sys/compat/freebsd/freebsd_misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: freebsd_misc.c,v 1.8 2002/07/06 19:14:20 nordin Exp $ */
+/* $OpenBSD: freebsd_misc.c,v 1.9 2005/02/19 21:19:28 matthieu Exp $ */
/* $NetBSD: freebsd_misc.c,v 1.2 1996/05/03 17:03:10 christos Exp $ */
/*
@@ -40,6 +40,10 @@
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/mount.h>
+#include <sys/file.h>
+#include <sys/dirent.h>
+#include <sys/filedesc.h>
+#include <sys/vnode.h>
#include <sys/syscallargs.h>
@@ -48,6 +52,8 @@
#include <compat/freebsd/freebsd_util.h>
#include <compat/freebsd/freebsd_rtprio.h>
+#include <compat/common/compat_dir.h>
+
/* just a place holder */
int
@@ -92,3 +98,66 @@ freebsd_sys_madvise(p, v, retval)
{
return (0);
}
+
+
+int freebsd_readdir_callback(void *, struct dirent *, off_t);
+
+struct freebsd_readdir_callback_args {
+ caddr_t outp;
+ int resid;
+};
+
+int
+freebsd_readdir_callback(void *arg, struct dirent *bdp, off_t cookie)
+{
+ struct freebsd_readdir_callback_args *cb = arg;
+ struct dirent idb;
+ int error;
+
+ if (cb->resid < bdp->d_reclen)
+ return (ENOMEM);
+ idb.d_fileno = bdp->d_fileno;
+ idb.d_reclen = bdp->d_reclen;
+ idb.d_type = bdp->d_type;
+ idb.d_namlen = bdp->d_namlen;
+ strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
+
+ if ((error = copyout((caddr_t)&idb, cb->outp, bdp->d_reclen)))
+ return (error);
+ cb->outp += bdp->d_reclen;
+ cb->resid -= bdp->d_reclen;
+
+ return (0);
+}
+
+int
+freebsd_sys_getdents(struct proc *p, void *v, register_t *retval)
+{
+ struct freebsd_sys_getdents_args /* {
+ syscallarg(int) fd;
+ syscallarg(void *) dirent;
+ syscallarg(unsigned) count;
+ } */ *uap = v;
+ struct vnode *vp;
+ struct file *fp;
+ int error;
+ struct freebsd_readdir_callback_args args;
+
+ if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
+ return (error);
+
+ vp = (struct vnode *)fp->f_data;
+
+ args.resid = SCARG(uap, count);
+ args.outp = (caddr_t)SCARG(uap, dirent);
+
+ error = readdir_with_callback(fp, &fp->f_offset, args.resid,
+ freebsd_readdir_callback, &args);
+
+ FRELE(fp);
+ if (error)
+ return (error);
+
+ *retval = SCARG(uap, count) - args.resid;
+ return (0);
+}
diff --git a/sys/compat/freebsd/syscalls.master b/sys/compat/freebsd/syscalls.master
index da40093160d..b1a3a696c40 100644
--- a/sys/compat/freebsd/syscalls.master
+++ b/sys/compat/freebsd/syscalls.master
@@ -1,4 +1,4 @@
- $OpenBSD: syscalls.master,v 1.26 2004/07/13 21:04:29 millert Exp $
+ $OpenBSD: syscalls.master,v 1.27 2005/02/19 21:19:28 matthieu Exp $
; $NetBSD: syscalls.master,v 1.3 1995/10/10 18:28:40 mycroft Exp $
; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -497,7 +497,8 @@
269 UNIMPL
270 UNIMPL
271 UNIMPL
-272 UNIMPL getdents
+272 STD { int freebsd_sys_getdents(int fd, void *dirent, \
+ unsigned count); }
273 UNIMPL
274 UNIMPL lchmod
275 UNIMPL lchown