From 4f9feb058cb63487207395b927f1dc7152771a57 Mon Sep 17 00:00:00 2001 From: Matthieu Herrb Date: Sat, 19 Feb 2005 21:19:29 +0000 Subject: Add getdents() emulation. Makes Veritas NetBackup client for FreeBSD work. ok deraadt@, tedu@. --- sys/compat/freebsd/freebsd_misc.c | 71 +++++++++++++++++++++++++++++++++++++- sys/compat/freebsd/syscalls.master | 5 +-- 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 #include #include +#include +#include +#include +#include #include @@ -48,6 +52,8 @@ #include #include +#include + /* 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 -- cgit v1.2.3