diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /sys/compat/common/vfs_syscalls_43.c |
initial import of NetBSD tree
Diffstat (limited to 'sys/compat/common/vfs_syscalls_43.c')
-rw-r--r-- | sys/compat/common/vfs_syscalls_43.c | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/sys/compat/common/vfs_syscalls_43.c b/sys/compat/common/vfs_syscalls_43.c new file mode 100644 index 00000000000..b834a9eda84 --- /dev/null +++ b/sys/compat/common/vfs_syscalls_43.c @@ -0,0 +1,510 @@ +/* $NetBSD: vfs_syscalls_43.c,v 1.3 1995/10/07 06:26:31 mycroft Exp $ */ + +/* + * Copyright (c) 1989, 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 + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vfs_syscalls.c 8.28 (Berkeley) 12/10/94 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/filedesc.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/file.h> +#include <sys/vnode.h> +#include <sys/namei.h> +#include <sys/dirent.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/syslog.h> +#include <sys/unistd.h> +#include <sys/resourcevar.h> + +#include <sys/mount.h> +#include <sys/syscallargs.h> + +/* + * Convert from an old to a new stat structure. + */ +static int +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; +} + +/* + * Get file status; this version follows links. + */ +/* ARGSUSED */ +int +compat_43_sys_stat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_stat_args /* { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; + } */ *uap = v; + struct stat sb; + struct ostat osb; + int error; + struct nameidata nd; + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) + return (error); + error = vn_stat(nd.ni_vp, &sb, p); + vput(nd.ni_vp); + if (error) + return (error); + cvtstat(&sb, &osb); + error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); + return (error); +} + + +/* + * Get file status; this version does not follow links. + */ +/* ARGSUSED */ +int +compat_43_sys_lstat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_lstat_args /* { + syscallarg(char *) path; + syscallarg(struct ostat *) ub; + } */ *uap = v; + struct vnode *vp, *dvp; + struct stat sb, sb1; + struct ostat osb; + int error; + struct nameidata nd; + + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, + SCARG(uap, path), p); + if (error = namei(&nd)) + return (error); + /* + * For symbolic links, always return the attributes of its + * containing directory, except for mode, size, and links. + */ + vp = nd.ni_vp; + dvp = nd.ni_dvp; + if (vp->v_type != VLNK) { + if (dvp == vp) + vrele(dvp); + else + vput(dvp); + error = vn_stat(vp, &sb, p); + vput(vp); + if (error) + return (error); + } else { + error = vn_stat(dvp, &sb, p); + vput(dvp); + if (error) { + vput(vp); + return (error); + } + error = vn_stat(vp, &sb1, p); + vput(vp); + if (error) + return (error); + sb.st_mode &= ~S_IFDIR; + sb.st_mode |= S_IFLNK; + sb.st_nlink = sb1.st_nlink; + sb.st_size = sb1.st_size; + sb.st_blocks = sb1.st_blocks; + } + cvtstat(&sb, &osb); + error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); + return (error); +} + + +/* + * Return status information about a file descriptor. + */ +/* ARGSUSED */ +compat_43_sys_fstat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_fstat_args /* { + syscallarg(int) fd; + syscallarg(struct ostat *) sb; + } */ *uap = v; + int fd = SCARG(uap, fd); + register struct filedesc *fdp = p->p_fd; + register struct file *fp; + struct stat ub; + struct ostat oub; + int error; + + if ((u_int)fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[fd]) == NULL) + return (EBADF); + switch (fp->f_type) { + + case DTYPE_VNODE: + error = vn_stat((struct vnode *)fp->f_data, &ub, p); + break; + + case DTYPE_SOCKET: + error = soo_stat((struct socket *)fp->f_data, &ub); + break; + + default: + panic("ofstat"); + /*NOTREACHED*/ + } + cvtstat(&ub, &oub); + if (error == 0) + error = copyout((caddr_t)&oub, (caddr_t)SCARG(uap, sb), + sizeof (oub)); + return (error); +} + + +/* + * Truncate a file given a file descriptor. + */ +/* ARGSUSED */ +int +compat_43_sys_ftruncate(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_ftruncate_args /* { + syscallarg(int) fd; + syscallarg(long) length; + } */ *uap = v; + struct sys_ftruncate_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ nuap; + + SCARG(&nuap, fd) = SCARG(uap, fd); + SCARG(&nuap, length) = SCARG(uap, length); + return (sys_ftruncate(p, &nuap, retval)); +} + +/* + * Truncate a file given its path name. + */ +/* ARGSUSED */ +int +compat_43_sys_truncate(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_truncate_args /* { + syscallarg(char *) path; + syscallarg(long) length; + } */ *uap = v; + struct sys_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 (sys_truncate(p, &nuap, retval)); +} + + +/* + * Reposition read/write file offset. + */ +int +compat_43_sys_lseek(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_lseek_args /* { + syscallarg(int) fd; + syscallarg(long) offset; + syscallarg(int) whence; + } */ *uap = v; + struct sys_lseek_args /* { + syscallarg(int) fd; + syscallarg(int) pad; + syscallarg(off_t) offset; + syscallarg(int) whence; + } */ nuap; + off_t qret; + int error; + + SCARG(&nuap, fd) = SCARG(uap, fd); + SCARG(&nuap, offset) = SCARG(uap, offset); + SCARG(&nuap, whence) = SCARG(uap, whence); + error = sys_lseek(p, &nuap, (register_t *)&qret); + *(long *)retval = qret; + return (error); +} + + +/* + * Create a file. + */ +int +compat_43_sys_creat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_creat_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap = v; + struct sys_open_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ nuap; + + SCARG(&nuap, path) = SCARG(uap, path); + SCARG(&nuap, mode) = SCARG(uap, mode); + SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; + return (sys_open(p, &nuap, retval)); +} + +/*ARGSUSED*/ +int +compat_43_sys_quota(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + + return (ENOSYS); +} + + +/* + * Read a block of directory entries in a file system independent format. + */ +int +compat_43_sys_getdirentries(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct compat_43_sys_getdirentries_args /* { + syscallarg(int) fd; + syscallarg(char *) buf; + syscallarg(u_int) count; + syscallarg(long *) basep; + } */ *uap = v; + register 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; + + if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) + 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_procp = p; + auio.uio_resid = SCARG(uap, count); + VOP_LOCK(vp); + 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, + (u_long *)0, 0); + 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, + (u_long *)0, 0); + 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); + if (error) + return (error); + +#ifdef UNION +{ + extern int (**union_vnodeop_p)(); + extern struct vnode *union_dircache __P((struct vnode *)); + + if ((SCARG(uap, 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); + VOP_UNLOCK(lvp); + + if (error) { + vrele(lvp); + return (error); + } + 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 ((SCARG(uap, 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; + } + error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), + sizeof(long)); + *retval = SCARG(uap, count) - auio.uio_resid; + return (error); +} |