diff options
Diffstat (limited to 'sys/compat/netbsd/netbsd_file.c')
-rw-r--r-- | sys/compat/netbsd/netbsd_file.c | 726 |
1 files changed, 726 insertions, 0 deletions
diff --git a/sys/compat/netbsd/netbsd_file.c b/sys/compat/netbsd/netbsd_file.c new file mode 100644 index 00000000000..5fe0988a34c --- /dev/null +++ b/sys/compat/netbsd/netbsd_file.c @@ -0,0 +1,726 @@ +/* $OpenBSD: netbsd_file.c,v 1.1 1999/09/17 22:14:09 kstailey Exp $ */ +/* $NetBSD: freebsd_file.c,v 1.3 1996/05/03 17:03:09 christos Exp $ */ + +/* + * Copyright (c) 1995 Frank van der Linden + * All rights reserved. + * + * 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 for the NetBSD Project + * by Frank van der Linden + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * from: linux_file.c,v 1.3 1995/04/04 04:21:30 mycroft Exp + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/proc.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/filedesc.h> +#include <sys/ioctl.h> +#include <sys/kernel.h> +#include <sys/vnode.h> +#include <sys/mount.h> +#include <sys/malloc.h> + +#include <sys/syscallargs.h> + +#include <compat/netbsd/netbsd_types.h> +#include <compat/netbsd/netbsd_stat.h> +#include <compat/netbsd/netbsd_signal.h> +#include <compat/netbsd/netbsd_syscallargs.h> +#include <compat/netbsd/netbsd_util.h> + +#define ARRAY_LENGTH(array) (sizeof(array)/sizeof(array[0])) + +const char netbsd_emul_path[] = "/emul/netbsd"; + +#if 0 +static char * convert_from_netbsd_mount_type __P((int)); +void statfs_to_netbsd_statfs __P((struct proc *, struct mount *, + struct statfs *, struct netbsd_statfs *)); + +struct netbsd_statfs { + long f_spare2; /* placeholder */ + long f_bsize; /* fundamental file system block size */ + long f_iosize; /* optimal transfer block size */ + long f_blocks; /* total data blocks in file system */ + long f_bfree; /* free blocks in fs */ + long f_bavail; /* free blocks avail to non-superuser */ + long f_files; /* total file nodes in file system */ + long f_ffree; /* free file nodes in fs */ + fsid_t f_fsid; /* file system id */ + uid_t f_owner; /* user that mounted the filesystem */ + int f_type; /* type of filesystem */ + int f_flags; /* copy of mount exported flags */ + long f_syncwrites; /* count of sync writes since mount */ + long f_asyncwrites; /* count of async writes since mount */ + char f_fstypename[MFSNAMELEN]; /* fs type name */ + char f_mntonname[MNAMELEN]; /* directory on which mounted */ + char f_mntfromname[MNAMELEN];/* mounted filesystem */ +}; + +static char * +convert_from_netbsd_mount_type(type) + int type; +{ + static char *netbsd_mount_type[] = { + NULL, /* 0 = MOUNT_NONE */ + "ffs", /* 1 = "Fast" Filesystem */ + "nfs", /* 2 = Network Filesystem */ + "mfs", /* 3 = Memory Filesystem */ + "msdos", /* 4 = MSDOS Filesystem */ + "lfs", /* 5 = Log-based Filesystem */ + "lofs", /* 6 = Loopback filesystem */ + "fdesc", /* 7 = File Descriptor Filesystem */ + "portal", /* 8 = Portal Filesystem */ + "null", /* 9 = Minimal Filesystem Layer */ + "umap", /* 10 = User/Group Identifier Remapping Filesystem */ + "kernfs", /* 11 = Kernel Information Filesystem */ + "procfs", /* 12 = /proc Filesystem */ + "afs", /* 13 = Andrew Filesystem */ + "cd9660", /* 14 = ISO9660 (aka CDROM) Filesystem */ + "union", /* 15 = Union (translucent) Filesystem */ + NULL, /* 16 = "devfs" - existing device Filesystem */ +#if 0 /* These filesystems don't exist in Netbsd */ + "adosfs", /* ?? = AmigaDOS Filesystem */ +#endif + }; + + if (type < 0 || type >= ARRAY_LENGTH(netbsd_mount_type)) + return (NULL); + return (netbsd_mount_type[type]); +} + +int +netbsd_sys_mount(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_mount_args /* { + syscallarg(int) type; + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(caddr_t) data; + } */ *uap = v; + int error; + char *type, *s; + caddr_t sg = stackgap_init(p->p_emul); + struct sys_mount_args bma; + + if ((type = convert_from_netbsd_mount_type(SCARG(uap, type))) == NULL) + return ENODEV; + s = stackgap_alloc(&sg, MFSNAMELEN + 1); + if ((error = copyout(type, s, strlen(type) + 1)) != 0) + return error; + SCARG(&bma, type) = s; + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + SCARG(&bma, path) = SCARG(uap, path); + SCARG(&bma, flags) = SCARG(uap, flags); + SCARG(&bma, data) = SCARG(uap, data); + return sys_mount(p, &bma, retval); +} +#endif /* 0 */ + +/* + * The following syscalls are only here because of the alternate path check. + */ + +/* XXX - UNIX domain: int netbsd_sys_bind(int s, caddr_t name, int namelen); */ +/* XXX - UNIX domain: int netbsd_sys_connect(int s, caddr_t name, int namelen); */ + + +int +netbsd_sys_open(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_open_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + syscallarg(int) mode; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + if (SCARG(uap, flags) & O_CREAT) + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); + else + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_open(p, uap, retval); +} + +int +compat_43_netbsd_sys_creat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct compat_43_netbsd_sys_creat_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); + return compat_43_sys_creat(p, uap, retval); +} + +int +netbsd_sys_link(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_link_args /* { + syscallarg(char *) path; + syscallarg(char *) link; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); + return sys_link(p, uap, retval); +} + +int +netbsd_sys_unlink(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_unlink_args /* { + syscallarg(char *) path; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_unlink(p, uap, retval); +} + +int +netbsd_sys_chdir(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_chdir_args /* { + syscallarg(char *) path; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_chdir(p, uap, retval); +} + +int +netbsd_sys_mknod(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_mknod_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + syscallarg(int) dev; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); + return sys_mknod(p, uap, retval); +} + +int +netbsd_sys_chmod(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_chmod_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_chmod(p, uap, retval); +} + +int +netbsd_sys_chown(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_chown_args /* { + syscallarg(char *) path; + syscallarg(int) uid; + syscallarg(int) gid; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_chown(p, uap, retval); +} + +int +netbsd_sys_unmount(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_unmount_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_unmount(p, uap, retval); +} + +int +netbsd_sys_access(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_access_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_access(p, uap, retval); +} + +int +netbsd_sys_chflags(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_chflags_args /* { + syscallarg(char *) path; + syscallarg(int) flags; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_chflags(p, uap, retval); +} + +int +netbsd_sys_revoke(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_revoke_args /* { + syscallarg(char *) path; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_revoke(p, uap, retval); +} + +int +netbsd_sys_symlink(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_symlink_args /* { + syscallarg(char *) path; + syscallarg(char *) link; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); + return sys_symlink(p, uap, retval); +} + +int +netbsd_sys_readlink(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_readlink_args /* { + syscallarg(char *) path; + syscallarg(char *) buf; + syscallarg(int) count; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_readlink(p, uap, retval); +} + +int +netbsd_sys_execve(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_execve_args /* { + syscallarg(char *) path; + syscallarg(char **) argp; + syscallarg(char **) envp; + } */ *uap = v; + struct sys_execve_args ap; + caddr_t sg; + + sg = stackgap_init(p->p_emul); + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + + SCARG(&ap, path) = SCARG(uap, path); + SCARG(&ap, argp) = SCARG(uap, argp); + SCARG(&ap, envp) = SCARG(uap, envp); + + return sys_execve(p, &ap, retval); +} + +int +netbsd_sys_chroot(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_chroot_args /* { + syscallarg(char *) path; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_chroot(p, uap, retval); +} + +int +netbsd_sys_rename(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_rename_args /* { + syscallarg(char *) from; + syscallarg(char *) to; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); + return sys_rename(p, uap, retval); +} + +int +compat_43_netbsd_sys_truncate(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct compat_43_netbsd_sys_truncate_args /* { + syscallarg(char *) path; + syscallarg(long) length; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return compat_43_sys_truncate(p, uap, retval); +} + +int +netbsd_sys_mkfifo(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_mkfifo_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); + return sys_mkfifo(p, uap, retval); +} + +int +netbsd_sys_mkdir(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_mkdir_args /* { + syscallarg(char *) path; + syscallarg(int) mode; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); + return sys_mkdir(p, uap, retval); +} + +int +netbsd_sys_rmdir(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_rmdir_args /* { + syscallarg(char *) path; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_rmdir(p, uap, retval); +} + +#if 0 /* XXX */ +/* + * Convert struct statfs -> struct netbsd_statfs + */ +void +statfs_to_netbsd_statfs(p, mp, sp, fsp) + struct proc *p; + struct mount *mp; + struct statfs *sp; + struct netbsd_statfs *fsp; +{ + fsp->f_bsize = sp->f_bsize; + fsp->f_iosize = sp->f_iosize; + fsp->f_blocks = sp->f_blocks; + fsp->f_bfree = sp->f_bfree; + fsp->f_bavail = sp->f_bavail; + fsp->f_files = sp->f_files; + fsp->f_ffree = sp->f_ffree; + /* Don't let non-root see filesystem id (for NFS security) */ + if (suser(p->p_ucred, &p->p_acflag)) + fsp->f_fsid.val[0] = fsp->f_fsid.val[1] = 0; + else + bcopy(&sp->f_fsid, &fsp->f_fsid, sizeof(fsp->f_fsid)); + fsp->f_owner = sp->f_owner; + fsp->f_type = mp->mnt_vfc->vfc_typenum; + fsp->f_flags = sp->f_flags; + fsp->f_syncwrites = sp->f_syncwrites; + fsp->f_asyncwrites = sp->f_asyncwrites; + bcopy(sp->f_fstypename, fsp->f_fstypename, MFSNAMELEN); + bcopy(sp->f_mntonname, fsp->f_mntonname, MNAMELEN); + bcopy(sp->f_mntfromname, fsp->f_mntfromname, MNAMELEN); +} + +/* + * Get filesystem statistics. + */ +/* ARGSUSED */ +int +netbsd_sys_statfs(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct netbsd_sys_statfs_args /* { + syscallarg(char *) path; + syscallarg(struct netbsd_statfs *) buf; + } */ *uap = v; + register struct mount *mp; + register struct statfs *sp; + struct netbsd_statfs fsb; + int error; + struct nameidata nd; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); + if ((error = namei(&nd)) != 0) + return (error); + mp = nd.ni_vp->v_mount; + sp = &mp->mnt_stat; + vrele(nd.ni_vp); + if ((error = VFS_STATFS(mp, sp, p)) != 0) + return (error); + sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + + statfs_to_netbsd_statfs(p, mp, sp, &fsb); + return (copyout((caddr_t)&fsb, (caddr_t)SCARG(uap, buf), sizeof(fsb))); +} + +/* + * Get filesystem statistics. + */ +/* ARGSUSED */ +int +netbsd_sys_fstatfs(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct netbsd_sys_fstatfs_args /* { + syscallarg(int) fd; + syscallarg(struct netbsd_statfs *) buf; + } */ *uap = v; + struct file *fp; + struct mount *mp; + register struct statfs *sp; + struct netbsd_statfs fsb; + int error; + + if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) + return (error); + mp = ((struct vnode *)fp->f_data)->v_mount; + sp = &mp->mnt_stat; + if ((error = VFS_STATFS(mp, sp, p)) != 0) + return (error); + sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + + statfs_to_netbsd_statfs(p, mp, sp, &fsb); + return (copyout((caddr_t)&fsb, (caddr_t)SCARG(uap, buf), sizeof(fsb))); +} + +/* + * Get statistics on all filesystems. + */ +int +netbsd_sys_getfsstat(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + register struct netbsd_sys_getfsstat_args /* { + syscallarg(struct netbsd_statfs *) buf; + syscallarg(long) bufsize; + syscallarg(int) flags; + } */ *uap = v; + register struct mount *mp, *nmp; + register struct statfs *sp; + struct netbsd_statfs fsb; + caddr_t sfsp; + long count, maxcount; + int error, flags = SCARG(uap, flags); + + maxcount = SCARG(uap, bufsize) / sizeof(struct netbsd_statfs); + sfsp = (caddr_t)SCARG(uap, buf); + count = 0; + simple_lock(&mountlist_slock); + for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { + if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) { + nmp = mp->mnt_list.cqe_next; + continue; + } + if (sfsp && count < maxcount) { + sp = &mp->mnt_stat; + + /* Refresh stats unless MNT_NOWAIT is specified */ + if (flags != MNT_NOWAIT && + flags != MNT_LAZY && + (flags == MNT_WAIT || + flags == 0) && + (error = VFS_STATFS(mp, sp, p))) { + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); + continue; + } + sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; + + statfs_to_netbsd_statfs(p, mp, sp, &fsb); + error = copyout((caddr_t)&fsb, sfsp, sizeof(fsb)); + if (error) { + vfs_unbusy(mp, p); + return (error); + } + sfsp += sizeof(fsb); + } + count++; + simple_lock(&mountlist_slock); + nmp = mp->mnt_list.cqe_next; + vfs_unbusy(mp, p); + } + simple_unlock(&mountlist_slock); + if (sfsp && count > maxcount) + *retval = maxcount; + else + *retval = count; + return (0); +} + +#ifdef NFSCLIENT +int +netbsd_sys_getfh(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_getfh_args /* { + syscallarg(char *) fname; + syscallarg(fhandle_t *) fhp; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, fname)); + return sys_getfh(p, uap, retval); +} +#endif /* NFSCLIENT */ + +#endif /* 0 XXX */ + +int +netbsd_sys_pathconf(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_pathconf_args /* { + syscallarg(char *) path; + syscallarg(int) name; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_pathconf(p, uap, retval); +} + +int +netbsd_sys_truncate(p, v, retval) + struct proc *p; + void *v; + register_t *retval; +{ + struct netbsd_sys_truncate_args /* { + syscallarg(char *) path; + syscallarg(int) pad; + syscallarg(off_t) length; + } */ *uap = v; + caddr_t sg = stackgap_init(p->p_emul); + + NETBSD_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); + return sys_truncate(p, uap, retval); +} |