From 9697c509606b1a3621c7976ef072d8527795d5ec Mon Sep 17 00:00:00 2001 From: "David P. Reese, Jr." Date: Mon, 3 Nov 2003 15:57:34 +0000 Subject: [PATCH] Split wait4(), setrlimit(), getrlimit(), statfs(), fstatfs(), chdir(), open(), mknod(), link(), symlink(), unlink(), lseek(), access(), stat(), lstat(), readlink(), chmod(), chown(), lchown(), utimes(), lutimes(), futimes(), truncate(), rename(), mkdir(), rmdir(), getdirentries(), getdents(). Trash the 4.3BSD numeric filesystem type support in mount(). Move ocreat(), olseek(), otruncate(), ostat(), olstat(), owait(), ogetrlimit(), and osetrlimit() to the 43bsd subtree and reimplement using split syscalls. Move ogetdirentries() to the subtree without change because it is such a mess. Convince linux_waitpid(), linux_wait(), linux_setrlimit(), linux_old_getrlimit(), and linux_getrlimit() to use split syscalls. The file kern/vfs_syscalls.c is now completely free of COMPAT_43 code. I believe that execve() is the only pending split before I can tackle stackgap usage in the linux emulator's CHECKALT{EXIST,CREAT}() macros. --- sys/conf/files | 4 +- .../43bsd/{43bsd_file.c => 43bsd_exit.c} | 25 +- sys/emulation/43bsd/43bsd_file.c | 166 ++- .../43bsd/{43bsd_stats.c => 43bsd_resource.c} | 64 +- sys/emulation/43bsd/43bsd_stats.c | 47 +- sys/emulation/linux/linux_misc.c | 188 +-- sys/kern/kern_exit.c | 109 +- sys/kern/kern_resource.c | 81 +- sys/kern/vfs_syscalls.c | 1299 ++++++++--------- sys/sys/kern_syscall.h | 40 +- 10 files changed, 1077 insertions(+), 946 deletions(-) copy sys/emulation/43bsd/{43bsd_file.c => 43bsd_exit.c} (80%) copy sys/emulation/43bsd/{43bsd_stats.c => 43bsd_resource.c} (70%) diff --git a/sys/conf/files b/sys/conf/files index 96b4d4587b..256e4f3384 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.22 2003/10/31 21:49:23 asmodai Exp $ +# $DragonFly: src/sys/conf/files,v 1.23 2003/11/03 15:57:33 daver Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -1585,3 +1585,5 @@ emulation/43bsd/43bsd_socket.c optional compat_43 emulation/43bsd/43bsd_stats.c optional compat_43 emulation/43bsd/43bsd_file.c optional compat_43 emulation/43bsd/43bsd_signal.c optional compat_43 +emulation/43bsd/43bsd_exit.c optional compat_43 +emulation/43bsd/43bsd_resource.c optional compat_43 diff --git a/sys/emulation/43bsd/43bsd_file.c b/sys/emulation/43bsd/43bsd_exit.c similarity index 80% copy from sys/emulation/43bsd/43bsd_file.c copy to sys/emulation/43bsd/43bsd_exit.c index 2ab25d127e..925e659c0a 100644 --- a/sys/emulation/43bsd/43bsd_file.c +++ b/sys/emulation/43bsd/43bsd_exit.c @@ -1,7 +1,7 @@ /* - * 43BSD_FILE.C - 4.3BSD compatibility file syscalls + * 43BSD_EXIT.C - 4.3BSD compatibility exit syscalls * - * Copyright (c) 1989, 1993 + * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed @@ -37,10 +37,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.1 2003/10/21 01:05:09 daver Exp $ - * from: DragonFly kern/vfs_syscalls.c,v 1.20 + * $DragonFly: src/sys/emulation/43bsd/43bsd_exit.c,v 1.1 2003/11/03 15:57:33 daver Exp $ + * from: DragonFly kern/kern_exit.c,v 1.26 * - * These syscalls used to live in kern/vfs_syscalls.c. They are modified + * These syscalls used to live in kern/kern_exit.c. They are modified * to use the new split syscalls. */ @@ -52,13 +52,22 @@ #include #include #include +#include +#include +/* + * owait() + * + * owait_args(int dummy) + */ int -oftruncate(struct oftruncate_args *uap) +owait(struct owait_args *uap) { - int error; + int error, status; - error = kern_ftruncate(uap->fd, uap->length); + error = kern_wait(WAIT_ANY, &status, 0, NULL, &uap->sysmsg_fds[0]); + if (error == 0) + uap->sysmsg_fds[1] = status; return (error); } diff --git a/sys/emulation/43bsd/43bsd_file.c b/sys/emulation/43bsd/43bsd_file.c index 2ab25d127e..85bdae6651 100644 --- a/sys/emulation/43bsd/43bsd_file.c +++ b/sys/emulation/43bsd/43bsd_file.c @@ -37,7 +37,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.1 2003/10/21 01:05:09 daver Exp $ + * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.2 2003/11/03 15:57:33 daver Exp $ * from: DragonFly kern/vfs_syscalls.c,v 1.20 * * These syscalls used to live in kern/vfs_syscalls.c. They are modified @@ -50,8 +50,34 @@ #include #include #include +#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include + +#include + +int +ocreat(struct ocreat_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_open(&nd, O_WRONLY | O_CREAT | O_TRUNC, uap->mode, + &uap->sysmsg_result); + + return (error); +} int oftruncate(struct oftruncate_args *uap) @@ -62,3 +88,141 @@ oftruncate(struct oftruncate_args *uap) return (error); } + +int +olseek(struct olseek_args *uap) +{ + int error; + + error = kern_lseek(uap->fd, uap->offset, uap->whence, + &uap->sysmsg_result); + + return (error); +} + +int +otruncate(struct otruncate_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_truncate(&nd, uap->length); + + return (error); +} + +int +ogetdirentries(struct ogetdirentries_args *uap) +{ + struct thread *td = curthread; + struct proc *p = td->td_proc; + struct vnode *vp; + struct file *fp; + struct uio auio, kuio; + struct iovec aiov, kiov; + struct dirent *dp, *edp; + caddr_t dirbuf; + int error, eofflag, readcnt; + long loff; + + /* XXX arbitrary sanity limit on `count'. */ + if (uap->count > 64 * 1024) + return (EINVAL); + if ((error = getvnode(p->p_fd, uap->fd, &fp)) != 0) + return (error); + if ((fp->f_flag & FREAD) == 0) + return (EBADF); + vp = (struct vnode *)fp->f_data; +unionread: + if (vp->v_type != VDIR) + return (EINVAL); + aiov.iov_base = uap->buf; + aiov.iov_len = uap->count; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_td = td; + auio.uio_resid = uap->count; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + loff = auio.uio_offset = fp->f_offset; +# if (BYTE_ORDER != LITTLE_ENDIAN) + if (vp->v_mount->mnt_maxsymlinklen <= 0) { + error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, + NULL, NULL); + fp->f_offset = auio.uio_offset; + } else +# endif + { + kuio = auio; + kuio.uio_iov = &kiov; + kuio.uio_segflg = UIO_SYSSPACE; + kiov.iov_len = uap->count; + MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); + kiov.iov_base = dirbuf; + error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, + NULL, NULL); + fp->f_offset = kuio.uio_offset; + if (error == 0) { + readcnt = uap->count - kuio.uio_resid; + edp = (struct dirent *)&dirbuf[readcnt]; + for (dp = (struct dirent *)dirbuf; dp < edp; ) { +# if (BYTE_ORDER == LITTLE_ENDIAN) + /* + * The expected low byte of + * dp->d_namlen is our dp->d_type. + * The high MBZ byte of dp->d_namlen + * is our dp->d_namlen. + */ + dp->d_type = dp->d_namlen; + dp->d_namlen = 0; +# else + /* + * The dp->d_type is the high byte + * of the expected dp->d_namlen, + * so must be zero'ed. + */ + dp->d_type = 0; +# endif + if (dp->d_reclen > 0) { + dp = (struct dirent *) + ((char *)dp + dp->d_reclen); + } else { + error = EIO; + break; + } + } + if (dp >= edp) + error = uiomove(dirbuf, readcnt, &auio); + } + FREE(dirbuf, M_TEMP); + } + VOP_UNLOCK(vp, 0, td); + if (error) + return (error); + if (uap->count == auio.uio_resid) { + if (union_dircheckp) { + error = union_dircheckp(td, &vp, fp); + if (error == -1) + goto unionread; + if (error) + return (error); + } + if ((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; + } + } + error = copyout(&loff, uap->basep, sizeof(long)); + uap->sysmsg_result = uap->count - auio.uio_resid; + return (error); +} diff --git a/sys/emulation/43bsd/43bsd_stats.c b/sys/emulation/43bsd/43bsd_resource.c similarity index 70% copy from sys/emulation/43bsd/43bsd_stats.c copy to sys/emulation/43bsd/43bsd_resource.c index d7736b8f58..81e90697a4 100644 --- a/sys/emulation/43bsd/43bsd_stats.c +++ b/sys/emulation/43bsd/43bsd_resource.c @@ -1,5 +1,5 @@ /* - * 43BSD_STATS.C - 4.3BSD compatibility stats syscalls + * 43BSD_RESOURCE.C - 4.3BSD compatibility exit syscalls * * Copyright (c) 1982, 1986, 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. @@ -37,10 +37,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/emulation/43bsd/43bsd_stats.c,v 1.1 2003/10/21 01:05:09 daver Exp $ - * from: DragonFly kern/kern_descrip.c,v 1.16 + * $DragonFly: src/sys/emulation/43bsd/43bsd_resource.c,v 1.1 2003/11/03 15:57:33 daver Exp $ + * from: DragonFly kern/kern_resource.c,v 1.14 * - * These syscalls used to live in kern/kern_descrip.c. They are modified + * These syscalls used to live in kern/kern_resource.c. They are modified * to use the new split syscalls. */ @@ -51,48 +51,46 @@ #include #include #include -#include #include +#include -static int -compat_43_copyout_stat(struct stat *st, struct ostat *uaddr) +int +ogetrlimit(struct ogetrlimit_args *uap) { - struct ostat ost; + struct orlimit olim; + struct rlimit lim; int error; - ost.st_dev = st->st_dev; - ost.st_ino = st->st_ino; - ost.st_mode = st->st_mode; - ost.st_nlink = st->st_nlink; - ost.st_uid = st->st_uid; - ost.st_gid = st->st_gid; - ost.st_rdev = st->st_rdev; - if (st->st_size < (quad_t)1 << 32) - ost.st_size = st->st_size; - else - ost.st_size = -2; - ost.st_atime = st->st_atime; - ost.st_mtime = st->st_mtime; - ost.st_ctime = st->st_ctime; - ost.st_blksize = st->st_blksize; - ost.st_blocks = st->st_blocks; - ost.st_flags = st->st_flags; - ost.st_gen = st->st_gen; + error = kern_getrlimit(uap->which, &lim); - error = copyout(&ost, uaddr, sizeof(ost)); + if (error == 0) { + olim.rlim_cur = lim.rlim_cur; + if (olim.rlim_cur == -1) + olim.rlim_cur = 0x7fffffff; + olim.rlim_max = lim.rlim_max; + if (olim.rlim_max == -1) + olim.rlim_max = 0x7fffffff; + error = copyout(&olim, uap->rlp, sizeof(*uap->rlp)); + } return (error); + } int -ofstat(struct ofstat_args *uap) +osetrlimit(struct osetrlimit_args *uap) { - struct stat st; + struct orlimit olim; + struct rlimit lim; int error; - error = kern_fstat(uap->fd, &st); + error = copyin(uap->rlp, &olim, sizeof(olim)); + if (error) + return (error); + lim.rlim_cur = olim.rlim_cur; + lim.rlim_max = olim.rlim_max; + + error = kern_setrlimit(uap->which, &lim); - if (error == 0) { - error = compat_43_copyout_stat(&st, uap->sb); - } return (error); + } diff --git a/sys/emulation/43bsd/43bsd_stats.c b/sys/emulation/43bsd/43bsd_stats.c index d7736b8f58..a3cb46b134 100644 --- a/sys/emulation/43bsd/43bsd_stats.c +++ b/sys/emulation/43bsd/43bsd_stats.c @@ -37,11 +37,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/emulation/43bsd/43bsd_stats.c,v 1.1 2003/10/21 01:05:09 daver Exp $ + * $DragonFly: src/sys/emulation/43bsd/43bsd_stats.c,v 1.2 2003/11/03 15:57:33 daver Exp $ * from: DragonFly kern/kern_descrip.c,v 1.16 + * from: DragonFly kern/vfs_syscalls.c,v 1.21 * - * These syscalls used to live in kern/kern_descrip.c. They are modified - * to use the new split syscalls. + * These syscalls used to live in kern/kern_descrip.c and + * kern/vfs_syscalls.c. They are modified * to use the new split syscalls. */ #include "opt_compat.h" @@ -53,6 +54,7 @@ #include #include #include +#include static int compat_43_copyout_stat(struct stat *st, struct ostat *uaddr) @@ -91,8 +93,43 @@ ofstat(struct ofstat_args *uap) error = kern_fstat(uap->fd, &st); - if (error == 0) { + if (error == 0) error = compat_43_copyout_stat(&st, uap->sb); - } + return (error); +} + +int +ostat(struct ostat_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + struct stat st; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ, + UIO_USERSPACE, uap->path, td); + + error = kern_stat(&nd, &st); + + if (error == 0) + error = compat_43_copyout_stat(&st, uap->ub); + return (error); +} + +int +olstat(struct olstat_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + struct stat st; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, + UIO_USERSPACE, uap->path, td); + + error = kern_stat(&nd, &st); + + if (error == 0) + error = compat_43_copyout_stat(&st, uap->ub); return (error); } diff --git a/sys/emulation/linux/linux_misc.c b/sys/emulation/linux/linux_misc.c index 5fb5c3d255..eb49403e92 100644 --- a/sys/emulation/linux/linux_misc.c +++ b/sys/emulation/linux/linux_misc.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $ - * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.14 2003/09/23 05:03:51 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.15 2003/11/03 15:57:33 daver Exp $ */ #include "opt_compat.h" @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -786,43 +787,33 @@ linux_utime(struct linux_utime_args *args) int linux_waitpid(struct linux_waitpid_args *args) { - struct wait_args bsd_args; - int error, tmpstat; + int error, options, status; #ifdef DEBUG if (ldebug(waitpid)) printf(ARGS(waitpid, "%d, %p, %d"), args->pid, (void *)args->status, args->options); #endif - - bsd_args.sysmsg_result = 0; - bsd_args.pid = args->pid; - bsd_args.status = args->status; - bsd_args.options = (args->options & (WNOHANG | WUNTRACED)); + options = args->options & (WNOHANG | WUNTRACED); /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ if (args->options & __WCLONE) - bsd_args.options |= WLINUXCLONE; - bsd_args.rusage = NULL; - - if ((error = wait4(&bsd_args)) != 0) - return error; - args->sysmsg_result = bsd_args.sysmsg_result; - - if (args->status) { - if ((error = copyin((caddr_t)args->status, &tmpstat, - sizeof(int))) != 0) - return error; - tmpstat &= 0xffff; - if (WIFSIGNALED(tmpstat)) - tmpstat = (tmpstat & 0xffffff80) | - BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); - else if (WIFSTOPPED(tmpstat)) - tmpstat = (tmpstat & 0xffff00ff) | - (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); - return copyout(&tmpstat, (caddr_t)args->status, sizeof(int)); + options |= WLINUXCLONE; + + error = kern_wait(args->pid, args->status ? &status : NULL, options, + NULL, &args->sysmsg_result); + + if (error == 0 && args->status) { + status &= 0xffff; + if (WIFSIGNALED(status)) + status = (status & 0xffffff80) | + BSD_TO_LINUX_SIGNAL(WTERMSIG(status)); + else if (WIFSTOPPED(status)) + status = (status & 0xffff00ff) | + (BSD_TO_LINUX_SIGNAL(WSTOPSIG(status)) << 8); + error = copyout(&status, args->status, sizeof(status)); } - return 0; + return (error); } #endif /*!__alpha__*/ @@ -831,8 +822,8 @@ linux_wait4(struct linux_wait4_args *args) { struct thread *td = curthread; struct proc *p = td->td_proc; - struct wait_args bsd_args; - int error, tmpstat; + struct rusage rusage; + int error, options, status; KKASSERT(p); @@ -842,37 +833,31 @@ linux_wait4(struct linux_wait4_args *args) args->pid, (void *)args->status, args->options, (void *)args->rusage); #endif - - bsd_args.sysmsg_result = 0; - bsd_args.pid = args->pid; - bsd_args.status = args->status; - bsd_args.options = (args->options & (WNOHANG | WUNTRACED)); + options = args->options & (WNOHANG | WUNTRACED); /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ if (args->options & __WCLONE) - bsd_args.options |= WLINUXCLONE; - bsd_args.rusage = (struct rusage *)args->rusage; - - if ((error = wait4(&bsd_args)) != 0) - return error; - args->sysmsg_result = bsd_args.sysmsg_result; - - SIGDELSET(p->p_siglist, SIGCHLD); - - if (args->status) { - if ((error = copyin((caddr_t)args->status, &tmpstat, - sizeof(int))) != 0) - return error; - tmpstat &= 0xffff; - if (WIFSIGNALED(tmpstat)) - tmpstat = (tmpstat & 0xffffff80) | - BSD_TO_LINUX_SIGNAL(WTERMSIG(tmpstat)); - else if (WIFSTOPPED(tmpstat)) - tmpstat = (tmpstat & 0xffff00ff) | - (BSD_TO_LINUX_SIGNAL(WSTOPSIG(tmpstat)) << 8); - return copyout(&tmpstat, (caddr_t)args->status, sizeof(int)); + options |= WLINUXCLONE; + + error = kern_wait(args->pid, args->status ? &status : NULL, options, + args->rusage ? &rusage : NULL, &args->sysmsg_result); + + if (error == 0) + SIGDELSET(p->p_siglist, SIGCHLD); + + if (error == 0 && args->status) { + status &= 0xffff; + if (WIFSIGNALED(status)) + status = (status & 0xffffff80) | + BSD_TO_LINUX_SIGNAL(WTERMSIG(status)); + else if (WIFSTOPPED(status)) + status = (status & 0xffff00ff) | + (BSD_TO_LINUX_SIGNAL(WSTOPSIG(status)) << 8); + error = copyout(&status, args->status, sizeof(status)); } + if (error == 0 && args->rusage) + error = copyout(&rusage, args->rusage, sizeof(rusage)); - return 0; + return (error); } int @@ -1100,104 +1085,93 @@ linux_getgroups(struct linux_getgroups_args *args) int linux_setrlimit(struct linux_setrlimit_args *args) { - struct __setrlimit_args bsd; - struct l_rlimit rlim; + struct l_rlimit linux_rlim; + struct rlimit rlim; + u_int which; int error; - caddr_t sg = stackgap_init(); #ifdef DEBUG if (ldebug(setrlimit)) printf(ARGS(setrlimit, "%d, %p"), args->resource, (void *)args->rlim); #endif - if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); - - bsd.which = linux_to_bsd_resource[args->resource]; - if (bsd.which == -1) + which = linux_to_bsd_resource[args->resource]; + if (which == -1) return (EINVAL); - error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim)); + error = copyin(args->rlim, &linux_rlim, sizeof(linux_rlim)); if (error) return (error); + rlim.rlim_cur = (rlim_t)linux_rlim.rlim_cur; + rlim.rlim_max = (rlim_t)linux_rlim.rlim_max; + + error = kern_setrlimit(which, &rlim); - bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); - bsd.rlp->rlim_cur = (rlim_t)rlim.rlim_cur; - bsd.rlp->rlim_max = (rlim_t)rlim.rlim_max; - bsd.sysmsg_result = 0; - error = setrlimit(&bsd); - args->sysmsg_result = bsd.sysmsg_result; return(error); } int linux_old_getrlimit(struct linux_old_getrlimit_args *args) { - struct __getrlimit_args bsd; - struct l_rlimit rlim; + struct l_rlimit linux_rlim; + struct rlimit rlim; + u_int which; int error; - caddr_t sg = stackgap_init(); #ifdef DEBUG if (ldebug(old_getrlimit)) printf(ARGS(old_getrlimit, "%d, %p"), args->resource, (void *)args->rlim); #endif - if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); - - bsd.which = linux_to_bsd_resource[args->resource]; - if (bsd.which == -1) + which = linux_to_bsd_resource[args->resource]; + if (which == -1) return (EINVAL); - bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); - bsd.sysmsg_result = 0; - error = getrlimit(&bsd); - if (error) - return (error); - args->sysmsg_result = bsd.sysmsg_result; - rlim.rlim_cur = (unsigned long)bsd.rlp->rlim_cur; - if (rlim.rlim_cur == ULONG_MAX) - rlim.rlim_cur = LONG_MAX; - rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max; - if (rlim.rlim_max == ULONG_MAX) - rlim.rlim_max = LONG_MAX; - return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim))); + error = kern_getrlimit(which, &rlim); + + if (error == 0) { + linux_rlim.rlim_cur = (l_ulong)rlim.rlim_cur; + if (linux_rlim.rlim_cur == ULONG_MAX) + linux_rlim.rlim_cur = LONG_MAX; + linux_rlim.rlim_max = (l_ulong)rlim.rlim_max; + if (linux_rlim.rlim_max == ULONG_MAX) + linux_rlim.rlim_max = LONG_MAX; + error = copyout(&linux_rlim, args->rlim, sizeof(rlim)); + } + return (error); } int linux_getrlimit(struct linux_getrlimit_args *args) { - struct __getrlimit_args bsd; - struct l_rlimit rlim; + struct l_rlimit linux_rlim; + struct rlimit rlim; + u_int which; int error; - caddr_t sg = stackgap_init(); #ifdef DEBUG if (ldebug(getrlimit)) printf(ARGS(getrlimit, "%d, %p"), args->resource, (void *)args->rlim); #endif - if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); - - bsd.which = linux_to_bsd_resource[args->resource]; - if (bsd.which == -1) + which = linux_to_bsd_resource[args->resource]; + if (which == -1) return (EINVAL); - bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); - bsd.sysmsg_result = 0; - error = getrlimit(&bsd); - if (error) - return (error); - args->sysmsg_result = bsd.sysmsg_result; + error = kern_getrlimit(which, &rlim); - rlim.rlim_cur = (l_ulong)bsd.rlp->rlim_cur; - rlim.rlim_max = (l_ulong)bsd.rlp->rlim_max; - return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim))); + if (error == 0) { + linux_rlim.rlim_cur = (l_ulong)rlim.rlim_cur; + linux_rlim.rlim_max = (l_ulong)rlim.rlim_max; + error = copyout(&linux_rlim, args->rlim, sizeof(rlim)); + } + return (error); } #endif /*!__alpha__*/ diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index d07d941c31..b4078b06a4 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -37,7 +37,7 @@ * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 * $FreeBSD: src/sys/kern/kern_exit.c,v 1.92.2.11 2003/01/13 22:51:16 dillon Exp $ - * $DragonFly: src/sys/kern/kern_exit.c,v 1.26 2003/10/18 20:41:08 dillon Exp $ + * $DragonFly: src/sys/kern/kern_exit.c,v 1.27 2003/11/03 15:57:33 daver Exp $ */ #include "opt_compat.h" @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -77,8 +78,6 @@ MALLOC_DEFINE(M_ZOMBIE, "zombie", "zombie proc status"); static MALLOC_DEFINE(M_ATEXIT, "atexit", "atexit callback"); -static int wait1 (struct wait_args *, int); - /* * callout list for things to do at exit time */ @@ -381,29 +380,20 @@ exit1(int rv) cpu_proc_exit(); } -#ifdef COMPAT_43 -/* - * owait() - * - * owait_args(int dummy) - */ int -owait(struct owait_args *uap) +wait4(struct wait_args *uap) { - struct wait_args w; + struct rusage rusage; + int error, status; - w.options = 0; - w.rusage = NULL; - w.pid = WAIT_ANY; - w.status = NULL; - return (wait1(&w, 1)); -} -#endif /* COMPAT_43 */ + error = kern_wait(uap->pid, uap->status ? &status : NULL, + uap->options, uap->rusage ? &rusage : NULL, &uap->sysmsg_fds[0]); -int -wait4(struct wait_args *uap) -{ - return (wait1(uap, 0)); + if (error == 0 && uap->status) + error = copyout(&status, uap->status, sizeof(*uap->status)); + if (error == 0 && uap->rusage) + error = copyout(&rusage, uap->rusage, sizeof(*uap->rusage)); + return (error); } /* @@ -411,22 +401,23 @@ wait4(struct wait_args *uap) * * wait_args(int pid, int *status, int options, struct rusage *rusage) */ -static int -wait1(struct wait_args *uap, int compat) +int +kern_wait(pid_t pid, int *status, int options, struct rusage *rusage, int *res) { - struct proc *q = curproc; + struct thread *td = curthread; + struct proc *q = td->td_proc; struct proc *p, *t; - int status, nfound, error; + int nfound, error; - if (uap->pid == 0) - uap->pid = -q->p_pgid; - if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) + if (pid == 0) + pid = -q->p_pgid; + if (options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) return (EINVAL); loop: nfound = 0; LIST_FOREACH(p, &q->p_children, p_sibling) { - if (uap->pid != WAIT_ANY && - p->p_pid != uap->pid && p->p_pgid != -uap->pid) + if (pid != WAIT_ANY && + p->p_pid != pid && p->p_pgid != -pid) continue; /* This special case handles a kthread spawned by linux_clone @@ -436,7 +427,7 @@ loop: * and the WLINUXCLONE option signifies we want to wait for threads * and not processes. */ - if ((p->p_sigparent != SIGCHLD) ^ ((uap->options & WLINUXCLONE) != 0)) + if ((p->p_sigparent != SIGCHLD) ^ ((options & WLINUXCLONE) != 0)) continue; nfound++; @@ -472,21 +463,12 @@ loop: ESTCPULIM(curproc->p_estcpu + p->p_estcpu); } - uap->sysmsg_fds[0] = p->p_pid; -#ifdef COMPAT_43 - if (compat) - uap->sysmsg_fds[1] = p->p_xstat; - else -#endif - if (uap->status) { - status = p->p_xstat; /* convert to int */ - if ((error = copyout((caddr_t)&status, - (caddr_t)uap->status, sizeof(status)))) - return (error); - } - if (uap->rusage && (error = copyout((caddr_t)p->p_ru, - (caddr_t)uap->rusage, sizeof (struct rusage)))) - return (error); + /* Take care of our return values. */ + *res = p->p_pid; + if (status) + *status = p->p_xstat; + if (rusage) + *rusage = *p->p_ru; /* * If we got the child via a ptrace 'attach', * we need to give it back to the old parent. @@ -506,7 +488,7 @@ loop: /* * Decrement the count of procs running with this uid. */ - (void)chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); + chgproccnt(p->p_ucred->cr_ruidinfo, -1, 0); /* * Free up credentials. @@ -541,31 +523,26 @@ loop: return (0); } if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && - (p->p_flag & P_TRACED || uap->options & WUNTRACED)) { + (p->p_flag & P_TRACED || options & WUNTRACED)) { p->p_flag |= P_WAITED; - uap->sysmsg_fds[0] = p->p_pid; -#ifdef COMPAT_43 - if (compat) { - uap->sysmsg_fds[1] = W_STOPCODE(p->p_xstat); - error = 0; - } else -#endif - if (uap->status) { - status = W_STOPCODE(p->p_xstat); - error = copyout((caddr_t)&status, - (caddr_t)uap->status, sizeof(status)); - } else - error = 0; - return (error); + + *res = p->p_pid; + if (status) + *status = p->p_xstat; + /* Zero rusage so we get something consistent. */ + if (rusage) + bzero(rusage, sizeof(rusage)); + return (0); } } if (nfound == 0) return (ECHILD); - if (uap->options & WNOHANG) { - uap->sysmsg_fds[0] = 0; + if (options & WNOHANG) { + *res = 0; return (0); } - if ((error = tsleep((caddr_t)q, PCATCH, "wait", 0))) + error = tsleep((caddr_t)q, PCATCH, "wait", 0); + if (error) return (error); goto loop; } diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index 9dfbcf7218..29ab313b9e 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -37,7 +37,7 @@ * * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 * $FreeBSD: src/sys/kern/kern_resource.c,v 1.55.2.5 2001/11/03 01:41:08 ps Exp $ - * $DragonFly: src/sys/kern/kern_resource.c,v 1.14 2003/08/26 21:09:02 rob Exp $ + * $DragonFly: src/sys/kern/kern_resource.c,v 1.15 2003/11/03 15:57:33 daver Exp $ */ #include "opt_compat.h" @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -273,57 +274,23 @@ rtprio(struct rtprio_args *uap) } } -#if defined(COMPAT_43) || defined(COMPAT_SUNOS) -/* ARGSUSED */ -int -osetrlimit(struct osetrlimit_args *uap) -{ - struct orlimit olim; - struct rlimit lim; - int error; - - if ((error = - copyin((caddr_t)uap->rlp, (caddr_t)&olim, sizeof(struct orlimit)))) - return (error); - lim.rlim_cur = olim.rlim_cur; - lim.rlim_max = olim.rlim_max; - return (dosetrlimit(uap->which, &lim)); -} - -/* ARGSUSED */ -int -ogetrlimit(struct ogetrlimit_args *uap) -{ - struct proc *p = curproc; - struct orlimit olim; - - if (uap->which >= RLIM_NLIMITS) - return (EINVAL); - olim.rlim_cur = p->p_rlimit[uap->which].rlim_cur; - if (olim.rlim_cur == -1) - olim.rlim_cur = 0x7fffffff; - olim.rlim_max = p->p_rlimit[uap->which].rlim_max; - if (olim.rlim_max == -1) - olim.rlim_max = 0x7fffffff; - return (copyout((caddr_t)&olim, (caddr_t)uap->rlp, sizeof(olim))); -} -#endif /* COMPAT_43 || COMPAT_SUNOS */ - -/* ARGSUSED */ int setrlimit(struct __setrlimit_args *uap) { struct rlimit alim; int error; - if ((error = - copyin((caddr_t)uap->rlp, (caddr_t)&alim, sizeof (struct rlimit)))) + error = copyin(uap->rlp, &alim, sizeof(alim)); + if (error) return (error); - return (dosetrlimit(uap->which, &alim)); + + error = kern_setrlimit(uap->which, &alim); + + return (error); } int -dosetrlimit(u_int which, struct rlimit *limp) +kern_setrlimit(u_int which, struct rlimit *limp) { struct proc *p = curproc; struct rlimit *alimp; @@ -423,16 +390,34 @@ dosetrlimit(u_int which, struct rlimit *limp) return (0); } -/* ARGSUSED */ +/* + * The rlimit indexed by which is returned in the second argument. + */ int -getrlimit(struct __getrlimit_args *uap) +kern_getrlimit(u_int which, struct rlimit *limp) { - struct proc *p = curproc; + struct thread *td = curthread; + struct proc *p = td->td_proc; - if (uap->which >= RLIM_NLIMITS) + if (which >= RLIM_NLIMITS) return (EINVAL); - return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp, - sizeof (struct rlimit))); + + *limp = p->p_rlimit[which]; + + return (0); +} + +int +getrlimit(struct __getrlimit_args *uap) +{ + struct rlimit lim; + int error; + + error = kern_getrlimit(uap->which, &lim); + + if (error == 0) + error = copyout(&lim, uap->rlp, sizeof(*uap->rlp)); + return error; } /* diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index b27b12f40a..a69ac3df30 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -37,12 +37,9 @@ * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $ - * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.21 2003/10/21 01:05:09 daver Exp $ + * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.22 2003/11/03 15:57:33 daver Exp $ */ -/* For 4.3 integer FS ID compatibility */ -#include "opt_compat.h" - #include #include #include @@ -109,9 +106,6 @@ mount(struct mount_args *uap) struct vfsconf *vfsp; int error, flag = 0, flag2 = 0; struct vattr va; -#ifdef COMPAT_43 - u_long fstypenum; -#endif struct nameidata nd; char fstypename[MFSNAMELEN]; @@ -202,24 +196,6 @@ mount(struct mount_args *uap) vput(vp); return (ENOTDIR); } -#ifdef COMPAT_43 - /* - * Historically filesystem types were identified by number. If we - * get an integer for the filesystem type instead of a string, we - * check to see if it matches one of the historic filesystem types. - */ - fstypenum = (uintptr_t)SCARG(uap, type); - if (fstypenum < maxvfsconf) { - for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) - if (vfsp->vfc_typenum == fstypenum) - break; - if (vfsp == NULL) { - vput(vp); - return (ENODEV); - } - strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); - } else -#endif /* COMPAT_43 */ if ((error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) != 0) { vput(vp); return (error); @@ -609,50 +585,56 @@ quotactl(struct quotactl_args *uap) SCARG(uap, arg), td)); } -/* - * statfs_args(char *path, struct statfs *buf) - * - * Get filesystem statistics. - */ -/* ARGSUSED */ int -statfs(struct statfs_args *uap) +kern_statfs(struct nameidata *nd, struct statfs *buf) { struct thread *td = curthread; struct mount *mp; struct statfs *sp; int error; - struct nameidata nd; - struct statfs sb; - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + error = namei(nd); + if (error) return (error); - mp = nd.ni_vp->v_mount; + mp = nd->ni_vp->v_mount; sp = &mp->mnt_stat; - NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(nd.ni_vp); + NDFREE(nd, NDF_ONLY_PNBUF); + vrele(nd->ni_vp); error = VFS_STATFS(mp, sp, td); if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser(td)) { - bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); - sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; - sp = &sb; - } - return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); + bcopy(sp, buf, sizeof(*buf)); + /* Only root should have access to the fsid's. */ + if (suser(td)) + buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; + return (0); } /* - * fstatfs_args(int fd, struct statfs *buf) + * statfs_args(char *path, struct statfs *buf) * * Get filesystem statistics. */ -/* ARGSUSED */ int -fstatfs(struct fstatfs_args *uap) +statfs(struct statfs_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + struct statfs buf; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_statfs(&nd, &buf); + + if (error == 0) + error = copyout(&buf, uap->buf, sizeof(*uap->buf)); + return (error); +} + +int +kern_fstatfs(int fd, struct statfs *buf) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -660,10 +642,10 @@ fstatfs(struct fstatfs_args *uap) struct mount *mp; struct statfs *sp; int error; - struct statfs sb; KKASSERT(p); - if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) + error = getvnode(p->p_fd, fd, &fp); + if (error) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; if (mp == NULL) @@ -673,12 +655,29 @@ fstatfs(struct fstatfs_args *uap) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser(td)) { - bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); - sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; - sp = &sb; - } - return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); + bcopy(sp, buf, sizeof(*buf)); + /* Only root should have access to the fsid's. */ + if (suser(td)) + buf->f_fsid.val[0] = buf->f_fsid.val[1] = 0; + return (0); +} + +/* + * fstatfs_args(int fd, struct statfs *buf) + * + * Get filesystem statistics. + */ +int +fstatfs(struct fstatfs_args *uap) +{ + struct statfs buf; + int error; + + error = kern_fstatfs(uap->fd, &buf); + + if (error == 0) + error = copyout(&buf, uap->buf, sizeof(*uap->buf)); + return (error); } /* @@ -787,29 +786,41 @@ fchdir(struct fchdir_args *uap) return (0); } +int +kern_chdir(struct nameidata *nd) +{ + struct thread *td = curthread; + struct proc *p = td->td_proc; + struct filedesc *fdp = p->p_fd; + int error; + + error = change_dir(nd, td); + if (error) + return (error); + NDFREE(nd, NDF_ONLY_PNBUF); + vrele(fdp->fd_cdir); + fdp->fd_cdir = nd->ni_vp; + return (0); +} + /* * chdir_args(char *path) * * Change current working directory (``.''). */ -/* ARGSUSED */ int chdir(struct chdir_args *uap) { struct thread *td = curthread; - struct proc *p = td->td_proc; - struct filedesc *fdp = p->p_fd; - int error; struct nameidata nd; + int error; NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = change_dir(&nd, td)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - vrele(fdp->fd_cdir); - fdp->fd_cdir = nd.ni_vp; - return (0); + uap->path, td); + + error = kern_chdir(&nd); + + return (error); } /* @@ -912,27 +923,19 @@ change_dir(struct nameidata *ndp, struct thread *td) return (error); } -/* - * open_args(char *path, int flags, int mode) - * - * Check permissions, allocate an open file structure, - * and call the device open routine if any. - */ int -open(struct open_args *uap) +kern_open(struct nameidata *nd, int oflags, int mode, int *res) { struct thread *td = curthread; struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; - int cmode, flags, oflags; + int cmode, flags; struct file *nfp; int type, indx, error; struct flock lf; - struct nameidata nd; - oflags = SCARG(uap, flags); if ((oflags & O_ACCMODE) == O_ACCMODE) return (EINVAL); flags = FFLAGS(oflags); @@ -940,16 +943,14 @@ open(struct open_args *uap) if (error) return (error); fp = nfp; - cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, - SCARG(uap, path), td); + cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; p->p_dupfd = -indx - 1; /* XXX check for fdopen */ /* * Bump the ref count to prevent another process from closing * the descriptor while we are blocked in vn_open() */ fhold(fp); - error = vn_open(&nd, flags, cmode); + error = vn_open(nd, flags, cmode); if (error) { /* * release our own reference @@ -965,7 +966,7 @@ open(struct open_args *uap) p->p_dupfd >= 0 && /* XXX from fdopen */ (error = dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { - uap->sysmsg_result = indx; + *res = indx; return (0); } /* @@ -982,8 +983,8 @@ open(struct open_args *uap) return (error); } p->p_dupfd = 0; - NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; + NDFREE(nd, NDF_ONLY_PNBUF); + vp = nd->ni_vp; /* * There should be 2 references on the file, one from the descriptor @@ -999,7 +1000,7 @@ open(struct open_args *uap) VOP_UNLOCK(vp, 0, td); vn_close(vp, flags & FMASK, td); fdrop(fp, td); - uap->sysmsg_result = indx; + *res = indx; return 0; } @@ -1046,40 +1047,32 @@ open(struct open_args *uap) * descriptor table intact. */ fdrop(fp, td); - uap->sysmsg_result = indx; + *res = indx; return (0); } -#ifdef COMPAT_43 /* - * ocreat(char *path, int mode) + * open_args(char *path, int flags, int mode) * - * Create a file. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. */ int -ocreat(struct ocreat_args *uap) +open(struct open_args *uap) { - struct open_args /* { - syscallarg(char *) path; - syscallarg(int) flags; - syscallarg(int) mode; - } */ nuap; + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); - SCARG(&nuap, path) = SCARG(uap, path); - SCARG(&nuap, mode) = SCARG(uap, mode); - SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; - return (open(&nuap)); + error = kern_open(&nd, uap->flags, uap->mode, &uap->sysmsg_result); + + return (error); } -#endif /* COMPAT_43 */ -/* - * mknod_args(char *path, int mode, int dev) - * - * Create a special file. - */ -/* ARGSUSED */ int -mknod(struct mknod_args *uap) +kern_mknod(struct nameidata *nd, int mode, int dev) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -1087,11 +1080,10 @@ mknod(struct mknod_args *uap) struct vattr vattr; int error; int whiteout = 0; - struct nameidata nd; KKASSERT(p); - switch (SCARG(uap, mode) & S_IFMT) { + switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: error = suser(td); @@ -1103,20 +1095,19 @@ mknod(struct mknod_args *uap) if (error) return (error); bwillwrite(); - NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + error = namei(nd); + if (error) return (error); - vp = nd.ni_vp; + vp = nd->ni_vp; if (vp != NULL) error = EEXIST; else { VATTR_NULL(&vattr); - vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; - vattr.va_rdev = SCARG(uap, dev); + vattr.va_mode = (mode & ALLPERMS) &~ p->p_fd->fd_cmask; + vattr.va_rdev = dev; whiteout = 0; - switch (SCARG(uap, mode) & S_IFMT) { + switch (mode & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; @@ -1134,29 +1125,50 @@ mknod(struct mknod_args *uap) break; } } - if (!error) { - VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE); + if (error == 0) { + VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE); if (whiteout) - error = VOP_WHITEOUT(nd.ni_dvp, NCPNULL, &nd.ni_cnd, NAMEI_CREATE); + error = VOP_WHITEOUT(nd->ni_dvp, NCPNULL, + &nd->ni_cnd, NAMEI_CREATE); else { - error = VOP_MKNOD(nd.ni_dvp, NCPNULL, &nd.ni_vp, - &nd.ni_cnd, &vattr); + error = VOP_MKNOD(nd->ni_dvp, NCPNULL, &nd->ni_vp, + &nd->ni_cnd, &vattr); if (error == 0) - vput(nd.ni_vp); + vput(nd->ni_vp); } - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_dvp); + NDFREE(nd, NDF_ONLY_PNBUF); + vput(nd->ni_dvp); } else { - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); + NDFREE(nd, NDF_ONLY_PNBUF); + if (nd->ni_dvp == vp) + vrele(nd->ni_dvp); else - vput(nd.ni_dvp); + vput(nd->ni_dvp); if (vp) vrele(vp); } - ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); - ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); + ASSERT_VOP_UNLOCKED(nd->ni_dvp, "mknod"); + ASSERT_VOP_UNLOCKED(nd->.ni_vp, "mknod"); + return (error); +} + +/* + * mknod_args(char *path, int mode, int dev) + * + * Create a special file. + */ +int +mknod(struct mknod_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path, + td); + + error = kern_mknod(&nd, uap->mode, uap->dev); + return (error); } @@ -1201,103 +1213,129 @@ mkfifo(struct mkfifo_args *uap) return (error); } -/* - * link_args(char *path, char *link) - * - * Make a hard file link. - */ -/* ARGSUSED */ int -link(struct link_args *uap) +kern_link(struct nameidata *nd, struct nameidata *linknd) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vnode *vp; - struct nameidata nd; int error; bwillwrite(); - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_NOOBJ, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + error = namei(nd); + if (error) return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; + NDFREE(nd, NDF_ONLY_PNBUF); + vp = nd->ni_vp; if (vp->v_type == VDIR) error = EPERM; /* POSIX */ else { - NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, link), td); - error = namei(&nd); - if (!error) { - if (nd.ni_vp != NULL) { - if (nd.ni_vp) - vrele(nd.ni_vp); + error = namei(linknd); + if (error == 0) { + if (linknd->ni_vp != NULL) { + if (linknd->ni_vp) + vrele(linknd->ni_vp); error = EEXIST; } else { - VOP_LEASE(nd.ni_dvp, td, p->p_ucred, + VOP_LEASE(linknd->ni_dvp, td, p->p_ucred, LEASE_WRITE); VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - error = VOP_LINK(nd.ni_dvp, NCPNULL, vp, &nd.ni_cnd); + error = VOP_LINK(linknd->ni_dvp, NCPNULL, vp, + &linknd->ni_cnd); } - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); + NDFREE(linknd, NDF_ONLY_PNBUF); + if (linknd->ni_dvp == linknd->ni_vp) + vrele(linknd->ni_dvp); else - vput(nd.ni_dvp); + vput(linknd->ni_dvp); + ASSERT_VOP_UNLOCKED(linknd->ni_dvp, "link"); + ASSERT_VOP_UNLOCKED(linknd->ni_vp, "link"); } } vrele(vp); - ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); - ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); return (error); } /* - * symlink(char *path, char *link) + * link_args(char *path, char *link) * - * Make a symbolic link. + * Make a hard file link. */ -/* ARGSUSED */ int -symlink(struct symlink_args *uap) +link(struct link_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd, linknd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_NOOBJ, UIO_USERSPACE, + uap->path, td); + NDINIT(&linknd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, + UIO_USERSPACE, uap->link, td); + + error = kern_link(&nd, &linknd); + + return (error); +} + +int +kern_symlink(char *path, struct nameidata *nd) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vattr vattr; - char *path; int error; - struct nameidata nd; - path = zalloc(namei_zone); - if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) - goto out; bwillwrite(); - NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, UIO_USERSPACE, - SCARG(uap, link), td); - if ((error = namei(&nd)) != 0) - goto out; - if (nd.ni_vp) { - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); + error = namei(nd); + if (error) + return (error); + if (nd->ni_vp) { + NDFREE(nd, NDF_ONLY_PNBUF); + if (nd->ni_dvp == nd->ni_vp) + vrele(nd->ni_dvp); else - vput(nd.ni_dvp); - vrele(nd.ni_vp); - error = EEXIST; - goto out; + vput(nd->ni_dvp); + vrele(nd->ni_vp); + return (EEXIST); } VATTR_NULL(&vattr); vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; - VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE); - error = VOP_SYMLINK(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, &vattr, path); - NDFREE(&nd, NDF_ONLY_PNBUF); + VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE); + error = VOP_SYMLINK(nd->ni_dvp, NCPNULL, &nd->ni_vp, &nd->ni_cnd, + &vattr, path); + NDFREE(nd, NDF_ONLY_PNBUF); if (error == 0) - vput(nd.ni_vp); - vput(nd.ni_dvp); - ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); - ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); -out: + vput(nd->ni_vp); + vput(nd->ni_dvp); + ASSERT_VOP_UNLOCKED(nd->ni_dvp, "symlink"); + ASSERT_VOP_UNLOCKED(nd->ni_vp, "symlink"); + + return (error); +} + +/* + * symlink(char *path, char *link) + * + * Make a symbolic link. + */ +int +symlink(struct symlink_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + char *path; + int error; + + path = zalloc(namei_zone); + error = copyinstr(uap->path, path, MAXPATHLEN, NULL); + if (error) + return (error); + NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT | CNP_NOOBJ, UIO_USERSPACE, + uap->link, td); + + error = kern_symlink(path, &nd); + zfree(namei_zone, path); return (error); } @@ -1343,25 +1381,19 @@ undelete(struct undelete_args *uap) return (error); } -/* - * unlink_args(char *path) - * - * Delete a name from the filesystem. - */ int -unlink(struct unlink_args *uap) +kern_unlink(struct nameidata *nd) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vnode *vp; int error; - struct nameidata nd; bwillwrite(); - NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + error = namei(nd); + if (error) return (error); - vp = nd.ni_vp; + vp = nd->ni_vp; VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); @@ -1377,101 +1409,101 @@ unlink(struct unlink_args *uap) error = EBUSY; } - if (!error) { - VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE); - error = VOP_REMOVE(nd.ni_dvp, NCPNULL, vp, &nd.ni_cnd); + if (error == 0) { + VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE); + error = VOP_REMOVE(nd->ni_dvp, NCPNULL, vp, &nd->ni_cnd); } - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); + NDFREE(nd, NDF_ONLY_PNBUF); + if (nd->ni_dvp == vp) + vrele(nd->ni_dvp); else - vput(nd.ni_dvp); + vput(nd->ni_dvp); if (vp != NULLVP) vput(vp); - ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); - ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); + ASSERT_VOP_UNLOCKED(nd->ni_dvp, "unlink"); + ASSERT_VOP_UNLOCKED(nd->ni_vp, "unlink"); return (error); } /* - * lseek_args(int fd, int pad, off_t offset, int whence) + * unlink_args(char *path) * - * Reposition read/write file offset. + * Delete a name from the filesystem. */ int -lseek(struct lseek_args *uap) +unlink(struct unlink_args *uap) { struct thread *td = curthread; - struct proc *p = td->td_proc; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path, + td); + + error = kern_unlink(&nd); + + return (error); +} + +int +kern_lseek(int fd, off_t offset, int whence, int *res) +{ + struct thread *td = curthread; + struct proc *p = td->td_proc; struct filedesc *fdp = p->p_fd; struct file *fp; struct vattr vattr; int error; - if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || - (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) + if (fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) return (ESPIPE); - switch (SCARG(uap, whence)) { + switch (whence) { case L_INCR: - fp->f_offset += SCARG(uap, offset); + fp->f_offset += offset; break; case L_XTND: error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, td); if (error) return (error); - fp->f_offset = SCARG(uap, offset) + vattr.va_size; + fp->f_offset = offset + vattr.va_size; break; case L_SET: - fp->f_offset = SCARG(uap, offset); + fp->f_offset = offset; break; default: return (EINVAL); } - uap->sysmsg_offset = fp->f_offset; + *res = fp->f_offset; return (0); } -#if defined(COMPAT_43) || defined(COMPAT_SUNOS) /* - * Reposition read/write file offset. + * lseek_args(int fd, int pad, off_t offset, int whence) * - * olseek_args(int fd, long offset, int whence) + * Reposition read/write file offset. */ int -olseek(struct olseek_args *uap) +lseek(struct lseek_args *uap) { - struct lseek_args /* { - syscallarg(int) fd; - syscallarg(int) pad; - syscallarg(off_t) offset; - syscallarg(int) whence; - } */ nuap; int error; - SCARG(&nuap, fd) = SCARG(uap, fd); - SCARG(&nuap, offset) = SCARG(uap, offset); - SCARG(&nuap, whence) = SCARG(uap, whence); - error = lseek(&nuap); + error = kern_lseek(uap->fd, uap->offset, uap->whence, + &uap->sysmsg_result); + return (error); } -#endif /* COMPAT_43 */ -/* - * access_args(char *path, int flags) - * - * Check access permissions. - */ int -access(struct access_args *uap) +kern_access(struct nameidata *nd, int aflags) { struct thread *td = curthread; struct proc *p = td->td_proc; struct ucred *cred, *tmpcred; struct vnode *vp; int error, flags; - struct nameidata nd; cred = p->p_ucred; /* @@ -1483,25 +1515,25 @@ access(struct access_args *uap) tmpcred->cr_uid = p->p_ucred->cr_ruid; tmpcred->cr_groups[0] = p->p_ucred->cr_rgid; p->p_ucred = tmpcred; - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + nd->ni_cnd.cn_cred = tmpcred; + error = namei(nd); + if (error) goto out1; - vp = nd.ni_vp; + vp = nd->ni_vp; /* Flags == 0 means only check for existence. */ - if (SCARG(uap, flags)) { + if (aflags) { flags = 0; - if (SCARG(uap, flags) & R_OK) + if (aflags & R_OK) flags |= VREAD; - if (SCARG(uap, flags) & W_OK) + if (aflags & W_OK) flags |= VWRITE; - if (SCARG(uap, flags) & X_OK) + if (aflags & X_OK) flags |= VEXEC; if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) error = VOP_ACCESS(vp, flags, tmpcred, td); } - NDFREE(&nd, NDF_ONLY_PNBUF); + NDFREE(nd, NDF_ONLY_PNBUF); vput(vp); out1: p->p_ucred = cred; @@ -1509,120 +1541,61 @@ out1: return (error); } -#if defined(COMPAT_43) || defined(COMPAT_SUNOS) /* - * ostat_args(char *path, struct ostat *ub) + * access_args(char *path, int flags) * - * Get file status; this version follows links. + * Check access permissions. */ -/* ARGSUSED */ int -ostat(struct ostat_args *uap) +access(struct access_args *uap) { struct thread *td = curthread; - struct stat sb; - struct ostat osb; - int error; struct nameidata nd; + int error; NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = vn_stat(nd.ni_vp, &sb, td); - vput(nd.ni_vp); - if (error) - return (error); - cvtstat(&sb, &osb); - error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); + UIO_USERSPACE, uap->path, td); + + error = kern_access(&nd, uap->flags); + return (error); } -/* - * olstat_args(char *path, struct ostat *ub) - * - * Get file status; this version does not follow links. - */ -/* ARGSUSED */ int -olstat(struct olstat_args *uap) +kern_stat(struct nameidata *nd, struct stat *st) { struct thread *td = curthread; - struct vnode *vp; - struct stat sb; - struct ostat osb; int error; - struct nameidata nd; - NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - vp = nd.ni_vp; - error = vn_stat(vp, &sb, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); + error = namei(nd); if (error) return (error); - cvtstat(&sb, &osb); - error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); + error = vn_stat(nd->ni_vp, st, td); + NDFREE(nd, NDF_ONLY_PNBUF); + vput(nd->ni_vp); return (error); } -/* - * Convert from an old to a new stat structure. - */ -void -cvtstat(st, ost) - struct stat *st; - struct ostat *ost; -{ - ost->st_dev = st->st_dev; - ost->st_ino = st->st_ino; - ost->st_mode = st->st_mode; - ost->st_nlink = st->st_nlink; - ost->st_uid = st->st_uid; - ost->st_gid = st->st_gid; - ost->st_rdev = st->st_rdev; - if (st->st_size < (quad_t)1 << 32) - ost->st_size = st->st_size; - else - ost->st_size = -2; - ost->st_atime = st->st_atime; - ost->st_mtime = st->st_mtime; - ost->st_ctime = st->st_ctime; - ost->st_blksize = st->st_blksize; - ost->st_blocks = st->st_blocks; - ost->st_flags = st->st_flags; - ost->st_gen = st->st_gen; -} -#endif /* COMPAT_43 || COMPAT_SUNOS */ - /* * stat_args(char *path, struct stat *ub) * * Get file status; this version follows links. */ -/* ARGSUSED */ int stat(struct stat_args *uap) { struct thread *td = curthread; - struct stat sb; - int error; struct nameidata nd; + struct stat st; + int error; NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW | CNP_LOCKLEAF | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - error = vn_stat(nd.ni_vp, &sb, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_vp); - if (error) - return (error); - error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); + UIO_USERSPACE, uap->path, td); + + error = kern_stat(&nd, &st); + + if (error == 0) + error = copyout(&st, uap->ub, sizeof(*uap->ub)); return (error); } @@ -1631,27 +1604,21 @@ stat(struct stat_args *uap) * * Get file status; this version does not follow links. */ -/* ARGSUSED */ int lstat(struct lstat_args *uap) { struct thread *td = curthread; - int error; - struct vnode *vp; - struct stat sb; struct nameidata nd; + struct stat st; + int error; NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - vp = nd.ni_vp; - error = vn_stat(vp, &sb, td); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(vp); - if (error) - return (error); - error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); + + error = kern_stat(&nd, &st); + + if (error == 0) + error = copyout(&st, uap->ub, sizeof(*uap->ub)); return (error); } @@ -1760,14 +1727,8 @@ pathconf(struct pathconf_args *uap) return (error); } -/* - * readlink_args(char *path, char *buf, int count) - * - * Return target name of a symbolic link. - */ -/* ARGSUSED */ int -readlink(struct readlink_args *uap) +kern_readlink(struct nameidata *nd, char *buf, int count, int *res) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -1775,30 +1736,49 @@ readlink(struct readlink_args *uap) struct iovec aiov; struct uio auio; int error; - struct nameidata nd; - NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + error = namei(nd); + if (error) return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; + NDFREE(nd, NDF_ONLY_PNBUF); + vp = nd->ni_vp; if (vp->v_type != VLNK) error = EINVAL; else { - aiov.iov_base = SCARG(uap, buf); - aiov.iov_len = SCARG(uap, count); + aiov.iov_base = buf; + aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - auio.uio_resid = SCARG(uap, count); + auio.uio_resid = count; error = VOP_READLINK(vp, &auio, p->p_ucred); } vput(vp); - uap->sysmsg_result = SCARG(uap, count) - auio.uio_resid; + *res = count - auio.uio_resid; + return (error); +} + +/* + * readlink_args(char *path, char *buf, int count) + * + * Return target name of a symbolic link. + */ +int +readlink(struct readlink_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_LOCKLEAF | CNP_NOOBJ, UIO_USERSPACE, + uap->path, td); + + error = kern_readlink(&nd, uap->buf, uap->count, + &uap->sysmsg_result); + return (error); } @@ -1888,6 +1868,20 @@ setfmode(struct vnode *vp, int mode) return error; } +int +kern_chmod(struct nameidata *nd, int mode) +{ + int error; + + error = namei(nd); + if (error) + return (error); + NDFREE(nd, NDF_ONLY_PNBUF); + error = setfmode(nd->ni_vp, mode); + vrele(nd->ni_vp); + return error; +} + /* * chmod_args(char *path, int mode) * @@ -1898,17 +1892,14 @@ int chmod(struct chmod_args *uap) { struct thread *td = curthread; - int error; struct nameidata nd; + int error; - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfmode(nd.ni_vp, SCARG(uap, mode)); - vrele(nd.ni_vp); - return error; + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_chmod(&nd, uap->mode); + + return (error); } /* @@ -1970,26 +1961,36 @@ setfown(struct vnode *vp, uid_t uid, gid_t gid) return error; } +int +kern_chown(struct nameidata *nd, int uid, int gid) +{ + int error; + + error = namei(nd); + if (error) + return (error); + NDFREE(nd, NDF_ONLY_PNBUF); + error = setfown(nd->ni_vp, uid, gid); + vrele(nd->ni_vp); + return (error); +} + /* * chown(char *path, int uid, int gid) * * Set ownership given a path name. */ -/* ARGSUSED */ int chown(struct chown_args *uap) { struct thread *td = curthread; - int error; struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_chown(&nd, uap->uid, uap->gid); - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); - vrele(nd.ni_vp); return (error); } @@ -1998,7 +1999,6 @@ chown(struct chown_args *uap) * * Set ownership given a path name, do not cross symlinks. */ -/* ARGSUSED */ int lchown(struct lchown_args *uap) { @@ -2006,12 +2006,10 @@ lchown(struct lchown_args *uap) int error; struct nameidata nd; - NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setfown(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); - vrele(nd.ni_vp); + NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, uap->path, td); + + error = kern_chown(&nd, uap->uid, uap->gid); + return (error); } @@ -2036,20 +2034,17 @@ fchown(struct fchown_args *uap) } static int -getutimes(const struct timeval *usrtvp, struct timespec *tsp) +getutimes(const struct timeval *tvp, struct timespec *tsp) { struct timeval tv[2]; - int error; - if (usrtvp == NULL) { + if (tvp == NULL) { microtime(&tv[0]); TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); tsp[1] = tsp[0]; } else { - if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) - return (error); - TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); - TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); + TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); + TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); } return 0; } @@ -2074,30 +2069,46 @@ setutimes(struct vnode *vp, const struct timespec *ts, int nullflag) return error; } +int +kern_utimes(struct nameidata *nd, struct timeval *tptr) +{ + struct timespec ts[2]; + int error; + + error = getutimes(tptr, ts); + if (error) + return (error); + error = namei(nd); + if (error) + return (error); + NDFREE(nd, NDF_ONLY_PNBUF); + error = setutimes(nd->ni_vp, ts, tptr == NULL); + vrele(nd->ni_vp); + return (error); +} + /* * utimes_args(char *path, struct timeval *tptr) * * Set the access and modification times of a file. */ -/* ARGSUSED */ int utimes(struct utimes_args *uap) { struct thread *td = curthread; - struct timespec ts[2]; - struct timeval *usrtvp; - int error; + struct timeval tv[2]; struct nameidata nd; + int error; + + if (uap->tptr) { + error = copyin(uap->tptr, tv, sizeof(tv)); + if (error) + return (error); + } + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_utimes(&nd, tv); - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) - return (error); - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setutimes(nd.ni_vp, ts, usrtvp == NULL); - vrele(nd.ni_vp); return (error); } @@ -2106,75 +2117,82 @@ utimes(struct utimes_args *uap) * * Set the access and modification times of a file. */ -/* ARGSUSED */ int lutimes(struct lutimes_args *uap) { struct thread *td = curthread; - struct timespec ts[2]; - struct timeval *usrtvp; - int error; + struct timeval tv[2]; struct nameidata nd; + int error; + + if (uap->tptr) { + error = copyin(uap->tptr, tv, sizeof(tv)); + if (error) + return (error); + } + NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, uap->path, td); + + error = kern_utimes(&nd, tv); - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) - return (error); - NDINIT(&nd, NAMEI_LOOKUP, 0, UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) - return (error); - NDFREE(&nd, NDF_ONLY_PNBUF); - error = setutimes(nd.ni_vp, ts, usrtvp == NULL); - vrele(nd.ni_vp); return (error); } -/* - * futimes_args(int fd, struct timeval *tptr) - * - * Set the access and modification times of a file. - */ -/* ARGSUSED */ int -futimes(struct futimes_args *uap) +kern_futimes(int fd, struct timeval *tptr) { struct thread *td = curthread; struct proc *p = td->td_proc; struct timespec ts[2]; struct file *fp; - struct timeval *usrtvp; int error; - usrtvp = SCARG(uap, tptr); - if ((error = getutimes(usrtvp, ts)) != 0) + error = getutimes(tptr, ts); + if (error) return (error); - if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) + error = getvnode(p->p_fd, fd, &fp); + if (error) return (error); - return setutimes((struct vnode *)fp->f_data, ts, usrtvp == NULL); + error = setutimes((struct vnode *)fp->f_data, ts, tptr == NULL); + return (error); } /* - * truncate(char *path, int pad, off_t length) + * futimes_args(int fd, struct timeval *tptr) * - * Truncate a file given its path name. + * Set the access and modification times of a file. */ -/* ARGSUSED */ int -truncate(struct truncate_args *uap) +futimes(struct futimes_args *uap) +{ + struct timeval tv[2]; + int error; + + if (uap->tptr) { + error = copyin(uap->tptr, tv, sizeof(tv)); + if (error) + return (error); + } + + error = kern_futimes(uap->fd, tv); + + return (error); +} + +int +kern_truncate(struct nameidata* nd, off_t length) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vnode *vp; struct vattr vattr; int error; - struct nameidata nd; - if (uap->length < 0) + if (length < 0) return(EINVAL); - NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + if ((error = namei(nd)) != 0) return (error); - vp = nd.ni_vp; - NDFREE(&nd, NDF_ONLY_PNBUF); + vp = nd->ni_vp; + NDFREE(nd, NDF_ONLY_PNBUF); VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); if (vp->v_type == VDIR) @@ -2182,13 +2200,32 @@ truncate(struct truncate_args *uap) else if ((error = vn_writechk(vp)) == 0 && (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, td)) == 0) { VATTR_NULL(&vattr); - vattr.va_size = SCARG(uap, length); + vattr.va_size = length; error = VOP_SETATTR(vp, &vattr, p->p_ucred, td); } vput(vp); return (error); } +/* + * truncate(char *path, int pad, off_t length) + * + * Truncate a file given its path name. + */ +int +truncate(struct truncate_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_USERSPACE, uap->path, td); + + error = kern_truncate(&nd, uap->length); + + return error; +} + int kern_ftruncate(int fd, off_t length) { @@ -2224,7 +2261,6 @@ kern_ftruncate(int fd, off_t length) * * Truncate a file given a file descriptor. */ -/* ARGSUSED */ int ftruncate(struct ftruncate_args *uap) { @@ -2235,28 +2271,6 @@ ftruncate(struct ftruncate_args *uap) return (error); } -#if defined(COMPAT_43) || defined(COMPAT_SUNOS) -/* - * otruncate_args(char *path, long length) - * - * Truncate a file given its path name. - */ -/* ARGSUSED */ -int -otruncate(struct otruncate_args *uap) -{ - struct truncate_args /* { - syscallarg(char *) path; - syscallarg(int) pad; - syscallarg(off_t) length; - } */ nuap; - - SCARG(&nuap, path) = SCARG(uap, path); - SCARG(&nuap, length) = SCARG(uap, length); - return (truncate(&nuap)); -} -#endif /* COMPAT_43 || COMPAT_SUNOS */ - /* * fsync(int fd) * @@ -2287,45 +2301,33 @@ fsync(struct fsync_args *uap) return (error); } -/* - * rename_args(char *from, char *to) - * - * Rename files. Source and destination must either both be directories, - * or both not be directories. If target is a directory, it must be empty. - */ -/* ARGSUSED */ int -rename(struct rename_args *uap) +kern_rename(struct nameidata *fromnd, struct nameidata *tond) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vnode *tvp, *fvp, *tdvp; - struct nameidata fromnd, tond; int error; bwillwrite(); - NDINIT(&fromnd, NAMEI_DELETE, CNP_WANTPARENT | CNP_SAVESTART, - UIO_USERSPACE, SCARG(uap, from), td); - if ((error = namei(&fromnd)) != 0) + error = namei(fromnd); + if (error) return (error); - fvp = fromnd.ni_vp; - NDINIT(&tond, NAMEI_RENAME, - CNP_LOCKPARENT | CNP_LOCKLEAF | CNP_NOCACHE | - CNP_SAVESTART | CNP_NOOBJ, - UIO_USERSPACE, SCARG(uap, to), td); - if (fromnd.ni_vp->v_type == VDIR) - tond.ni_cnd.cn_flags |= CNP_WILLBEDIR; - if ((error = namei(&tond)) != 0) { + fvp = fromnd->ni_vp; + if (fromnd->ni_vp->v_type == VDIR) + tond->ni_cnd.cn_flags |= CNP_WILLBEDIR; + error = namei(tond); + if (error) { /* Translate error code for rename("dir1", "dir2/."). */ if (error == EISDIR && fvp->v_type == VDIR) error = EINVAL; - NDFREE(&fromnd, NDF_ONLY_PNBUF); - vrele(fromnd.ni_dvp); + NDFREE(fromnd, NDF_ONLY_PNBUF); + vrele(fromnd->ni_dvp); vrele(fvp); goto out1; } - tdvp = tond.ni_dvp; - tvp = tond.ni_vp; + tdvp = tond->ni_dvp; + tvp = tond->ni_vp; if (tvp != NULL) { if (fvp->v_type == VDIR && tvp->v_type != VDIR) { error = ENOTDIR; @@ -2346,108 +2348,140 @@ rename(struct rename_args *uap) out: if (!error) { VOP_LEASE(tdvp, td, p->p_ucred, LEASE_WRITE); - if (fromnd.ni_dvp != tdvp) { - VOP_LEASE(fromnd.ni_dvp, td, p->p_ucred, LEASE_WRITE); + if (fromnd->ni_dvp != tdvp) { + VOP_LEASE(fromnd->ni_dvp, td, p->p_ucred, LEASE_WRITE); } if (tvp) { VOP_LEASE(tvp, td, p->p_ucred, LEASE_WRITE); } - error = VOP_RENAME(fromnd.ni_dvp, NCPNULL, fromnd.ni_vp, &fromnd.ni_cnd, - tond.ni_dvp, NCPNULL, tond.ni_vp, &tond.ni_cnd); - NDFREE(&fromnd, NDF_ONLY_PNBUF); - NDFREE(&tond, NDF_ONLY_PNBUF); + error = VOP_RENAME(fromnd->ni_dvp, NCPNULL, fromnd->ni_vp, + &fromnd->ni_cnd, tond->ni_dvp, NCPNULL, tond->ni_vp, + &tond->ni_cnd); + NDFREE(fromnd, NDF_ONLY_PNBUF); + NDFREE(tond, NDF_ONLY_PNBUF); } else { - NDFREE(&fromnd, NDF_ONLY_PNBUF); - NDFREE(&tond, NDF_ONLY_PNBUF); + NDFREE(fromnd, NDF_ONLY_PNBUF); + NDFREE(tond, NDF_ONLY_PNBUF); if (tdvp == tvp) vrele(tdvp); else vput(tdvp); if (tvp) vput(tvp); - vrele(fromnd.ni_dvp); + vrele(fromnd->ni_dvp); vrele(fvp); } - vrele(tond.ni_startdir); - ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); - ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); - ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); - ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); + vrele(tond->ni_startdir); + ASSERT_VOP_UNLOCKED(fromnd->ni_dvp, "rename"); + ASSERT_VOP_UNLOCKED(fromnd->ni_vp, "rename"); + ASSERT_VOP_UNLOCKED(tond->ni_dvp, "rename"); + ASSERT_VOP_UNLOCKED(tond->ni_vp, "rename"); out1: - if (fromnd.ni_startdir) - vrele(fromnd.ni_startdir); + if (fromnd->ni_startdir) + vrele(fromnd->ni_startdir); if (error == -1) return (0); return (error); } /* - * mkdir_args(char *path, int mode) + * rename_args(char *from, char *to) * - * Make a directory file. + * Rename files. Source and destination must either both be directories, + * or both not be directories. If target is a directory, it must be empty. */ -/* ARGSUSED */ int -mkdir(struct mkdir_args *uap) +rename(struct rename_args *uap) +{ + struct thread *td = curthread; + struct nameidata fromnd, tond; + int error; + + NDINIT(&fromnd, NAMEI_DELETE, CNP_WANTPARENT | CNP_SAVESTART, + UIO_USERSPACE, uap->from, td); + NDINIT(&tond, NAMEI_RENAME, + CNP_LOCKPARENT | CNP_LOCKLEAF | CNP_NOCACHE | + CNP_SAVESTART | CNP_NOOBJ, + UIO_USERSPACE, uap->to, td); + + error = kern_rename(&fromnd, &tond); + + return (error); +} + +int +kern_mkdir(struct nameidata *nd, int mode) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vnode *vp; struct vattr vattr; int error; - struct nameidata nd; bwillwrite(); - NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, - SCARG(uap, path), td); - nd.ni_cnd.cn_flags |= CNP_WILLBEDIR; - if ((error = namei(&nd)) != 0) + nd->ni_cnd.cn_flags |= CNP_WILLBEDIR; + error = namei(nd); + if (error) return (error); - vp = nd.ni_vp; - if (vp != NULL) { - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); + vp = nd->ni_vp; + if (vp) { + NDFREE(nd, NDF_ONLY_PNBUF); + if (nd->ni_dvp == vp) + vrele(nd->ni_dvp); else - vput(nd.ni_dvp); + vput(nd->ni_dvp); vrele(vp); return (EEXIST); } VATTR_NULL(&vattr); vattr.va_type = VDIR; - vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; - VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE); - error = VOP_MKDIR(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, &vattr); - NDFREE(&nd, NDF_ONLY_PNBUF); - vput(nd.ni_dvp); - if (!error) - vput(nd.ni_vp); - ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); - ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); + vattr.va_mode = (mode & ACCESSPERMS) &~ p->p_fd->fd_cmask; + VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE); + error = VOP_MKDIR(nd->ni_dvp, NCPNULL, &nd->ni_vp, &nd->ni_cnd, + &vattr); + NDFREE(nd, NDF_ONLY_PNBUF); + vput(nd->ni_dvp); + if (error == 0) + vput(nd->ni_vp); + ASSERT_VOP_UNLOCKED(nd->ni_dvp, "mkdir"); + ASSERT_VOP_UNLOCKED(nd->ni_vp, "mkdir"); return (error); } /* - * rmdir_args(char *path) + * mkdir_args(char *path, int mode) * - * Remove a directory file. + * Make a directory file. */ /* ARGSUSED */ int -rmdir(struct rmdir_args *uap) +mkdir(struct mkdir_args *uap) +{ + struct thread *td = curthread; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_CREATE, CNP_LOCKPARENT, UIO_USERSPACE, uap->path, + td); + + error = kern_mkdir(&nd, uap->mode); + + return (error); +} + +int +kern_rmdir(struct nameidata *nd) { struct thread *td = curthread; struct proc *p = td->td_proc; struct vnode *vp; int error; - struct nameidata nd; bwillwrite(); - NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT | CNP_LOCKLEAF, UIO_USERSPACE, - SCARG(uap, path), td); - if ((error = namei(&nd)) != 0) + error = namei(nd); + if (error) return (error); - vp = nd.ni_vp; + vp = nd->ni_vp; if (vp->v_type != VDIR) { error = ENOTDIR; goto out; @@ -2455,7 +2489,7 @@ rmdir(struct rmdir_args *uap) /* * No rmdir "." please. */ - if (nd.ni_dvp == vp) { + if (nd->ni_dvp == vp) { error = EINVAL; goto out; } @@ -2465,151 +2499,47 @@ rmdir(struct rmdir_args *uap) if (vp->v_flag & VROOT) error = EBUSY; else { - VOP_LEASE(nd.ni_dvp, td, p->p_ucred, LEASE_WRITE); + VOP_LEASE(nd->ni_dvp, td, p->p_ucred, LEASE_WRITE); VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); - error = VOP_RMDIR(nd.ni_dvp, NCPNULL, nd.ni_vp, &nd.ni_cnd); + error = VOP_RMDIR(nd->ni_dvp, NCPNULL, nd->ni_vp, + &nd->ni_cnd); } out: - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp == vp) - vrele(nd.ni_dvp); + NDFREE(nd, NDF_ONLY_PNBUF); + if (nd->ni_dvp == vp) + vrele(nd->ni_dvp); else - vput(nd.ni_dvp); + vput(nd->ni_dvp); if (vp != NULLVP) vput(vp); - ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); - ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); + ASSERT_VOP_UNLOCKED(nd->ni_dvp, "rmdir"); + ASSERT_VOP_UNLOCKED(nd->ni_vp, "rmdir"); return (error); } -#ifdef COMPAT_43 /* - * ogetdirentries_args(int fd, char *buf, u_int count, long *basep) + * rmdir_args(char *path) * - * Read a block of directory entries in a file system independent format. + * Remove a directory file. */ +/* ARGSUSED */ int -ogetdirentries(struct ogetdirentries_args *uap) +rmdir(struct rmdir_args *uap) { struct thread *td = curthread; - struct proc *p = td->td_proc; - struct vnode *vp; - struct file *fp; - struct uio auio, kuio; - struct iovec aiov, kiov; - struct dirent *dp, *edp; - caddr_t dirbuf; - int error, eofflag, readcnt; - long loff; + struct nameidata nd; + int error; + + NDINIT(&nd, NAMEI_DELETE, CNP_LOCKPARENT | CNP_LOCKLEAF, + UIO_USERSPACE, uap->path, td); + + error = kern_rmdir(&nd); - /* XXX arbitrary sanity limit on `count'. */ - if (SCARG(uap, count) > 64 * 1024) - return (EINVAL); - if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) - return (error); - if ((fp->f_flag & FREAD) == 0) - return (EBADF); - vp = (struct vnode *)fp->f_data; -unionread: - if (vp->v_type != VDIR) - return (EINVAL); - aiov.iov_base = SCARG(uap, buf); - aiov.iov_len = SCARG(uap, count); - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; - auio.uio_resid = SCARG(uap, count); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - loff = auio.uio_offset = fp->f_offset; -# if (BYTE_ORDER != LITTLE_ENDIAN) - if (vp->v_mount->mnt_maxsymlinklen <= 0) { - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, - NULL, NULL); - fp->f_offset = auio.uio_offset; - } else -# endif - { - kuio = auio; - kuio.uio_iov = &kiov; - kuio.uio_segflg = UIO_SYSSPACE; - kiov.iov_len = SCARG(uap, count); - MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); - kiov.iov_base = dirbuf; - error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, - NULL, NULL); - fp->f_offset = kuio.uio_offset; - if (error == 0) { - readcnt = SCARG(uap, count) - kuio.uio_resid; - edp = (struct dirent *)&dirbuf[readcnt]; - for (dp = (struct dirent *)dirbuf; dp < edp; ) { -# if (BYTE_ORDER == LITTLE_ENDIAN) - /* - * The expected low byte of - * dp->d_namlen is our dp->d_type. - * The high MBZ byte of dp->d_namlen - * is our dp->d_namlen. - */ - dp->d_type = dp->d_namlen; - dp->d_namlen = 0; -# else - /* - * The dp->d_type is the high byte - * of the expected dp->d_namlen, - * so must be zero'ed. - */ - dp->d_type = 0; -# endif - if (dp->d_reclen > 0) { - dp = (struct dirent *) - ((char *)dp + dp->d_reclen); - } else { - error = EIO; - break; - } - } - if (dp >= edp) - error = uiomove(dirbuf, readcnt, &auio); - } - FREE(dirbuf, M_TEMP); - } - VOP_UNLOCK(vp, 0, td); - if (error) - return (error); - if (SCARG(uap, count) == auio.uio_resid) { - if (union_dircheckp) { - error = union_dircheckp(td, &vp, fp); - if (error == -1) - goto unionread; - if (error) - return (error); - } - if ((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; - } - } - error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), - sizeof(long)); - uap->sysmsg_result = SCARG(uap, count) - auio.uio_resid; return (error); } -#endif /* COMPAT_43 */ -/* - * getdirentries_args(int fd, char *buf, u_int conut, long *basep) - * - * Read a block of directory entries in a file system independent format. - */ int -getdirentries(struct getdirentries_args *uap) +kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res) { struct thread *td = curthread; struct proc *p = td->td_proc; @@ -2620,7 +2550,7 @@ getdirentries(struct getdirentries_args *uap) long loff; int error, eofflag; - if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) + if ((error = getvnode(p->p_fd, fd, &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) return (EBADF); @@ -2628,14 +2558,14 @@ getdirentries(struct getdirentries_args *uap) unionread: if (vp->v_type != VDIR) return (EINVAL); - aiov.iov_base = SCARG(uap, buf); - aiov.iov_len = SCARG(uap, count); + aiov.iov_base = buf; + aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - auio.uio_resid = SCARG(uap, count); + auio.uio_resid = count; /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); loff = auio.uio_offset = fp->f_offset; @@ -2644,7 +2574,7 @@ unionread: VOP_UNLOCK(vp, 0, td); if (error) return (error); - if (SCARG(uap, count) == auio.uio_resid) { + if (count == auio.uio_resid) { if (union_dircheckp) { error = union_dircheckp(td, &vp, fp); if (error == -1) @@ -2663,11 +2593,29 @@ unionread: goto unionread; } } - if (SCARG(uap, basep) != NULL) { - error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), - sizeof(long)); + if (basep) { + *basep = loff; } - uap->sysmsg_result = SCARG(uap, count) - auio.uio_resid; + *res = count - auio.uio_resid; + return (error); +} + +/* + * getdirentries_args(int fd, char *buf, u_int conut, long *basep) + * + * Read a block of directory entries in a file system independent format. + */ +int +getdirentries(struct getdirentries_args *uap) +{ + long base; + int error; + + error = kern_getdirentries(uap->fd, uap->buf, uap->count, &base, + &uap->sysmsg_result); + + if (error == 0) + error = copyout(&base, uap->basep, sizeof(*uap->basep)); return (error); } @@ -2677,13 +2625,12 @@ unionread: int getdents(struct getdents_args *uap) { - struct getdirentries_args ap; + int error; + + error = kern_getdirentries(uap->fd, uap->buf, uap->count, NULL, + &uap->sysmsg_result); - ap.fd = uap->fd; - ap.buf = uap->buf; - ap.count = uap->count; - ap.basep = NULL; - return getdirentries(&ap); + return (error); } /* diff --git a/sys/sys/kern_syscall.h b/sys/sys/kern_syscall.h index 3e95476258..fc189cae39 100644 --- a/sys/sys/kern_syscall.h +++ b/sys/sys/kern_syscall.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/kern_syscall.h,v 1.9 2003/10/24 14:10:46 daver Exp $ + * $DragonFly: src/sys/sys/kern_syscall.h,v 1.10 2003/11/03 15:57:34 daver Exp $ */ #ifndef _SYS_KERN_SYSCALL_H_ @@ -35,6 +35,9 @@ enum dup_type {DUP_FIXED, DUP_VARIABLE}; union fcntl_dat; struct mbuf; struct msghdr; +struct nameidata; +struct rlimit; +struct rusage; struct sigaction; struct sigaltstack; struct __sigset; @@ -43,6 +46,8 @@ struct sockaddr; struct socket; struct sockopt; struct stat; +struct statfs; +struct timeval; struct uio; struct vnode; @@ -53,6 +58,12 @@ int kern_dup(enum dup_type type, int old, int new, int *res); int kern_fcntl(int fd, int cmd, union fcntl_dat *dat); int kern_fstat(int fd, struct stat *st); +/* + * Prototypes for syscalls in kern/kern_exit.c + */ +int kern_wait(pid_t pid, int *status, int options, struct rusage *rusage, + int *res); + /* * Prototypes for syscalls in kern/kern_sig.c */ @@ -69,6 +80,12 @@ int kern_kill(int sig, int id); int kern_readv(int fd, struct uio *auio, int flags, int *res); int kern_writev(int fd, struct uio *auio, int flags, int *res); +/* + * Prototypes for syscalls in kern/kern_resource.c + */ +int kern_setrlimit(u_int which, struct rlimit *limp); +int kern_getrlimit(u_int which, struct rlimit *limp); + /* * Prototypes for syscalls in kern/uipc_syscalls.c */ @@ -93,6 +110,27 @@ int kern_socketpair(int domain, int type, int protocol, int *sockv); /* * Prototypes for syscalls in kern/vfs_syscalls.c */ +int kern_access(struct nameidata *nd, int aflags); +int kern_chdir(struct nameidata *nd); +int kern_chmod(struct nameidata *nd, int mode); +int kern_chown(struct nameidata *nd, int uid, int gid); +int kern_fstatfs(int fd, struct statfs *buf); int kern_ftruncate(int fd, off_t length); +int kern_futimes(int fd, struct timeval *tptr); +int kern_getdirentries(int fd, char *buf, u_int count, long *basep, int *res); +int kern_link(struct nameidata *nd, struct nameidata *linknd); +int kern_lseek(int fd, off_t offset, int whence, int *res); +int kern_mkdir(struct nameidata *nd, int mode); +int kern_mknod(struct nameidata *nd, int mode, int dev); +int kern_open(struct nameidata *nd, int flags, int mode, int *res); +int kern_readlink(struct nameidata *nd, char *buf, int count, int *res); +int kern_rename(struct nameidata *fromnd, struct nameidata *tond); +int kern_rmdir(struct nameidata *nd); +int kern_stat(struct nameidata *nd, struct stat *st); +int kern_statfs(struct nameidata *nd, struct statfs *buf); +int kern_symlink(char *path, struct nameidata *nd); +int kern_truncate(struct nameidata *nd, off_t length); +int kern_unlink(struct nameidata *nd); +int kern_utimes(struct nameidata *nd, struct timeval *tptr); #endif /* !_SYS_KERN_SYSCALL_H_ */ -- 2.41.0