1139799Simp/*- 211734Sswallace * Copyright (c) 1995 Steven Wallace 311397Sswallace * Copyright (c) 1994, 1995 Scott Bartram 411397Sswallace * Copyright (c) 1992, 1993 511397Sswallace * The Regents of the University of California. All rights reserved. 63584Ssos * 711397Sswallace * This software was developed by the Computer Systems Engineering group 811397Sswallace * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 911397Sswallace * contributed to Berkeley. 103584Ssos * 1111397Sswallace * All advertising materials mentioning features or use of this software 1211397Sswallace * must display the following acknowledgement: 1311397Sswallace * This product includes software developed by the University of 1411397Sswallace * California, Lawrence Berkeley Laboratory. 1511397Sswallace * 163584Ssos * Redistribution and use in source and binary forms, with or without 173584Ssos * modification, are permitted provided that the following conditions 183584Ssos * are met: 193584Ssos * 1. Redistributions of source code must retain the above copyright 2011397Sswallace * notice, this list of conditions and the following disclaimer. 213584Ssos * 2. Redistributions in binary form must reproduce the above copyright 223584Ssos * notice, this list of conditions and the following disclaimer in the 233584Ssos * documentation and/or other materials provided with the distribution. 243584Ssos * 3. All advertising materials mentioning features or use of this software 253584Ssos * must display the following acknowledgement: 263584Ssos * This product includes software developed by the University of 273584Ssos * California, Berkeley and its contributors. 283584Ssos * 4. Neither the name of the University nor the names of its contributors 293584Ssos * may be used to endorse or promote products derived from this software 303584Ssos * without specific prior written permission. 313584Ssos * 323584Ssos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 333584Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 343584Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 353584Ssos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 363584Ssos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 373584Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 383584Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 393584Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 403584Ssos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 413584Ssos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 423584Ssos * SUCH DAMAGE. 433584Ssos * 4411397Sswallace * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 4511397Sswallace * 4611397Sswallace * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 473584Ssos */ 483584Ssos 49115684Sobrien#include <sys/cdefs.h> 50115684Sobrien__FBSDID("$FreeBSD$"); 51115684Sobrien 5211397Sswallace/* 5311397Sswallace * IBCS2 compatibility module. 5411397Sswallace * 5511397Sswallace * IBCS2 system calls that are implemented differently in BSD are 5611397Sswallace * handled here. 5711397Sswallace */ 583584Ssos#include <sys/param.h> 5976166Smarkm#include <sys/systm.h> 60224778Srwatson#include <sys/capability.h> 6138404Sbde#include <sys/dirent.h> 6224131Sbde#include <sys/fcntl.h> 6311397Sswallace#include <sys/filedesc.h> 64141488Sjhb#include <sys/imgact.h> 6511397Sswallace#include <sys/kernel.h> 6631561Sbde#include <sys/lock.h> 6711397Sswallace#include <sys/malloc.h> 6876166Smarkm#include <sys/file.h> /* Must come after sys/malloc.h */ 6976166Smarkm#include <sys/mutex.h> 70195458Strasz#include <sys/namei.h> 71164033Srwatson#include <sys/priv.h> 7211397Sswallace#include <sys/reboot.h> 733584Ssos#include <sys/resourcevar.h> 743584Ssos#include <sys/stat.h> 7538404Sbde#include <sys/sysctl.h> 76139739Sjhb#include <sys/syscallsubr.h> 7738404Sbde#include <sys/sysproto.h> 783584Ssos#include <sys/time.h> 793584Ssos#include <sys/times.h> 8011397Sswallace#include <sys/vnode.h> 8111397Sswallace#include <sys/wait.h> 8211397Sswallace 833584Ssos#include <machine/cpu.h> 843584Ssos 8511397Sswallace#include <i386/ibcs2/ibcs2_dirent.h> 8611397Sswallace#include <i386/ibcs2/ibcs2_signal.h> 8738404Sbde#include <i386/ibcs2/ibcs2_proto.h> 8811397Sswallace#include <i386/ibcs2/ibcs2_unistd.h> 8911397Sswallace#include <i386/ibcs2/ibcs2_util.h> 9011397Sswallace#include <i386/ibcs2/ibcs2_utime.h> 9111397Sswallace#include <i386/ibcs2/ibcs2_xenix.h> 923584Ssos 93163606Srwatson#include <security/mac/mac_framework.h> 94163606Srwatson 953584Ssosint 9683366Sjulianibcs2_ulimit(td, uap) 9783366Sjulian struct thread *td; 9811397Sswallace struct ibcs2_ulimit_args *uap; 993584Ssos{ 100125454Sjhb struct rlimit rl; 101125454Sjhb struct proc *p; 10211397Sswallace int error; 10311397Sswallace#define IBCS2_GETFSIZE 1 10411397Sswallace#define IBCS2_SETFSIZE 2 10511397Sswallace#define IBCS2_GETPSIZE 3 10611397Sswallace#define IBCS2_GETDTABLESIZE 4 107125454Sjhb 108125454Sjhb p = td->td_proc; 109107849Salfred switch (uap->cmd) { 11011397Sswallace case IBCS2_GETFSIZE: 111125454Sjhb PROC_LOCK(p); 112125454Sjhb td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 113125454Sjhb PROC_UNLOCK(p); 114125454Sjhb if (td->td_retval[0] == -1) 115125454Sjhb td->td_retval[0] = 0x7fffffff; 11611397Sswallace return 0; 117125454Sjhb case IBCS2_SETFSIZE: 118125454Sjhb PROC_LOCK(p); 119125454Sjhb rl.rlim_max = lim_max(p, RLIMIT_FSIZE); 120125454Sjhb PROC_UNLOCK(p); 121107849Salfred rl.rlim_cur = uap->newlimit; 122125454Sjhb error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); 123125454Sjhb if (!error) { 124125454Sjhb PROC_LOCK(p); 125125454Sjhb td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 126125454Sjhb PROC_UNLOCK(p); 127125454Sjhb } else { 12811397Sswallace DPRINTF(("failed ")); 129125454Sjhb } 13011397Sswallace return error; 13111397Sswallace case IBCS2_GETPSIZE: 132125454Sjhb PROC_LOCK(p); 133125454Sjhb td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ 134125454Sjhb PROC_UNLOCK(p); 13511397Sswallace return 0; 13611397Sswallace case IBCS2_GETDTABLESIZE: 13711397Sswallace uap->cmd = IBCS2_SC_OPEN_MAX; 13883366Sjulian return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap); 13911397Sswallace default: 14011397Sswallace return ENOSYS; 14111397Sswallace } 1423584Ssos} 1433584Ssos 14411734Sswallace#define IBCS2_WSTOPPED 0177 14511734Sswallace#define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED) 1463584Ssosint 14783366Sjulianibcs2_wait(td, uap) 14883366Sjulian struct thread *td; 14911397Sswallace struct ibcs2_wait_args *uap; 1503584Ssos{ 151127140Sjhb int error, options, status; 152127140Sjhb int *statusp; 153127140Sjhb pid_t pid; 15483366Sjulian struct trapframe *tf = td->td_frame; 15511397Sswallace 156127140Sjhb if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V)) 15711397Sswallace == (PSL_Z|PSL_PF|PSL_N|PSL_V)) { 15811397Sswallace /* waitpid */ 159127140Sjhb pid = uap->a1; 160127140Sjhb statusp = (int *)uap->a2; 161127140Sjhb options = uap->a3; 16211397Sswallace } else { 16311397Sswallace /* wait */ 164127140Sjhb pid = WAIT_ANY; 165127140Sjhb statusp = (int *)uap->a1; 166127140Sjhb options = 0; 1673584Ssos } 168127140Sjhb error = kern_wait(td, pid, &status, options, NULL); 169127140Sjhb if (error) 17011397Sswallace return error; 171127140Sjhb if (statusp) { 172121016Stjr /* 173127140Sjhb * Convert status/signal result. 174121016Stjr */ 175121016Stjr if (WIFSTOPPED(status)) { 176121016Stjr if (WSTOPSIG(status) <= 0 || 177121016Stjr WSTOPSIG(status) > IBCS2_SIGTBLSZ) 178121016Stjr return (EINVAL); 17911734Sswallace status = 18051793Smarcel IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]); 181121016Stjr } else if (WIFSIGNALED(status)) { 182121016Stjr if (WTERMSIG(status) <= 0 || 183121016Stjr WTERMSIG(status) > IBCS2_SIGTBLSZ) 184121016Stjr return (EINVAL); 18551793Smarcel status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))]; 186121016Stjr } 18711734Sswallace /* else exit status -- identical */ 18811734Sswallace 18911734Sswallace /* record result/status */ 19083366Sjulian td->td_retval[1] = status; 191127140Sjhb return copyout(&status, statusp, sizeof(status)); 19211734Sswallace } 19311734Sswallace 1943584Ssos return 0; 1953584Ssos} 1963584Ssos 1973584Ssosint 19883366Sjulianibcs2_execv(td, uap) 19983366Sjulian struct thread *td; 20011397Sswallace struct ibcs2_execv_args *uap; 2013584Ssos{ 202141488Sjhb struct image_args eargs; 203141488Sjhb char *path; 204141488Sjhb int error; 2053584Ssos 206141488Sjhb CHECKALTEXIST(td, uap->path, &path); 207141488Sjhb 208141488Sjhb error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL); 209141488Sjhb free(path, M_TEMP); 210141488Sjhb if (error == 0) 211141488Sjhb error = kern_execve(td, &eargs, NULL); 212141488Sjhb return (error); 2133584Ssos} 2143584Ssos 2153584Ssosint 21683366Sjulianibcs2_execve(td, uap) 21783366Sjulian struct thread *td; 21811397Sswallace struct ibcs2_execve_args *uap; 2193584Ssos{ 220141488Sjhb struct image_args eargs; 221141488Sjhb char *path; 222141488Sjhb int error; 223141488Sjhb 224141488Sjhb CHECKALTEXIST(td, uap->path, &path); 225141488Sjhb 226141488Sjhb error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, 227141488Sjhb uap->envp); 228141488Sjhb free(path, M_TEMP); 229141488Sjhb if (error == 0) 230141488Sjhb error = kern_execve(td, &eargs, NULL); 231141488Sjhb return (error); 2323584Ssos} 2333584Ssos 2343584Ssosint 23583366Sjulianibcs2_umount(td, uap) 23683366Sjulian struct thread *td; 23711397Sswallace struct ibcs2_umount_args *uap; 2383584Ssos{ 23911397Sswallace struct unmount_args um; 2403584Ssos 241107849Salfred um.path = uap->name; 242107849Salfred um.flags = 0; 243225617Skmacy return sys_unmount(td, &um); 2443584Ssos} 2453584Ssos 2463584Ssosint 24783366Sjulianibcs2_mount(td, uap) 24883366Sjulian struct thread *td; 24911397Sswallace struct ibcs2_mount_args *uap; 2503584Ssos{ 25111397Sswallace#ifdef notyet 252107849Salfred int oflags = uap->flags, nflags, error; 25311397Sswallace char fsname[MFSNAMELEN]; 2543584Ssos 25511397Sswallace if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5)) 25611397Sswallace return (EINVAL); 25711397Sswallace if ((oflags & IBCS2_MS_NEWTYPE) == 0) 25811397Sswallace return (EINVAL); 25911397Sswallace nflags = 0; 26011397Sswallace if (oflags & IBCS2_MS_RDONLY) 26111397Sswallace nflags |= MNT_RDONLY; 26211397Sswallace if (oflags & IBCS2_MS_NOSUID) 26311397Sswallace nflags |= MNT_NOSUID; 26411397Sswallace if (oflags & IBCS2_MS_REMOUNT) 26511397Sswallace nflags |= MNT_UPDATE; 266107849Salfred uap->flags = nflags; 2673584Ssos 268107849Salfred if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, 26911397Sswallace (u_int *)0)) 27011397Sswallace return (error); 2713584Ssos 27211397Sswallace if (strcmp(fsname, "4.2") == 0) { 273107849Salfred uap->type = (caddr_t)STACK_ALLOC(); 274107849Salfred if (error = copyout("ufs", uap->type, sizeof("ufs"))) 27511397Sswallace return (error); 27611397Sswallace } else if (strcmp(fsname, "nfs") == 0) { 27711397Sswallace struct ibcs2_nfs_args sna; 27811397Sswallace struct sockaddr_in sain; 27911397Sswallace struct nfs_args na; 28011397Sswallace struct sockaddr sa; 28111397Sswallace 282107849Salfred if (error = copyin(uap->data, &sna, sizeof sna)) 28311397Sswallace return (error); 28411397Sswallace if (error = copyin(sna.addr, &sain, sizeof sain)) 28511397Sswallace return (error); 28611397Sswallace bcopy(&sain, &sa, sizeof sa); 28711397Sswallace sa.sa_len = sizeof(sain); 288107849Salfred uap->data = (caddr_t)STACK_ALLOC(); 289107849Salfred na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 29011397Sswallace na.sotype = SOCK_DGRAM; 29111397Sswallace na.proto = IPPROTO_UDP; 29211397Sswallace na.fh = (nfsv2fh_t *)sna.fh; 29311397Sswallace na.flags = sna.flags; 29411397Sswallace na.wsize = sna.wsize; 29511397Sswallace na.rsize = sna.rsize; 29611397Sswallace na.timeo = sna.timeo; 29711397Sswallace na.retrans = sna.retrans; 29811397Sswallace na.hostname = sna.hostname; 29911397Sswallace 30011397Sswallace if (error = copyout(&sa, na.addr, sizeof sa)) 30111397Sswallace return (error); 302107849Salfred if (error = copyout(&na, uap->data, sizeof na)) 30311397Sswallace return (error); 30411397Sswallace } 30583366Sjulian return (mount(td, uap)); 30611397Sswallace#else 30711397Sswallace return EINVAL; 30811397Sswallace#endif 3093584Ssos} 3103584Ssos 31111397Sswallace/* 31211397Sswallace * Read iBCS2-style directory entries. We suck them into kernel space so 31311397Sswallace * that they can be massaged before being copied out to user code. Like 31411397Sswallace * SunOS, we squish out `empty' entries. 31511397Sswallace * 31611397Sswallace * This is quite ugly, but what do you expect from compatibility code? 31711397Sswallace */ 3183584Ssos 3193584Ssosint 32083366Sjulianibcs2_getdents(td, uap) 32183366Sjulian struct thread *td; 32211397Sswallace register struct ibcs2_getdents_args *uap; 3233584Ssos{ 32411397Sswallace register struct vnode *vp; 32511397Sswallace register caddr_t inp, buf; /* BSD-format */ 32611397Sswallace register int len, reclen; /* BSD-format */ 32711397Sswallace register caddr_t outp; /* iBCS2-format */ 32811397Sswallace register int resid; /* iBCS2-format */ 329255219Spjd cap_rights_t rights; 33011397Sswallace struct file *fp; 33111397Sswallace struct uio auio; 33211397Sswallace struct iovec aiov; 33311397Sswallace struct ibcs2_dirent idb; 33411397Sswallace off_t off; /* true file offset */ 335241896Skib int buflen, error, eofflag; 33624677Sdfr u_long *cookies = NULL, *cookiep; 33724677Sdfr int ncookies; 33824677Sdfr#define BSD_DIRENT(cp) ((struct dirent *)(cp)) 33911397Sswallace#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) 34011397Sswallace 341255219Spjd error = getvnode(td->td_proc->p_fd, uap->fd, 342255219Spjd cap_rights_init(&rights, CAP_READ), &fp); 343255219Spjd if (error != 0) 34411397Sswallace return (error); 34589306Salfred if ((fp->f_flag & FREAD) == 0) { 34689306Salfred fdrop(fp, td); 34711397Sswallace return (EBADF); 34889306Salfred } 349116678Sphk vp = fp->f_vnode; 35089306Salfred if (vp->v_type != VDIR) { /* XXX vnode readdir op should do this */ 35189306Salfred fdrop(fp, td); 35211397Sswallace return (EINVAL); 35389306Salfred } 35411417Sswallace 35511417Sswallace off = fp->f_offset; 35624677Sdfr#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 357107849Salfred buflen = max(DIRBLKSIZ, uap->nbytes); 35811417Sswallace buflen = min(buflen, MAXBSIZE); 359111119Simp buf = malloc(buflen, M_TEMP, M_WAITOK); 360188588Sjhb vn_lock(vp, LK_SHARED | LK_RETRY); 36111397Sswallaceagain: 36211397Sswallace aiov.iov_base = buf; 36311397Sswallace aiov.iov_len = buflen; 36411397Sswallace auio.uio_iov = &aiov; 36511397Sswallace auio.uio_iovcnt = 1; 36611397Sswallace auio.uio_rw = UIO_READ; 36711397Sswallace auio.uio_segflg = UIO_SYSSPACE; 36883366Sjulian auio.uio_td = td; 36911397Sswallace auio.uio_resid = buflen; 37024677Sdfr auio.uio_offset = off; 37124677Sdfr 37224677Sdfr if (cookies) { 37324677Sdfr free(cookies, M_TEMP); 37424677Sdfr cookies = NULL; 37524677Sdfr } 37624677Sdfr 377101710Srwatson#ifdef MAC 378172930Srwatson error = mac_vnode_check_readdir(td->td_ucred, vp); 379101710Srwatson if (error) 380101710Srwatson goto out; 381101710Srwatson#endif 382101710Srwatson 38311397Sswallace /* 38411397Sswallace * First we read into the malloc'ed buffer, then 38511397Sswallace * we massage it into user space, one record at a time. 38611397Sswallace */ 38743314Sdillon if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) 38811397Sswallace goto out; 38911397Sswallace inp = buf; 390107849Salfred outp = uap->buf; 391107849Salfred resid = uap->nbytes; 39224677Sdfr if ((len = buflen - auio.uio_resid) <= 0) 39311397Sswallace goto eof; 39424677Sdfr 39524677Sdfr cookiep = cookies; 39624677Sdfr 39724677Sdfr if (cookies) { 39824677Sdfr /* 39924677Sdfr * When using cookies, the vfs has the option of reading from 40024677Sdfr * a different offset than that supplied (UFS truncates the 40124677Sdfr * offset to a block boundary to make sure that it never reads 40224677Sdfr * partway through a directory entry, even if the directory 40324677Sdfr * has been compacted). 40424677Sdfr */ 40524677Sdfr while (len > 0 && ncookies > 0 && *cookiep <= off) { 40624677Sdfr len -= BSD_DIRENT(inp)->d_reclen; 40724677Sdfr inp += BSD_DIRENT(inp)->d_reclen; 40824677Sdfr cookiep++; 40924677Sdfr ncookies--; 41024677Sdfr } 41124677Sdfr } 41224677Sdfr 41311397Sswallace for (; len > 0; len -= reclen) { 41424677Sdfr if (cookiep && ncookies == 0) 41524677Sdfr break; 41611397Sswallace reclen = BSD_DIRENT(inp)->d_reclen; 41711417Sswallace if (reclen & 3) { 41811417Sswallace printf("ibcs2_getdents: reclen=%d\n", reclen); 41911417Sswallace error = EFAULT; 42011417Sswallace goto out; 42111417Sswallace } 42224677Sdfr if (BSD_DIRENT(inp)->d_fileno == 0) { 42311397Sswallace inp += reclen; /* it is a hole; squish it out */ 42424677Sdfr if (cookiep) { 42524677Sdfr off = *cookiep++; 42624677Sdfr ncookies--; 42724677Sdfr } else 42824677Sdfr off += reclen; 42911397Sswallace continue; 43011397Sswallace } 43111397Sswallace if (reclen > len || resid < IBCS2_RECLEN(reclen)) { 43211397Sswallace /* entry too big for buffer, so just stop */ 43311397Sswallace outp++; 43411397Sswallace break; 43511397Sswallace } 43611397Sswallace /* 437108533Sschweikh * Massage in place to make an iBCS2-shaped dirent (otherwise 43811397Sswallace * we have to worry about touching user memory outside of 43911397Sswallace * the copyout() call). 44011397Sswallace */ 44124677Sdfr idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; 44211397Sswallace idb.d_off = (ibcs2_off_t)off; 44311397Sswallace idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); 44411397Sswallace if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || 44511397Sswallace (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10, 44611397Sswallace BSD_DIRENT(inp)->d_namlen + 1)) != 0) 44711397Sswallace goto out; 44811397Sswallace /* advance past this real entry */ 44924677Sdfr if (cookiep) { 45024677Sdfr off = *cookiep++; 45124677Sdfr ncookies--; 45224677Sdfr } else 45324677Sdfr off += reclen; 45411397Sswallace inp += reclen; 45511397Sswallace /* advance output past iBCS2-shaped entry */ 45611397Sswallace outp += IBCS2_RECLEN(reclen); 45711397Sswallace resid -= IBCS2_RECLEN(reclen); 45811397Sswallace } 45911397Sswallace /* if we squished out the whole block, try again */ 460107849Salfred if (outp == uap->buf) 46111397Sswallace goto again; 46211397Sswallace fp->f_offset = off; /* update the vnode offset */ 46311397Sswallaceeof: 464107849Salfred td->td_retval[0] = uap->nbytes - resid; 46511397Sswallaceout: 466175294Sattilio VOP_UNLOCK(vp, 0); 46789306Salfred fdrop(fp, td); 46824677Sdfr if (cookies) 46924677Sdfr free(cookies, M_TEMP); 47011397Sswallace free(buf, M_TEMP); 47111397Sswallace return (error); 4723584Ssos} 4733584Ssos 4743584Ssosint 47583366Sjulianibcs2_read(td, uap) 47683366Sjulian struct thread *td; 47711397Sswallace struct ibcs2_read_args *uap; 4783584Ssos{ 47911397Sswallace register struct vnode *vp; 48011397Sswallace register caddr_t inp, buf; /* BSD-format */ 48111397Sswallace register int len, reclen; /* BSD-format */ 48211397Sswallace register caddr_t outp; /* iBCS2-format */ 48311397Sswallace register int resid; /* iBCS2-format */ 484255219Spjd cap_rights_t rights; 48511397Sswallace struct file *fp; 48611397Sswallace struct uio auio; 48711397Sswallace struct iovec aiov; 48811397Sswallace struct ibcs2_direct { 48911397Sswallace ibcs2_ino_t ino; 49011397Sswallace char name[14]; 49111397Sswallace } idb; 49211397Sswallace off_t off; /* true file offset */ 493241896Skib int buflen, error, eofflag, size; 49424677Sdfr u_long *cookies = NULL, *cookiep; 49524677Sdfr int ncookies; 49611397Sswallace 497255219Spjd error = getvnode(td->td_proc->p_fd, uap->fd, 498255219Spjd cap_rights_init(&rights, CAP_READ), &fp); 499255219Spjd if (error != 0) { 50011397Sswallace if (error == EINVAL) 501225617Skmacy return sys_read(td, (struct read_args *)uap); 50211397Sswallace else 50311397Sswallace return error; 50411397Sswallace } 50589306Salfred if ((fp->f_flag & FREAD) == 0) { 50689306Salfred fdrop(fp, td); 50711397Sswallace return (EBADF); 50889306Salfred } 509116678Sphk vp = fp->f_vnode; 51089306Salfred if (vp->v_type != VDIR) { 51189306Salfred fdrop(fp, td); 512225617Skmacy return sys_read(td, (struct read_args *)uap); 51389306Salfred } 51489306Salfred 51589306Salfred off = fp->f_offset; 51611417Sswallace 51711397Sswallace DPRINTF(("ibcs2_read: read directory\n")); 51811417Sswallace 519107849Salfred buflen = max(DIRBLKSIZ, uap->nbytes); 52011417Sswallace buflen = min(buflen, MAXBSIZE); 521111119Simp buf = malloc(buflen, M_TEMP, M_WAITOK); 522188588Sjhb vn_lock(vp, LK_SHARED | LK_RETRY); 52311397Sswallaceagain: 52411397Sswallace aiov.iov_base = buf; 52511397Sswallace aiov.iov_len = buflen; 52611397Sswallace auio.uio_iov = &aiov; 52711397Sswallace auio.uio_iovcnt = 1; 52811397Sswallace auio.uio_rw = UIO_READ; 52911397Sswallace auio.uio_segflg = UIO_SYSSPACE; 53083366Sjulian auio.uio_td = td; 53111397Sswallace auio.uio_resid = buflen; 53224677Sdfr auio.uio_offset = off; 53324677Sdfr 53424677Sdfr if (cookies) { 53524677Sdfr free(cookies, M_TEMP); 53624677Sdfr cookies = NULL; 53724677Sdfr } 53824677Sdfr 539101710Srwatson#ifdef MAC 540172930Srwatson error = mac_vnode_check_readdir(td->td_ucred, vp); 541101710Srwatson if (error) 542101710Srwatson goto out; 543101710Srwatson#endif 544101710Srwatson 54511397Sswallace /* 54611397Sswallace * First we read into the malloc'ed buffer, then 54711397Sswallace * we massage it into user space, one record at a time. 54811397Sswallace */ 54943314Sdillon if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) { 55011397Sswallace DPRINTF(("VOP_READDIR failed: %d\n", error)); 55111397Sswallace goto out; 55211397Sswallace } 55311417Sswallace inp = buf; 554107849Salfred outp = uap->buf; 555107849Salfred resid = uap->nbytes; 55624677Sdfr if ((len = buflen - auio.uio_resid) <= 0) 55711397Sswallace goto eof; 55824677Sdfr 55924677Sdfr cookiep = cookies; 56024677Sdfr 56124677Sdfr if (cookies) { 56224677Sdfr /* 56324677Sdfr * When using cookies, the vfs has the option of reading from 56424677Sdfr * a different offset than that supplied (UFS truncates the 56524677Sdfr * offset to a block boundary to make sure that it never reads 56624677Sdfr * partway through a directory entry, even if the directory 56724677Sdfr * has been compacted). 56824677Sdfr */ 56924677Sdfr while (len > 0 && ncookies > 0 && *cookiep <= off) { 57024677Sdfr len -= BSD_DIRENT(inp)->d_reclen; 57124677Sdfr inp += BSD_DIRENT(inp)->d_reclen; 57224677Sdfr cookiep++; 57324677Sdfr ncookies--; 57424677Sdfr } 57524677Sdfr } 57624677Sdfr 57711397Sswallace for (; len > 0 && resid > 0; len -= reclen) { 57824677Sdfr if (cookiep && ncookies == 0) 57924677Sdfr break; 58011397Sswallace reclen = BSD_DIRENT(inp)->d_reclen; 58111417Sswallace if (reclen & 3) { 58211417Sswallace printf("ibcs2_read: reclen=%d\n", reclen); 58311417Sswallace error = EFAULT; 58411417Sswallace goto out; 58511417Sswallace } 58624677Sdfr if (BSD_DIRENT(inp)->d_fileno == 0) { 58711397Sswallace inp += reclen; /* it is a hole; squish it out */ 58824677Sdfr if (cookiep) { 58924677Sdfr off = *cookiep++; 59024677Sdfr ncookies--; 59124677Sdfr } else 59224677Sdfr off += reclen; 59311397Sswallace continue; 59411397Sswallace } 59511397Sswallace if (reclen > len || resid < sizeof(struct ibcs2_direct)) { 59611397Sswallace /* entry too big for buffer, so just stop */ 59711397Sswallace outp++; 59811397Sswallace break; 59911397Sswallace } 60011397Sswallace /* 601108533Sschweikh * Massage in place to make an iBCS2-shaped dirent (otherwise 60211397Sswallace * we have to worry about touching user memory outside of 60311397Sswallace * the copyout() call). 60411397Sswallace * 60511397Sswallace * TODO: if length(filename) > 14, then break filename into 60611397Sswallace * multiple entries and set inode = 0xffff except last 60711397Sswallace */ 60824677Sdfr idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : 60924677Sdfr BSD_DIRENT(inp)->d_fileno; 61011397Sswallace (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); 61111397Sswallace bzero(idb.name + size, 14 - size); 61243314Sdillon if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0) 61311397Sswallace goto out; 61411397Sswallace /* advance past this real entry */ 61524677Sdfr if (cookiep) { 61624677Sdfr off = *cookiep++; 61724677Sdfr ncookies--; 61824677Sdfr } else 61924677Sdfr off += reclen; 62011397Sswallace inp += reclen; 62111397Sswallace /* advance output past iBCS2-shaped entry */ 62211397Sswallace outp += sizeof(struct ibcs2_direct); 62311397Sswallace resid -= sizeof(struct ibcs2_direct); 62411397Sswallace } 62511397Sswallace /* if we squished out the whole block, try again */ 626107849Salfred if (outp == uap->buf) 62711397Sswallace goto again; 62811397Sswallace fp->f_offset = off; /* update the vnode offset */ 62911397Sswallaceeof: 630107849Salfred td->td_retval[0] = uap->nbytes - resid; 63111397Sswallaceout: 632175294Sattilio VOP_UNLOCK(vp, 0); 63389306Salfred fdrop(fp, td); 63424677Sdfr if (cookies) 63524677Sdfr free(cookies, M_TEMP); 63611397Sswallace free(buf, M_TEMP); 63711397Sswallace return (error); 6383584Ssos} 6393584Ssos 6403584Ssosint 64183366Sjulianibcs2_mknod(td, uap) 64283366Sjulian struct thread *td; 64311397Sswallace struct ibcs2_mknod_args *uap; 6443584Ssos{ 645141488Sjhb char *path; 646141488Sjhb int error; 64711397Sswallace 648141488Sjhb CHECKALTCREAT(td, uap->path, &path); 649141488Sjhb if (S_ISFIFO(uap->mode)) 650141488Sjhb error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode); 651141488Sjhb else 652141488Sjhb error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev); 653141488Sjhb free(path, M_TEMP); 654141488Sjhb return (error); 6553584Ssos} 6563584Ssos 6573584Ssosint 65883366Sjulianibcs2_getgroups(td, uap) 65983366Sjulian struct thread *td; 66011397Sswallace struct ibcs2_getgroups_args *uap; 6613584Ssos{ 662194498Sbrooks ibcs2_gid_t *iset; 663194498Sbrooks gid_t *gp; 664160139Sjhb u_int i, ngrp; 665160139Sjhb int error; 66611397Sswallace 667202342Sbrooks if (uap->gidsetsize < td->td_ucred->cr_ngroups) { 668202342Sbrooks if (uap->gidsetsize == 0) 669202342Sbrooks ngrp = 0; 670202342Sbrooks else 671202342Sbrooks return (EINVAL); 672202342Sbrooks } else 673202342Sbrooks ngrp = td->td_ucred->cr_ngroups; 674194498Sbrooks gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK); 675160139Sjhb error = kern_getgroups(td, &ngrp, gp); 676160139Sjhb if (error) 677194498Sbrooks goto out; 678160139Sjhb if (uap->gidsetsize > 0) { 679194498Sbrooks iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK); 680160139Sjhb for (i = 0; i < ngrp; i++) 681160139Sjhb iset[i] = (ibcs2_gid_t)gp[i]; 682160139Sjhb error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t)); 683194498Sbrooks free(iset, M_TEMP); 68411397Sswallace } 685160139Sjhb if (error == 0) 686160139Sjhb td->td_retval[0] = ngrp; 687194498Sbrooksout: 688194498Sbrooks free(gp, M_TEMP); 689160139Sjhb return (error); 6903584Ssos} 6913584Ssos 6923584Ssosint 69383366Sjulianibcs2_setgroups(td, uap) 69483366Sjulian struct thread *td; 69511397Sswallace struct ibcs2_setgroups_args *uap; 6963584Ssos{ 697194498Sbrooks ibcs2_gid_t *iset; 698194498Sbrooks gid_t *gp; 69911397Sswallace int error, i; 70011397Sswallace 701202143Sbrooks if (uap->gidsetsize < 0 || uap->gidsetsize > ngroups_max + 1) 702121016Stjr return (EINVAL); 703194498Sbrooks if (uap->gidsetsize && uap->gidset == NULL) 704194498Sbrooks return (EINVAL); 705194498Sbrooks gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK); 706194498Sbrooks if (uap->gidsetsize) { 707194498Sbrooks iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK); 708160139Sjhb error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * 709160139Sjhb uap->gidsetsize); 710194498Sbrooks if (error) { 711194498Sbrooks free(iset, M_TEMP); 712194498Sbrooks goto out; 713194498Sbrooks } 714160139Sjhb for (i = 0; i < uap->gidsetsize; i++) 715160139Sjhb gp[i] = (gid_t)iset[i]; 71611397Sswallace } 717194498Sbrooks 718194498Sbrooks error = kern_setgroups(td, uap->gidsetsize, gp); 719194498Sbrooksout: 720194498Sbrooks free(gp, M_TEMP); 721194498Sbrooks return (error); 7223584Ssos} 7233584Ssos 7243584Ssosint 72583366Sjulianibcs2_setuid(td, uap) 72683366Sjulian struct thread *td; 72711397Sswallace struct ibcs2_setuid_args *uap; 7283584Ssos{ 72911397Sswallace struct setuid_args sa; 7303584Ssos 731107849Salfred sa.uid = (uid_t)uap->uid; 732225617Skmacy return sys_setuid(td, &sa); 7333584Ssos} 7343584Ssos 7353584Ssosint 73683366Sjulianibcs2_setgid(td, uap) 73783366Sjulian struct thread *td; 73811397Sswallace struct ibcs2_setgid_args *uap; 7393584Ssos{ 74011397Sswallace struct setgid_args sa; 7413584Ssos 742107849Salfred sa.gid = (gid_t)uap->gid; 743225617Skmacy return sys_setgid(td, &sa); 7443584Ssos} 7453584Ssos 7463584Ssosint 74783366Sjulianibcs2_time(td, uap) 74883366Sjulian struct thread *td; 74911397Sswallace struct ibcs2_time_args *uap; 7503584Ssos{ 7513584Ssos struct timeval tv; 7523584Ssos 75338403Sbde microtime(&tv); 75483366Sjulian td->td_retval[0] = tv.tv_sec; 755107849Salfred if (uap->tp) 756107849Salfred return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp, 75711397Sswallace sizeof(ibcs2_time_t)); 75811397Sswallace else 75911397Sswallace return 0; 7603584Ssos} 7613584Ssos 7623584Ssosint 76383366Sjulianibcs2_pathconf(td, uap) 76483366Sjulian struct thread *td; 76511397Sswallace struct ibcs2_pathconf_args *uap; 7663584Ssos{ 767141488Sjhb char *path; 768141488Sjhb int error; 769141488Sjhb 770141488Sjhb CHECKALTEXIST(td, uap->path, &path); 771107849Salfred uap->name++; /* iBCS2 _PC_* defines are offset by one */ 772195458Strasz error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW); 773141488Sjhb free(path, M_TEMP); 774141488Sjhb return (error); 7753584Ssos} 7763584Ssos 7773584Ssosint 77883366Sjulianibcs2_fpathconf(td, uap) 77983366Sjulian struct thread *td; 78011397Sswallace struct ibcs2_fpathconf_args *uap; 7813584Ssos{ 782107849Salfred uap->name++; /* iBCS2 _PC_* defines are offset by one */ 783225617Skmacy return sys_fpathconf(td, (struct fpathconf_args *)uap); 7843584Ssos} 7853584Ssos 7863584Ssosint 78783366Sjulianibcs2_sysconf(td, uap) 78883366Sjulian struct thread *td; 78911397Sswallace struct ibcs2_sysconf_args *uap; 7903584Ssos{ 79111397Sswallace int mib[2], value, len, error; 792125454Sjhb struct proc *p; 7933584Ssos 794125454Sjhb p = td->td_proc; 795107849Salfred switch(uap->name) { 79611397Sswallace case IBCS2_SC_ARG_MAX: 79711397Sswallace mib[1] = KERN_ARGMAX; 79811397Sswallace break; 7993584Ssos 80011397Sswallace case IBCS2_SC_CHILD_MAX: 801125454Sjhb PROC_LOCK(p); 802125454Sjhb td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); 803125454Sjhb PROC_UNLOCK(p); 80411397Sswallace return 0; 8053584Ssos 80611397Sswallace case IBCS2_SC_CLK_TCK: 80783366Sjulian td->td_retval[0] = hz; 80811397Sswallace return 0; 8093584Ssos 81011397Sswallace case IBCS2_SC_NGROUPS_MAX: 81111397Sswallace mib[1] = KERN_NGROUPS; 81211397Sswallace break; 8133584Ssos 81411397Sswallace case IBCS2_SC_OPEN_MAX: 815125454Sjhb PROC_LOCK(p); 816125454Sjhb td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); 817125454Sjhb PROC_UNLOCK(p); 81811397Sswallace return 0; 81911397Sswallace 82011397Sswallace case IBCS2_SC_JOB_CONTROL: 82111397Sswallace mib[1] = KERN_JOB_CONTROL; 82211397Sswallace break; 82311397Sswallace 82411397Sswallace case IBCS2_SC_SAVED_IDS: 82511397Sswallace mib[1] = KERN_SAVED_IDS; 82611397Sswallace break; 82711397Sswallace 82811397Sswallace case IBCS2_SC_VERSION: 82911397Sswallace mib[1] = KERN_POSIX1; 83011397Sswallace break; 83111397Sswallace 83211397Sswallace case IBCS2_SC_PASS_MAX: 83383366Sjulian td->td_retval[0] = 128; /* XXX - should we create PASS_MAX ? */ 83411397Sswallace return 0; 8353584Ssos 83611397Sswallace case IBCS2_SC_XOPEN_VERSION: 83783366Sjulian td->td_retval[0] = 2; /* XXX: What should that be? */ 83811397Sswallace return 0; 83911397Sswallace 84011397Sswallace default: 84111397Sswallace return EINVAL; 84211397Sswallace } 8433584Ssos 84411397Sswallace mib[0] = CTL_KERN; 84511397Sswallace len = sizeof(value); 846136418Sphk error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0); 847125454Sjhb if (error) 84811397Sswallace return error; 84983366Sjulian td->td_retval[0] = value; 85011397Sswallace return 0; 85111397Sswallace} 8523584Ssos 8533584Ssosint 85483366Sjulianibcs2_alarm(td, uap) 85583366Sjulian struct thread *td; 85611397Sswallace struct ibcs2_alarm_args *uap; 8573584Ssos{ 858141488Sjhb struct itimerval itv, oitv; 85911397Sswallace int error; 8603584Ssos 861141488Sjhb timevalclear(&itv.it_interval); 862141488Sjhb itv.it_value.tv_sec = uap->sec; 863141488Sjhb itv.it_value.tv_usec = 0; 864141488Sjhb error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv); 86511397Sswallace if (error) 866141488Sjhb return (error); 867141488Sjhb if (oitv.it_value.tv_usec != 0) 868141488Sjhb oitv.it_value.tv_sec++; 869141488Sjhb td->td_retval[0] = oitv.it_value.tv_sec; 870141488Sjhb return (0); 8713584Ssos} 8723584Ssos 8733584Ssosint 87483366Sjulianibcs2_times(td, uap) 87583366Sjulian struct thread *td; 87611397Sswallace struct ibcs2_times_args *uap; 8773584Ssos{ 878141488Sjhb struct rusage ru; 879141488Sjhb struct timeval t; 880141488Sjhb struct tms tms; 88111397Sswallace int error; 882141488Sjhb 88311397Sswallace#define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 88411397Sswallace 885141488Sjhb error = kern_getrusage(td, RUSAGE_SELF, &ru); 88611397Sswallace if (error) 887141488Sjhb return (error); 888141488Sjhb tms.tms_utime = CONVTCK(ru.ru_utime); 889141488Sjhb tms.tms_stime = CONVTCK(ru.ru_stime); 89011397Sswallace 891141488Sjhb error = kern_getrusage(td, RUSAGE_CHILDREN, &ru); 89211397Sswallace if (error) 893141488Sjhb return (error); 894141488Sjhb tms.tms_cutime = CONVTCK(ru.ru_utime); 895141488Sjhb tms.tms_cstime = CONVTCK(ru.ru_stime); 89611397Sswallace 89711397Sswallace microtime(&t); 898141488Sjhb td->td_retval[0] = CONVTCK(t); 89911397Sswallace 900141488Sjhb return (copyout(&tms, uap->tp, sizeof(struct tms))); 9013584Ssos} 9023584Ssos 9033584Ssosint 90483366Sjulianibcs2_stime(td, uap) 90583366Sjulian struct thread *td; 90611397Sswallace struct ibcs2_stime_args *uap; 9073584Ssos{ 908144451Sjhb struct timeval tv; 909144451Sjhb long secs; 91011397Sswallace int error; 91111397Sswallace 912144451Sjhb error = copyin(uap->timep, &secs, sizeof(long)); 913144451Sjhb if (error) 914144451Sjhb return (error); 915144451Sjhb tv.tv_sec = secs; 916144451Sjhb tv.tv_usec = 0; 917144451Sjhb error = kern_settimeofday(td, &tv, NULL); 918144451Sjhb if (error) 919144451Sjhb error = EPERM; 920144451Sjhb return (error); 9213584Ssos} 9223584Ssos 9233584Ssosint 92483366Sjulianibcs2_utime(td, uap) 92583366Sjulian struct thread *td; 92611397Sswallace struct ibcs2_utime_args *uap; 9273584Ssos{ 928141488Sjhb struct ibcs2_utimbuf ubuf; 929141488Sjhb struct timeval tbuf[2], *tp; 930141488Sjhb char *path; 93111397Sswallace int error; 93211397Sswallace 933107849Salfred if (uap->buf) { 934141488Sjhb error = copyin(uap->buf, &ubuf, sizeof(ubuf)); 935141488Sjhb if (error) 936141488Sjhb return (error); 937141488Sjhb tbuf[0].tv_sec = ubuf.actime; 938141488Sjhb tbuf[0].tv_usec = 0; 939141488Sjhb tbuf[1].tv_sec = ubuf.modtime; 940141488Sjhb tbuf[1].tv_usec = 0; 941141488Sjhb tp = tbuf; 942141488Sjhb } else 943141488Sjhb tp = NULL; 94411397Sswallace 945141488Sjhb CHECKALTEXIST(td, uap->path, &path); 946141488Sjhb error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE); 947141488Sjhb free(path, M_TEMP); 948141488Sjhb return (error); 9493584Ssos} 9503584Ssos 9513584Ssosint 95283366Sjulianibcs2_nice(td, uap) 95383366Sjulian struct thread *td; 95411397Sswallace struct ibcs2_nice_args *uap; 9553584Ssos{ 95616322Sgpalmer int error; 95711397Sswallace struct setpriority_args sa; 95811397Sswallace 959107849Salfred sa.which = PRIO_PROCESS; 960107849Salfred sa.who = 0; 961130551Sjulian sa.prio = td->td_proc->p_nice + uap->incr; 962225617Skmacy if ((error = sys_setpriority(td, &sa)) != 0) 96311397Sswallace return EPERM; 964130551Sjulian td->td_retval[0] = td->td_proc->p_nice; 96511397Sswallace return 0; 9663584Ssos} 9673584Ssos 96811397Sswallace/* 96911397Sswallace * iBCS2 getpgrp, setpgrp, setsid, and setpgid 97011397Sswallace */ 9713584Ssos 9723584Ssosint 97383366Sjulianibcs2_pgrpsys(td, uap) 97483366Sjulian struct thread *td; 97511397Sswallace struct ibcs2_pgrpsys_args *uap; 9763584Ssos{ 97783366Sjulian struct proc *p = td->td_proc; 978107849Salfred switch (uap->type) { 97911397Sswallace case 0: /* getpgrp */ 98071489Sjhb PROC_LOCK(p); 98183366Sjulian td->td_retval[0] = p->p_pgrp->pg_id; 98271489Sjhb PROC_UNLOCK(p); 98311397Sswallace return 0; 9843584Ssos 98511397Sswallace case 1: /* setpgrp */ 98611397Sswallace { 98711397Sswallace struct setpgid_args sa; 9883584Ssos 989107849Salfred sa.pid = 0; 990107849Salfred sa.pgid = 0; 991225617Skmacy sys_setpgid(td, &sa); 99271489Sjhb PROC_LOCK(p); 99383366Sjulian td->td_retval[0] = p->p_pgrp->pg_id; 99471489Sjhb PROC_UNLOCK(p); 99511397Sswallace return 0; 99611397Sswallace } 9973584Ssos 99811397Sswallace case 2: /* setpgid */ 99911397Sswallace { 100011397Sswallace struct setpgid_args sa; 10013584Ssos 1002107849Salfred sa.pid = uap->pid; 1003107849Salfred sa.pgid = uap->pgid; 1004225617Skmacy return sys_setpgid(td, &sa); 100511397Sswallace } 10063584Ssos 100711397Sswallace case 3: /* setsid */ 1008225617Skmacy return sys_setsid(td, NULL); 100911397Sswallace 10103584Ssos default: 101111397Sswallace return EINVAL; 10123584Ssos } 10133584Ssos} 10143584Ssos 101511397Sswallace/* 101611397Sswallace * XXX - need to check for nested calls 101711397Sswallace */ 10183584Ssos 10193584Ssosint 102083366Sjulianibcs2_plock(td, uap) 102183366Sjulian struct thread *td; 102211397Sswallace struct ibcs2_plock_args *uap; 10233584Ssos{ 102411397Sswallace int error; 102511397Sswallace#define IBCS2_UNLOCK 0 102611397Sswallace#define IBCS2_PROCLOCK 1 102711397Sswallace#define IBCS2_TEXTLOCK 2 102811397Sswallace#define IBCS2_DATALOCK 4 10293584Ssos 103011397Sswallace 1031107849Salfred switch(uap->cmd) { 103211397Sswallace case IBCS2_UNLOCK: 1033164033Srwatson error = priv_check(td, PRIV_VM_MUNLOCK); 1034164033Srwatson if (error) 1035164033Srwatson return (error); 1036164033Srwatson /* XXX - TODO */ 1037164033Srwatson return (0); 1038164033Srwatson 103911397Sswallace case IBCS2_PROCLOCK: 104011397Sswallace case IBCS2_TEXTLOCK: 104111397Sswallace case IBCS2_DATALOCK: 1042164033Srwatson error = priv_check(td, PRIV_VM_MLOCK); 1043164033Srwatson if (error) 1044164033Srwatson return (error); 1045164033Srwatson /* XXX - TODO */ 1046164033Srwatson return 0; 104711397Sswallace } 104811397Sswallace return EINVAL; 10493584Ssos} 10503584Ssos 10513584Ssosint 105283366Sjulianibcs2_uadmin(td, uap) 105383366Sjulian struct thread *td; 105411397Sswallace struct ibcs2_uadmin_args *uap; 10553584Ssos{ 105611397Sswallace#define SCO_A_REBOOT 1 105711397Sswallace#define SCO_A_SHUTDOWN 2 105811397Sswallace#define SCO_A_REMOUNT 4 105911397Sswallace#define SCO_A_CLOCK 8 106011397Sswallace#define SCO_A_SETCONFIG 128 106111397Sswallace#define SCO_A_GETDEV 130 10623584Ssos 106311397Sswallace#define SCO_AD_HALT 0 106411397Sswallace#define SCO_AD_BOOT 1 106511397Sswallace#define SCO_AD_IBOOT 2 106611397Sswallace#define SCO_AD_PWRDOWN 3 106711397Sswallace#define SCO_AD_PWRNAP 4 10683584Ssos 106911397Sswallace#define SCO_AD_PANICBOOT 1 10703584Ssos 107111397Sswallace#define SCO_AD_GETBMAJ 0 107211397Sswallace#define SCO_AD_GETCMAJ 1 10733584Ssos 1074107849Salfred switch(uap->cmd) { 107511397Sswallace case SCO_A_REBOOT: 107611397Sswallace case SCO_A_SHUTDOWN: 1077107849Salfred switch(uap->func) { 107811397Sswallace struct reboot_args r; 107911397Sswallace case SCO_AD_HALT: 108011397Sswallace case SCO_AD_PWRDOWN: 108111397Sswallace case SCO_AD_PWRNAP: 108211397Sswallace r.opt = RB_HALT; 1083225617Skmacy return (sys_reboot(td, &r)); 108411397Sswallace case SCO_AD_BOOT: 108511397Sswallace case SCO_AD_IBOOT: 108611397Sswallace r.opt = RB_AUTOBOOT; 1087225617Skmacy return (sys_reboot(td, &r)); 108811397Sswallace } 108911397Sswallace return EINVAL; 109011397Sswallace case SCO_A_REMOUNT: 109111397Sswallace case SCO_A_CLOCK: 109211397Sswallace case SCO_A_SETCONFIG: 109311397Sswallace return 0; 109411397Sswallace case SCO_A_GETDEV: 109511397Sswallace return EINVAL; /* XXX - TODO */ 109611397Sswallace } 109711397Sswallace return EINVAL; 10983584Ssos} 10993584Ssos 11003584Ssosint 110183366Sjulianibcs2_sysfs(td, uap) 110283366Sjulian struct thread *td; 110311397Sswallace struct ibcs2_sysfs_args *uap; 11043584Ssos{ 110511397Sswallace#define IBCS2_GETFSIND 1 110611397Sswallace#define IBCS2_GETFSTYP 2 110711397Sswallace#define IBCS2_GETNFSTYP 3 11088876Srgrimes 1109107849Salfred switch(uap->cmd) { 111011397Sswallace case IBCS2_GETFSIND: 111111397Sswallace case IBCS2_GETFSTYP: 111211397Sswallace case IBCS2_GETNFSTYP: 111328748Sbde break; 11143584Ssos } 111511397Sswallace return EINVAL; /* XXX - TODO */ 11163584Ssos} 11173584Ssos 11183584Ssosint 111983366Sjulianibcs2_unlink(td, uap) 112083366Sjulian struct thread *td; 112111397Sswallace struct ibcs2_unlink_args *uap; 11223584Ssos{ 1123141488Sjhb char *path; 1124141488Sjhb int error; 112511397Sswallace 1126141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1127141488Sjhb error = kern_unlink(td, path, UIO_SYSSPACE); 1128141488Sjhb free(path, M_TEMP); 1129141488Sjhb return (error); 11303584Ssos} 11313584Ssos 11323584Ssosint 113383366Sjulianibcs2_chdir(td, uap) 113483366Sjulian struct thread *td; 113511397Sswallace struct ibcs2_chdir_args *uap; 11363584Ssos{ 1137141488Sjhb char *path; 1138141488Sjhb int error; 113911397Sswallace 1140141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1141141488Sjhb error = kern_chdir(td, path, UIO_SYSSPACE); 1142141488Sjhb free(path, M_TEMP); 1143141488Sjhb return (error); 11443584Ssos} 11453584Ssos 11463584Ssosint 114783366Sjulianibcs2_chmod(td, uap) 114883366Sjulian struct thread *td; 114911397Sswallace struct ibcs2_chmod_args *uap; 11503584Ssos{ 1151141488Sjhb char *path; 1152141488Sjhb int error; 11533584Ssos 1154141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1155141488Sjhb error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode); 1156141488Sjhb free(path, M_TEMP); 1157141488Sjhb return (error); 11583584Ssos} 11593584Ssos 11603584Ssosint 116183366Sjulianibcs2_chown(td, uap) 116283366Sjulian struct thread *td; 116311397Sswallace struct ibcs2_chown_args *uap; 11643584Ssos{ 1165141488Sjhb char *path; 1166141488Sjhb int error; 11673584Ssos 1168141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1169141488Sjhb error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid); 1170141488Sjhb free(path, M_TEMP); 1171141488Sjhb return (error); 11723584Ssos} 11733584Ssos 11743584Ssosint 117583366Sjulianibcs2_rmdir(td, uap) 117683366Sjulian struct thread *td; 117711397Sswallace struct ibcs2_rmdir_args *uap; 11783584Ssos{ 1179141488Sjhb char *path; 1180141488Sjhb int error; 11813584Ssos 1182141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1183141488Sjhb error = kern_rmdir(td, path, UIO_SYSSPACE); 1184141488Sjhb free(path, M_TEMP); 1185141488Sjhb return (error); 11863584Ssos} 11873584Ssos 11883584Ssosint 118983366Sjulianibcs2_mkdir(td, uap) 119083366Sjulian struct thread *td; 119111397Sswallace struct ibcs2_mkdir_args *uap; 11923584Ssos{ 1193141488Sjhb char *path; 1194141488Sjhb int error; 11953584Ssos 1196141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1197141488Sjhb error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode); 1198141488Sjhb free(path, M_TEMP); 1199141488Sjhb return (error); 12003584Ssos} 12013584Ssos 12023584Ssosint 120383366Sjulianibcs2_symlink(td, uap) 120483366Sjulian struct thread *td; 120511397Sswallace struct ibcs2_symlink_args *uap; 12063584Ssos{ 1207141488Sjhb char *path, *link; 1208141488Sjhb int error; 12093584Ssos 1210141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1211141488Sjhb 1212141488Sjhb /* 1213141488Sjhb * Have to expand CHECKALTCREAT() so that 'path' can be freed on 1214141488Sjhb * errors. 1215141488Sjhb */ 1216141488Sjhb error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1); 1217141488Sjhb if (link == NULL) { 1218141488Sjhb free(path, M_TEMP); 1219141488Sjhb return (error); 1220141488Sjhb } 1221141488Sjhb error = kern_symlink(td, path, link, UIO_SYSSPACE); 1222141488Sjhb free(path, M_TEMP); 1223141488Sjhb free(link, M_TEMP); 1224141488Sjhb return (error); 12253584Ssos} 12263584Ssos 12273584Ssosint 122883366Sjulianibcs2_rename(td, uap) 122983366Sjulian struct thread *td; 123011397Sswallace struct ibcs2_rename_args *uap; 12313584Ssos{ 1232141488Sjhb char *from, *to; 1233141488Sjhb int error; 12343584Ssos 1235141488Sjhb CHECKALTEXIST(td, uap->from, &from); 1236141488Sjhb 1237141488Sjhb /* 1238141488Sjhb * Have to expand CHECKALTCREAT() so that 'from' can be freed on 1239141488Sjhb * errors. 1240141488Sjhb */ 1241141488Sjhb error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1); 1242167900Sjhb if (to == NULL) { 1243141488Sjhb free(from, M_TEMP); 1244141488Sjhb return (error); 1245141488Sjhb } 1246141488Sjhb error = kern_rename(td, from, to, UIO_SYSSPACE); 1247141488Sjhb free(from, M_TEMP); 1248141488Sjhb free(to, M_TEMP); 1249141488Sjhb return (error); 12503584Ssos} 12513584Ssos 12523584Ssosint 125383366Sjulianibcs2_readlink(td, uap) 125483366Sjulian struct thread *td; 125511397Sswallace struct ibcs2_readlink_args *uap; 12563584Ssos{ 1257141488Sjhb char *path; 1258141488Sjhb int error; 12593584Ssos 1260141488Sjhb CHECKALTEXIST(td, uap->path, &path); 1261141488Sjhb error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE, 1262141488Sjhb uap->count); 1263141488Sjhb free(path, M_TEMP); 1264141488Sjhb return (error); 12653584Ssos} 1266