/* $NetBSD: netbsd32_netbsd.c,v 1.9 1999/03/25 15:34:37 mrg Exp $ */ /* * Copyright (c) 1998 Matthew R. Green * 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. 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. */ #include "opt_ktrace.h" #include "opt_ntp.h" #include "opt_compat_freebsd.h" #include "opt_compat_linux.h" #include "opt_compat_sunos.h" #include "opt_compat_43.h" #if defined(COMPAT_43) || defined(COMPAT_SUNOS) || defined(COMPAT_LINUX) || \ defined(COMPAT_FREEBSD) #define COMPAT_OLDSOCK /* used by */ #endif #include "fs_lfs.h" #include "fs_nfs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static __inline void sparc32_from_timeval __P((struct timeval *, struct sparc32_timeval *)); static __inline void sparc32_to_timeval __P((struct sparc32_timeval *, struct timeval *)); static __inline void sparc32_from_itimerval __P((struct itimerval *, struct sparc32_itimerval *)); static __inline void sparc32_to_itimerval __P((struct sparc32_itimerval *, struct itimerval *)); static __inline void sparc32_to_timespec __P((struct sparc32_timespec *, struct timespec *)); static __inline void sparc32_from_timespec __P((struct timespec *, struct sparc32_timespec *)); static __inline void sparc32_from_rusage __P((struct rusage *, struct sparc32_rusage *)); static __inline void sparc32_to_rusage __P((struct sparc32_rusage *, struct rusage *)); static __inline int sparc32_to_iovecin __P((struct sparc32_iovec *, struct iovec *, int)); static __inline void sparc32_to_msghdr __P((struct sparc32_msghdr *, struct msghdr *)); static __inline void sparc32_from_msghdr __P((struct sparc32_msghdr *, struct msghdr *)); static __inline void sparc32_from_statfs __P((struct statfs *, struct sparc32_statfs *)); static __inline void sparc32_from_timex __P((struct timex *, struct sparc32_timex *)); static __inline void sparc32_to_timex __P((struct sparc32_timex *, struct timex *)); static __inline void sparc32_from___stat13 __P((struct stat *, struct sparc32_stat *)); static __inline void sparc32_to_ipc_perm __P((struct sparc32_ipc_perm *, struct ipc_perm *)); static __inline void sparc32_from_ipc_perm __P((struct ipc_perm *, struct sparc32_ipc_perm *)); static __inline void sparc32_to_msg __P((struct sparc32_msg *, struct msg *)); static __inline void sparc32_from_msg __P((struct msg *, struct sparc32_msg *)); static __inline void sparc32_to_msqid_ds __P((struct sparc32_msqid_ds *, struct msqid_ds *)); static __inline void sparc32_from_msqid_ds __P((struct msqid_ds *, struct sparc32_msqid_ds *)); static __inline void sparc32_to_shmid_ds __P((struct sparc32_shmid_ds *, struct shmid_ds *)); static __inline void sparc32_from_shmid_ds __P((struct shmid_ds *, struct sparc32_shmid_ds *)); static __inline void sparc32_to_semid_ds __P((struct sparc32_semid_ds *, struct semid_ds *)); static __inline void sparc32_from_semid_ds __P((struct semid_ds *, struct sparc32_semid_ds *)); static int recvit32 __P((struct proc *, int, struct sparc32_msghdr *, struct iovec *, caddr_t, register_t *)); static int dofilereadv32 __P((struct proc *, int, struct file *, struct sparc32_iovec *, int, off_t *, int, register_t *)); static int dofilewritev32 __P((struct proc *, int, struct file *, struct sparc32_iovec *, int, off_t *, int, register_t *)); static int change_utimes32 __P((struct vnode *, struct timeval *, struct proc *)); /* converters for structures that we need */ static __inline void sparc32_from_timeval(tv, tv32) struct timeval *tv; struct sparc32_timeval *tv32; { tv32->tv_sec = (sparc32_long)tv->tv_sec; tv32->tv_usec = (sparc32_long)tv->tv_usec; } static __inline void sparc32_to_timeval(tv32, tv) struct sparc32_timeval *tv32; struct timeval *tv; { tv->tv_sec = (long)tv32->tv_sec; tv->tv_usec = (long)tv32->tv_usec; } static __inline void sparc32_from_itimerval(itv, itv32) struct itimerval *itv; struct sparc32_itimerval *itv32; { sparc32_from_timeval(&itv->it_interval, &itv32->it_interval); sparc32_from_timeval(&itv->it_value, &itv32->it_value); } static __inline void sparc32_to_itimerval(itv32, itv) struct sparc32_itimerval *itv32; struct itimerval *itv; { sparc32_to_timeval(&itv32->it_interval, &itv->it_interval); sparc32_to_timeval(&itv32->it_value, &itv->it_value); } static __inline void sparc32_to_timespec(s32p, p) struct sparc32_timespec *s32p; struct timespec *p; { p->tv_sec = s32p->tv_sec; p->tv_nsec = (long)s32p->tv_nsec; } static __inline void sparc32_from_timespec(p, s32p) struct timespec *p; struct sparc32_timespec *s32p; { s32p->tv_sec = p->tv_sec; s32p->tv_nsec = (sparc32_long)p->tv_nsec; } static __inline void sparc32_from_rusage(rup, ru32p) struct rusage *rup; struct sparc32_rusage *ru32p; { sparc32_from_timeval(&rup->ru_utime, &ru32p->ru_utime); sparc32_from_timeval(&rup->ru_stime, &ru32p->ru_stime); #define C(var) ru32p->var = (sparc32_long)rup->var C(ru_maxrss); C(ru_ixrss); C(ru_idrss); C(ru_isrss); C(ru_minflt); C(ru_majflt); C(ru_nswap); C(ru_inblock); C(ru_oublock); C(ru_msgsnd); C(ru_msgrcv); C(ru_nsignals); C(ru_nvcsw); C(ru_nivcsw); #undef C } static __inline void sparc32_to_rusage(ru32p, rup) struct sparc32_rusage *ru32p; struct rusage *rup; { sparc32_to_timeval(&ru32p->ru_utime, &rup->ru_utime); sparc32_to_timeval(&ru32p->ru_stime, &rup->ru_stime); #define C(var) rup->var = (long)ru32p->var C(ru_maxrss); C(ru_ixrss); C(ru_idrss); C(ru_isrss); C(ru_minflt); C(ru_majflt); C(ru_nswap); C(ru_inblock); C(ru_oublock); C(ru_msgsnd); C(ru_msgrcv); C(ru_nsignals); C(ru_nvcsw); C(ru_nivcsw); #undef C } static __inline int sparc32_to_iovecin(iov32p, iovp, len) struct sparc32_iovec *iov32p; struct iovec *iovp; int len; { int i, error=0; u_int32_t iov_base; u_int32_t iov_len; /* * We could allocate an iov32p, do a copyin, and translate * each field and then free it all up, or we could copyin * each field separately. I'm doing the latter to reduce * the number of MALLOC()s. */ printf("converting iovec at %p len %lx to %p\n", iov32p, len, iovp); for (i = 0; i < len; i++, iovp++, iov32p++) { if ((error = copyin((caddr_t)&iov32p->iov_base, &iov_base, sizeof(iov_base)))) return (error); if ((error = copyin((caddr_t)&iov32p->iov_len, &iov_len, sizeof(iov_len)))) return (error); iovp->iov_base = (void *)(u_long)iov_base; iovp->iov_len = (size_t)iov_len; printf("iovec slot %d base %p len %lx\n", i, iovp->iov_base, iovp->iov_len); } } /* msg_iov must be done separately */ static __inline void sparc32_to_msghdr(mhp32, mhp) struct sparc32_msghdr *mhp32; struct msghdr *mhp; { mhp->msg_name = (caddr_t)(u_long)mhp32->msg_name; mhp->msg_namelen = mhp32->msg_namelen; mhp->msg_iovlen = (size_t)mhp32->msg_iovlen; mhp->msg_control = (caddr_t)(u_long)mhp32->msg_control; mhp->msg_controllen = mhp32->msg_controllen; mhp->msg_flags = mhp32->msg_flags; } /* msg_iov must be done separately */ static __inline void sparc32_from_msghdr(mhp32, mhp) struct sparc32_msghdr *mhp32; struct msghdr *mhp; { mhp32->msg_name = mhp32->msg_name; mhp32->msg_namelen = mhp32->msg_namelen; mhp32->msg_iovlen = mhp32->msg_iovlen; mhp32->msg_control = mhp32->msg_control; mhp32->msg_controllen = mhp->msg_controllen; mhp32->msg_flags = mhp->msg_flags; } static __inline void sparc32_from_statfs(sbp, sb32p) struct statfs *sbp; struct sparc32_statfs *sb32p; { sb32p->f_type = sbp->f_type; sb32p->f_flags = sbp->f_flags; sb32p->f_bsize = (sparc32_long)sbp->f_bsize; sb32p->f_iosize = (sparc32_long)sbp->f_iosize; sb32p->f_blocks = (sparc32_long)sbp->f_blocks; sb32p->f_bfree = (sparc32_long)sbp->f_bfree; sb32p->f_bavail = (sparc32_long)sbp->f_bavail; sb32p->f_files = (sparc32_long)sbp->f_files; sb32p->f_ffree = (sparc32_long)sbp->f_ffree; sb32p->f_fsid = sbp->f_fsid; sb32p->f_owner = sbp->f_owner; sb32p->f_spare[0] = 0; sb32p->f_spare[1] = 0; sb32p->f_spare[2] = 0; sb32p->f_spare[3] = 0; #if 1 /* May as well do the whole batch in one go */ memcpy(sb32p->f_fstypename, sbp->f_fstypename, MFSNAMELEN+MNAMELEN+MNAMELEN); #else /* If we want to be careful */ memcpy(sb32p->f_fstypename, sbp->f_fstypename, MFSNAMELEN); memcpy(sb32p->f_mntonname, sbp->f_mntonname, MNAMELEN); memcpy(sb32p->f_mntfromname, sbp->f_mntfromname, MNAMELEN); #endif } static __inline void sparc32_from_timex(txp, tx32p) struct timex *txp; struct sparc32_timex *tx32p; { tx32p->modes = txp->modes; tx32p->offset = (sparc32_long)txp->offset; tx32p->freq = (sparc32_long)txp->freq; tx32p->maxerror = (sparc32_long)txp->maxerror; tx32p->esterror = (sparc32_long)txp->esterror; tx32p->status = txp->status; tx32p->constant = (sparc32_long)txp->constant; tx32p->precision = (sparc32_long)txp->precision; tx32p->tolerance = (sparc32_long)txp->tolerance; tx32p->ppsfreq = (sparc32_long)txp->ppsfreq; tx32p->jitter = (sparc32_long)txp->jitter; tx32p->shift = txp->shift; tx32p->stabil = (sparc32_long)txp->stabil; tx32p->jitcnt = (sparc32_long)txp->jitcnt; tx32p->calcnt = (sparc32_long)txp->calcnt; tx32p->errcnt = (sparc32_long)txp->errcnt; tx32p->stbcnt = (sparc32_long)txp->stbcnt; } static __inline void sparc32_to_timex(tx32p, txp) struct sparc32_timex *tx32p; struct timex *txp; { txp->modes = tx32p->modes; txp->offset = (long)tx32p->offset; txp->freq = (long)tx32p->freq; txp->maxerror = (long)tx32p->maxerror; txp->esterror = (long)tx32p->esterror; txp->status = tx32p->status; txp->constant = (long)tx32p->constant; txp->precision = (long)tx32p->precision; txp->tolerance = (long)tx32p->tolerance; txp->ppsfreq = (long)tx32p->ppsfreq; txp->jitter = (long)tx32p->jitter; txp->shift = tx32p->shift; txp->stabil = (long)tx32p->stabil; txp->jitcnt = (long)tx32p->jitcnt; txp->calcnt = (long)tx32p->calcnt; txp->errcnt = (long)tx32p->errcnt; txp->stbcnt = (long)tx32p->stbcnt; } static __inline void sparc32_from___stat13(sbp, sb32p) struct stat *sbp; struct sparc32_stat *sb32p; { sb32p->st_dev = sbp->st_dev; sb32p->st_ino = sbp->st_ino; sb32p->st_mode = sbp->st_mode; sb32p->st_nlink = sbp->st_nlink; sb32p->st_uid = sbp->st_uid; sb32p->st_gid = sbp->st_gid; sb32p->st_rdev = sbp->st_rdev; if (sbp->st_size < (quad_t)1 << 32) sb32p->st_size = sbp->st_size; else sb32p->st_size = -2; sb32p->st_atimespec.tv_sec = sbp->st_atimespec.tv_sec; sb32p->st_atimespec.tv_nsec = (sparc32_long)sbp->st_atimespec.tv_nsec; sb32p->st_mtimespec.tv_sec = sbp->st_mtimespec.tv_sec; sb32p->st_mtimespec.tv_nsec = (sparc32_long)sbp->st_mtimespec.tv_nsec; sb32p->st_ctimespec.tv_sec = sbp->st_ctimespec.tv_sec; sb32p->st_ctimespec.tv_nsec = (sparc32_long)sbp->st_ctimespec.tv_nsec; sb32p->st_blksize = sbp->st_blksize; sb32p->st_blocks = sbp->st_blocks; sb32p->st_flags = sbp->st_flags; sb32p->st_gen = sbp->st_gen; } static __inline void sparc32_to_ipc_perm(ip32p, ipp) struct sparc32_ipc_perm *ip32p; struct ipc_perm *ipp; { ipp->cuid = ip32p->cuid; ipp->cgid = ip32p->cgid; ipp->uid = ip32p->uid; ipp->gid = ip32p->gid; ipp->mode = ip32p->mode; ipp->seq = ip32p->seq; ipp->key = (key_t)ip32p->key; } static __inline void sparc32_from_ipc_perm(ipp, ip32p) struct ipc_perm *ipp; struct sparc32_ipc_perm *ip32p; { ip32p->cuid = ipp->cuid; ip32p->cgid = ipp->cgid; ip32p->uid = ipp->uid; ip32p->gid = ipp->gid; ip32p->mode = ipp->mode; ip32p->seq = ipp->seq; ip32p->key = (sparc32_key_t)ipp->key; } static __inline void sparc32_to_msg(m32p, mp) struct sparc32_msg *m32p; struct msg *mp; { mp->msg_next = (struct msg *)(u_long)m32p->msg_next; mp->msg_type = (long)m32p->msg_type; mp->msg_ts = m32p->msg_ts; mp->msg_spot = m32p->msg_spot; } static __inline void sparc32_from_msg(mp, m32p) struct msg *mp; struct sparc32_msg *m32p; { m32p->msg_next = (sparc32_msgp_t)(u_long)mp->msg_next; m32p->msg_type = (sparc32_long)mp->msg_type; m32p->msg_ts = mp->msg_ts; m32p->msg_spot = mp->msg_spot; } static __inline void sparc32_to_msqid_ds(ds32p, dsp) struct sparc32_msqid_ds *ds32p; struct msqid_ds *dsp; { sparc32_to_ipc_perm(&ds32p->msg_perm, &dsp->msg_perm); sparc32_to_msg((struct sparc32_msg *)(u_long)ds32p->msg_first, dsp->msg_first); sparc32_to_msg((struct sparc32_msg *)(u_long)ds32p->msg_last, dsp->msg_last); dsp->msg_cbytes = (u_long)ds32p->msg_cbytes; dsp->msg_qnum = (u_long)ds32p->msg_qnum; dsp->msg_qbytes = (u_long)ds32p->msg_qbytes; dsp->msg_lspid = ds32p->msg_lspid; dsp->msg_lrpid = ds32p->msg_lrpid; dsp->msg_rtime = (time_t)ds32p->msg_rtime; dsp->msg_stime = (time_t)ds32p->msg_stime; dsp->msg_ctime = (time_t)ds32p->msg_ctime; } static __inline void sparc32_from_msqid_ds(dsp, ds32p) struct msqid_ds *dsp; struct sparc32_msqid_ds *ds32p; { sparc32_from_ipc_perm(&dsp->msg_perm, &ds32p->msg_perm); sparc32_from_msg(dsp->msg_first, (struct sparc32_msg *)(u_long)ds32p->msg_first); sparc32_from_msg(dsp->msg_last, (struct sparc32_msg *)(u_long)ds32p->msg_last); ds32p->msg_cbytes = (sparc32_u_long)dsp->msg_cbytes; ds32p->msg_qnum = (sparc32_u_long)dsp->msg_qnum; ds32p->msg_qbytes = (sparc32_u_long)dsp->msg_qbytes; ds32p->msg_lspid = dsp->msg_lspid; ds32p->msg_lrpid = dsp->msg_lrpid; ds32p->msg_rtime = dsp->msg_rtime; ds32p->msg_stime = dsp->msg_stime; ds32p->msg_ctime = dsp->msg_ctime; } static __inline void sparc32_to_shmid_ds(ds32p, dsp) struct sparc32_shmid_ds *ds32p; struct shmid_ds *dsp; { sparc32_to_ipc_perm(&ds32p->shm_perm, &dsp->shm_perm); dsp->shm_segsz = ds32p->shm_segsz; dsp->shm_lpid = ds32p->shm_lpid; dsp->shm_cpid = ds32p->shm_cpid; dsp->shm_nattch = ds32p->shm_nattch; dsp->shm_atime = (long)ds32p->shm_atime; dsp->shm_dtime = (long)ds32p->shm_dtime; dsp->shm_ctime = (long)ds32p->shm_ctime; dsp->shm_internal = (void *)(u_long)ds32p->shm_internal; } static __inline void sparc32_from_shmid_ds(dsp, ds32p) struct shmid_ds *dsp; struct sparc32_shmid_ds *ds32p; { sparc32_from_ipc_perm(&dsp->shm_perm, &ds32p->shm_perm); ds32p->shm_segsz = dsp->shm_segsz; ds32p->shm_lpid = dsp->shm_lpid; ds32p->shm_cpid = dsp->shm_cpid; ds32p->shm_nattch = dsp->shm_nattch; ds32p->shm_atime = (sparc32_long)dsp->shm_atime; ds32p->shm_dtime = (sparc32_long)dsp->shm_dtime; ds32p->shm_ctime = (sparc32_long)dsp->shm_ctime; ds32p->shm_internal = (sparc32_voidp)(u_long)dsp->shm_internal; } static __inline void sparc32_to_semid_ds(s32dsp, dsp) struct sparc32_semid_ds *s32dsp; struct semid_ds *dsp; { sparc32_from_ipc_perm(&dsp->sem_perm, &s32dsp->sem_perm); dsp->sem_base = (struct sem *)(u_long)s32dsp->sem_base; dsp->sem_nsems = s32dsp->sem_nsems; dsp->sem_otime = s32dsp->sem_otime; dsp->sem_ctime = s32dsp->sem_ctime; } static __inline void sparc32_from_semid_ds(dsp, s32dsp) struct semid_ds *dsp; struct sparc32_semid_ds *s32dsp; { sparc32_to_ipc_perm(&s32dsp->sem_perm, &dsp->sem_perm); s32dsp->sem_base = (sparc32_semp_t)(u_long)dsp->sem_base; s32dsp->sem_nsems = dsp->sem_nsems; s32dsp->sem_otime = dsp->sem_otime; s32dsp->sem_ctime = dsp->sem_ctime; } /* * below are all the standard NetBSD system calls, in the 32bit * environment, witht he necessary conversions to 64bit before * calling the real syscall. */ int compat_sparc32_exit(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_exit_args /* { syscallarg(int) rval; } */ *uap = v; struct sys_exit_args ua; SPARC32TO64_UAP(rval); sys_exit(p, &ua, retval); } int compat_sparc32_read(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_read_args /* { syscallarg(int) fd; syscallarg(sparc32_voidp) buf; syscallarg(sparc32_size_t) nbyte; } */ *uap = v; struct sys_read_args ua; SPARC32TO64_UAP(fd); SPARC32TOP_UAP(buf, void *); SPARC32TOX_UAP(nbyte, size_t); return sys_read(p, &ua, retval); } int compat_sparc32_write(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_write_args /* { syscallarg(int) fd; syscallarg(const sparc32_voidp) buf; syscallarg(sparc32_size_t) nbyte; } */ *uap = v; struct sys_write_args ua; SPARC32TO64_UAP(fd); SPARC32TOP_UAP(buf, void *); SPARC32TOX_UAP(nbyte, size_t); return sys_write(p, &ua, retval); } int compat_sparc32_close(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_close_args /* { syscallarg(int) fd; } */ *uap = v; struct sys_close_args ua; SPARC32TO64_UAP(fd); return sys_write(p, &ua, retval); } int compat_sparc32_open(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_open_args /* { syscallarg(const sparc32_charp) path; syscallarg(int) flags; syscallarg(mode_t) mode; } */ *uap = v; struct sys_open_args ua; caddr_t sg; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(flags); SPARC32TO64_UAP(mode); sg = stackgap_init(p->p_emul); SPARC32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path)); return (sys_open(p, &ua, retval)); } int compat_sparc32_wait4(q, v, retval) struct proc *q; void *v; register_t *retval; { struct compat_sparc32_wait4_args /* { syscallarg(int) pid; syscallarg(sparc32_intp) status; syscallarg(int) options; syscallarg(sparc32_rusagep_t) rusage; } */ *uap = v; struct sparc32_rusage ru32; register int nfound; register struct proc *p, *t; int status, error; if (SCARG(uap, pid) == 0) SCARG(uap, pid) = -q->p_pgid; if (SCARG(uap, options) &~ (WUNTRACED|WNOHANG)) return (EINVAL); loop: nfound = 0; for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) { if (SCARG(uap, pid) != WAIT_ANY && p->p_pid != SCARG(uap, pid) && p->p_pgid != -SCARG(uap, pid)) continue; nfound++; if (p->p_stat == SZOMB) { retval[0] = p->p_pid; if (SCARG(uap, status)) { status = p->p_xstat; /* convert to int */ error = copyout((caddr_t)&status, (caddr_t)(u_long)SCARG(uap, status), sizeof(status)); if (error) return (error); } if (SCARG(uap, rusage)) { sparc32_from_rusage(p->p_ru, &ru32); if ((error = copyout((caddr_t)&ru32, (caddr_t)(u_long)SCARG(uap, rusage), sizeof(struct sparc32_rusage)))) return (error); } /* * If we got the child via ptrace(2) or procfs, and * the parent is different (meaning the process was * attached, rather than run as a child), then we need * to give it back to the old parent, and send the * parent a SIGCHLD. The rest of the cleanup will be * done when the old parent waits on the child. */ if ((p->p_flag & P_TRACED) && p->p_oppid != p->p_pptr->p_pid) { t = pfind(p->p_oppid); proc_reparent(p, t ? t : initproc); p->p_oppid = 0; p->p_flag &= ~(P_TRACED|P_WAITED|P_FSTRACE); psignal(p->p_pptr, SIGCHLD); wakeup((caddr_t)p->p_pptr); return (0); } p->p_xstat = 0; ruadd(&q->p_stats->p_cru, p->p_ru); pool_put(&rusage_pool, p->p_ru); /* * Finally finished with old proc entry. * Unlink it from its process group and free it. */ leavepgrp(p); LIST_REMOVE(p, p_list); /* off zombproc */ LIST_REMOVE(p, p_sibling); /* * Decrement the count of procs running with this uid. */ (void)chgproccnt(p->p_cred->p_ruid, -1); /* * Free up credentials. */ if (--p->p_cred->p_refcnt == 0) { crfree(p->p_cred->pc_ucred); pool_put(&pcred_pool, p->p_cred); } /* * Release reference to text vnode */ if (p->p_textvp) vrele(p->p_textvp); /* * Give machine-dependent layer a chance * to free anything that cpu_exit couldn't * release while still running in process context. */ cpu_wait(p); pool_put(&proc_pool, p); nprocs--; return (0); } if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 && (p->p_flag & P_TRACED || SCARG(uap, options) & WUNTRACED)) { p->p_flag |= P_WAITED; retval[0] = p->p_pid; if (SCARG(uap, status)) { status = W_STOPCODE(p->p_xstat); error = copyout((caddr_t)&status, (caddr_t)(u_long)SCARG(uap, status), sizeof(status)); } else error = 0; return (error); } } if (nfound == 0) return (ECHILD); if (SCARG(uap, options) & WNOHANG) { retval[0] = 0; return (0); } if ((error = tsleep((caddr_t)q, PWAIT | PCATCH, "wait", 0)) != 0) return (error); goto loop; } int compat_sparc32_link(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_link_args /* { syscallarg(const sparc32_charp) path; syscallarg(const sparc32_charp) link; } */ *uap = v; struct sys_link_args ua; SPARC32TOP_UAP(path, const char); SPARC32TOP_UAP(link, const char); return (sys_link(p, &ua, retval)); } int compat_sparc32_unlink(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_unlink_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_unlink_args ua; SPARC32TOP_UAP(path, const char); return (sys_unlink(p, &ua, retval)); } int compat_sparc32_chdir(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_chdir_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_chdir_args ua; SPARC32TOP_UAP(path, const char); return (sys_chdir(p, &ua, retval)); } int compat_sparc32_fchdir(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fchdir_args /* { syscallarg(int) fd; } */ *uap = v; struct sys_fchdir_args ua; SPARC32TO64_UAP(fd); return (sys_fchdir(p, &ua, retval)); } int compat_sparc32_mknod(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mknod_args /* { syscallarg(const sparc32_charp) path; syscallarg(mode_t) mode; syscallarg(dev_t) dev; } */ *uap = v; struct sys_mknod_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(dev); SPARC32TO64_UAP(mode); return (sys_mknod(p, &ua, retval)); } int compat_sparc32_chmod(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_chmod_args /* { syscallarg(const sparc32_charp) path; syscallarg(mode_t) mode; } */ *uap = v; struct sys_chmod_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(mode); return (sys_chmod(p, &ua, retval)); } int compat_sparc32_chown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_chown_args /* { syscallarg(const sparc32_charp) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct sys_chown_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(uid); SPARC32TO64_UAP(gid); return (sys_chown(p, &ua, retval)); } int compat_sparc32_break(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_break_args /* { syscallarg(sparc32_charp) nsize; } */ *uap = v; struct sys_obreak_args ua; SCARG(&ua, nsize) = (char *)(u_long)SCARG(uap, nsize); SPARC32TOP_UAP(nsize, char); return (sys_obreak(p, &ua, retval)); } int compat_sparc32_getfsstat(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getfsstat_args /* { syscallarg(sparc32_statfsp_t) buf; syscallarg(sparc32_long) bufsize; syscallarg(int) flags; } */ *uap = v; struct sys_getfsstat_args ua; struct statfs sb; struct sparc32_statfs *sb32p; int error; sb32p = (struct sparc32_statfs *)(u_long)SCARG(uap, buf); if (sb32p) SCARG(&ua, buf) = &sb; else SCARG(&ua, buf) = NULL; SPARC32TOX_UAP(bufsize, long); SPARC32TO64_UAP(flags); error = sys_getfsstat(p, &ua, retval); if (error) return (error); if (sb32p) { struct sparc32_statfs sb32; sparc32_from_statfs(&sb, &sb32); if (copyout(&sb32, sb32p, sizeof(sb32))) return EFAULT; } return (0); } int compat_sparc32_mount(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mount_args /* { syscallarg(const sparc32_charp) type; syscallarg(const sparc32_charp) path; syscallarg(int) flags; syscallarg(sparc32_voidp) data; } */ *uap = v; struct sys_mount_args ua; SPARC32TOP_UAP(type, const char); SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(flags); SPARC32TOP_UAP(data, void); return (sys_mount(p, &ua, retval)); } int compat_sparc32_unmount(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_unmount_args /* { syscallarg(const sparc32_charp) path; syscallarg(int) flags; } */ *uap = v; struct sys_unmount_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(flags); return (sys_unmount(p, &ua, retval)); } int compat_sparc32_setuid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setuid_args /* { syscallarg(uid_t) uid; } */ *uap = v; struct sys_setuid_args ua; SPARC32TO64_UAP(uid); return (sys_setuid(p, &ua, retval)); } int compat_sparc32_ptrace(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_ptrace_args /* { syscallarg(int) req; syscallarg(pid_t) pid; syscallarg(sparc32_caddr_t) addr; syscallarg(int) data; } */ *uap = v; struct sys_ptrace_args ua; SPARC32TO64_UAP(req); SPARC32TO64_UAP(pid); SPARC32TOX64_UAP(addr, caddr_t); SPARC32TO64_UAP(data); return (sys_ptrace(p, &ua, retval)); } int compat_sparc32_recvmsg(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_recvmsg_args /* { syscallarg(int) s; syscallarg(sparc32_msghdrp_t) msg; syscallarg(int) flags; } */ *uap = v; struct sparc32_msghdr msg; struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; register int error; error = copyin((caddr_t)(u_long)SCARG(uap, msg), (caddr_t)&msg, sizeof(msg)); /* sparc32_msghdr needs the iov pre-allocated */ if (error) return (error); if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) { if ((u_int)msg.msg_iovlen > IOV_MAX) return (EMSGSIZE); MALLOC(iov, struct iovec *, sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, M_WAITOK); } else if ((u_int)msg.msg_iovlen > 0) iov = aiov; else return (EMSGSIZE); #ifdef COMPAT_OLDSOCK msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT; #else msg.msg_flags = SCARG(uap, flags); #endif uiov = (struct iovec *)(u_long)msg.msg_iov; error = sparc32_to_iovecin((struct sparc32_iovec *)uiov, iov, msg.msg_iovlen); if (error) goto done; if ((error = recvit32(p, SCARG(uap, s), &msg, iov, (caddr_t)0, retval)) == 0) { error = copyout((caddr_t)&msg, (caddr_t)(u_long)SCARG(uap, msg), sizeof(msg)); } done: if (iov != aiov) FREE(iov, M_IOV); return (error); } int recvit32(p, s, mp, iov, namelenp, retsize) struct proc *p; int s; struct sparc32_msghdr *mp; struct iovec *iov; caddr_t namelenp; register_t *retsize; { struct file *fp; struct uio auio; register int i; int len, error; struct mbuf *from = 0, *control = 0; struct socket *so; #ifdef KTRACE struct iovec *ktriov = NULL; #endif if ((error = getsock(p->p_fd, s, &fp)) != 0) return (error); auio.uio_iov = (struct iovec *)(u_long)mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_READ; auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; for (i = 0; i < mp->msg_iovlen; i++, iov++) { #if 0 /* cannot happen iov_len is unsigned */ if (iov->iov_len < 0) return (EINVAL); #endif /* * Reads return ssize_t because -1 is returned on error. * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ auio.uio_resid += iov->iov_len; if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) return (EINVAL); } #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { int iovlen = auio.uio_iovcnt * sizeof(struct iovec); MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); } #endif len = auio.uio_resid; so = (struct socket *)fp->f_data; error = (*so->so_receive)(so, &from, &auio, NULL, mp->msg_control ? &control : NULL, &mp->msg_flags); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p->p_tracep, s, UIO_READ, ktriov, len - auio.uio_resid, error); FREE(ktriov, M_TEMP); } #endif if (error) goto out; *retsize = len - auio.uio_resid; if (mp->msg_name) { len = mp->msg_namelen; if (len <= 0 || from == 0) len = 0; else { #ifdef COMPAT_OLDSOCK if (mp->msg_flags & MSG_COMPAT) mtod(from, struct osockaddr *)->sa_family = mtod(from, struct sockaddr *)->sa_family; #endif if (len > from->m_len) len = from->m_len; /* else if len < from->m_len ??? */ error = copyout(mtod(from, caddr_t), (caddr_t)(u_long)mp->msg_name, (unsigned)len); if (error) goto out; } mp->msg_namelen = len; if (namelenp && (error = copyout((caddr_t)&len, namelenp, sizeof(int)))) { #ifdef COMPAT_OLDSOCK if (mp->msg_flags & MSG_COMPAT) error = 0; /* old recvfrom didn't check */ else #endif goto out; } } if (mp->msg_control) { #ifdef COMPAT_OLDSOCK /* * We assume that old recvmsg calls won't receive access * rights and other control info, esp. as control info * is always optional and those options didn't exist in 4.3. * If we receive rights, trim the cmsghdr; anything else * is tossed. */ if (control && mp->msg_flags & MSG_COMPAT) { if (mtod(control, struct cmsghdr *)->cmsg_level != SOL_SOCKET || mtod(control, struct cmsghdr *)->cmsg_type != SCM_RIGHTS) { mp->msg_controllen = 0; goto out; } control->m_len -= sizeof(struct cmsghdr); control->m_data += sizeof(struct cmsghdr); } #endif len = mp->msg_controllen; if (len <= 0 || control == 0) len = 0; else { struct mbuf *m = control; caddr_t p = (caddr_t)(u_long)mp->msg_control; do { i = m->m_len; if (len < i) { mp->msg_flags |= MSG_CTRUNC; i = len; } error = copyout(mtod(m, caddr_t), p, (unsigned)i); if (m->m_next) i = ALIGN(i); p += i; len -= i; if (error != 0 || len <= 0) break; } while ((m = m->m_next) != NULL); len = p - (caddr_t)(u_long)mp->msg_control; } mp->msg_controllen = len; } out: if (from) m_freem(from); if (control) m_freem(control); return (error); } int compat_sparc32_sendmsg(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sendmsg_args /* { syscallarg(int) s; syscallarg(const sparc32_msghdrp_t) msg; syscallarg(int) flags; } */ *uap = v; struct msghdr msg; struct sparc32_msghdr msg32; struct iovec aiov[UIO_SMALLIOV], *iov; int error; error = copyin((caddr_t)(u_long)SCARG(uap, msg), (caddr_t)&msg32, sizeof(msg32)); if (error) return (error); sparc32_to_msghdr(&msg32, &msg); if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) { if ((u_int)msg.msg_iovlen > IOV_MAX) return (EMSGSIZE); MALLOC(iov, struct iovec *, sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, M_WAITOK); } else if ((u_int)msg.msg_iovlen > 0) iov = aiov; else return (EMSGSIZE); error = sparc32_to_iovecin((struct sparc32_iovec *)msg.msg_iov, iov, msg.msg_iovlen); if (error) goto done; msg.msg_iov = iov; #ifdef COMPAT_OLDSOCK msg.msg_flags = 0; #endif /* Luckily we can use this directly */ error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); done: if (iov != aiov) FREE(iov, M_IOV); return (error); } int compat_sparc32_recvfrom(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_recvfrom_args /* { syscallarg(int) s; syscallarg(sparc32_voidp) buf; syscallarg(sparc32_size_t) len; syscallarg(int) flags; syscallarg(sparc32_sockaddrp_t) from; syscallarg(sparc32_intp) fromlenaddr; } */ *uap = v; struct sparc32_msghdr msg; struct iovec aiov; int error; if (SCARG(uap, fromlenaddr)) { error = copyin((caddr_t)(u_long)SCARG(uap, fromlenaddr), (caddr_t)&msg.msg_namelen, sizeof(msg.msg_namelen)); if (error) return (error); } else msg.msg_namelen = 0; msg.msg_name = SCARG(uap, from); msg.msg_iov = NULL; /* We can't store a real pointer here */ msg.msg_iovlen = 1; aiov.iov_base = (caddr_t)(u_long)SCARG(uap, buf); aiov.iov_len = (u_long)SCARG(uap, len); msg.msg_control = 0; msg.msg_flags = SCARG(uap, flags); return (recvit32(p, SCARG(uap, s), &msg, &aiov, (caddr_t)(u_long)SCARG(uap, fromlenaddr), retval)); } int compat_sparc32_sendto(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sendto_args /* { syscallarg(int) s; syscallarg(const sparc32_voidp) buf; syscallarg(sparc32_size_t) len; syscallarg(int) flags; syscallarg(const sparc32_sockaddrp_t) to; syscallarg(int) tolen; } */ *uap = v; struct msghdr msg; struct iovec aiov; msg.msg_name = (caddr_t)(u_long)SCARG(uap, to); /* XXX kills const */ msg.msg_namelen = SCARG(uap, tolen); msg.msg_iov = &aiov; msg.msg_iovlen = 1; msg.msg_control = 0; #ifdef COMPAT_OLDSOCK msg.msg_flags = 0; #endif aiov.iov_base = (char *)(u_long)SCARG(uap, buf); /* XXX kills const */ aiov.iov_len = SCARG(uap, len); return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval)); } int compat_sparc32_accept(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_accept_args /* { syscallarg(int) s; syscallarg(sparc32_sockaddrp_t) name; syscallarg(sparc32_intp) anamelen; } */ *uap = v; struct sys_accept_args ua; SPARC32TO64_UAP(s); SPARC32TOP_UAP(name, struct sockaddr); SPARC32TOP_UAP(anamelen, int); return (sys_accept(p, &ua, retval)); } int compat_sparc32_getpeername(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getpeername_args /* { syscallarg(int) fdes; syscallarg(sparc32_sockaddrp_t) asa; syscallarg(sparc32_intp) alen; } */ *uap = v; struct sys_getpeername_args ua; SPARC32TO64_UAP(fdes); SPARC32TOP_UAP(asa, struct sockaddr); SPARC32TOP_UAP(alen, int); /* NB: do the protocol specific sockaddrs need to be converted? */ return (sys_getpeername(p, &ua, retval)); } int compat_sparc32_getsockname(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getsockname_args /* { syscallarg(int) fdes; syscallarg(sparc32_sockaddrp_t) asa; syscallarg(sparc32_intp) alen; } */ *uap = v; struct sys_getsockname_args ua; SPARC32TO64_UAP(fdes); SPARC32TOP_UAP(asa, struct sockaddr); SPARC32TOP_UAP(alen, int); return (sys_getsockname(p, &ua, retval)); } int compat_sparc32_access(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_access_args /* { syscallarg(const sparc32_charp) path; syscallarg(int) flags; } */ *uap = v; struct sys_access_args ua; caddr_t sg; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(flags); sg = stackgap_init(p->p_emul); SPARC32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path)); return (sys_access(p, &ua, retval)); } int compat_sparc32_chflags(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_chflags_args /* { syscallarg(const sparc32_charp) path; syscallarg(sparc32_u_long) flags; } */ *uap = v; struct sys_chflags_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(flags); return (sys_chflags(p, &ua, retval)); } int compat_sparc32_fchflags(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fchflags_args /* { syscallarg(int) fd; syscallarg(sparc32_u_long) flags; } */ *uap = v; struct sys_fchflags_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(flags); return (sys_fchflags(p, &ua, retval)); } int compat_sparc32_kill(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_kill_args /* { syscallarg(int) pid; syscallarg(int) signum; } */ *uap = v; struct sys_kill_args ua; SPARC32TO64_UAP(pid); SPARC32TO64_UAP(signum); return (sys_kill(p, &ua, retval)); } int compat_sparc32_dup(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_dup_args /* { syscallarg(int) fd; } */ *uap = v; struct sys_dup_args ua; SPARC32TO64_UAP(fd); return (sys_dup(p, &ua, retval)); } int compat_sparc32_profil(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_profil_args /* { syscallarg(sparc32_caddr_t) samples; syscallarg(sparc32_size_t) size; syscallarg(sparc32_u_long) offset; syscallarg(u_int) scale; } */ *uap = v; struct sys_profil_args ua; SPARC32TOX64_UAP(samples, caddr_t); SPARC32TOX_UAP(size, size_t); SPARC32TOX_UAP(offset, u_long); SPARC32TO64_UAP(scale); return (sys_profil(p, &ua, retval)); } int compat_sparc32_ktrace(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_ktrace_args /* { syscallarg(const sparc32_charp) fname; syscallarg(int) ops; syscallarg(int) facs; syscallarg(int) pid; } */ *uap = v; struct sys_ktrace_args ua; SPARC32TOP_UAP(fname, const char); SPARC32TO64_UAP(ops); SPARC32TO64_UAP(facs); SPARC32TO64_UAP(pid); return (sys_ktrace(p, &ua, retval)); } int compat_sparc32_sigaction(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sigaction_args /* { syscallarg(int) signum; syscallarg(const sparc32_sigactionp_t) nsa; syscallarg(sparc32_sigactionp_t) osa; } */ *uap = v; struct sigaction nsa, osa; struct sparc32_sigaction *sa32p, sa32; int error; if (SCARG(uap, nsa)) { sa32p = (struct sparc32_sigaction *)(u_long)SCARG(uap, nsa); if (copyin(sa32p, &sa32, sizeof(sa32))) return EFAULT; nsa.sa_handler = (void *)(u_long)sa32.sa_handler; nsa.sa_mask = sa32.sa_mask; nsa.sa_flags = sa32.sa_flags; } error = sigaction1(p, SCARG(uap, signum), SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0); if (error) return (error); if (SCARG(uap, osa)) { sa32.sa_handler = (sparc32_sigactionp_t)(u_long)osa.sa_handler; sa32.sa_mask = osa.sa_mask; sa32.sa_flags = osa.sa_flags; sa32p = (struct sparc32_sigaction *)(u_long)SCARG(uap, osa); if (copyout(&sa32, sa32p, sizeof(sa32))) return EFAULT; } return (0); } int compat_sparc32___getlogin(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___getlogin_args /* { syscallarg(sparc32_charp) namebuf; syscallarg(u_int) namelen; } */ *uap = v; struct sys___getlogin_args ua; SPARC32TOP_UAP(namebuf, char); SPARC32TO64_UAP(namelen); return (sys___getlogin(p, &ua, retval)); } int compat_sparc32_setlogin(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setlogin_args /* { syscallarg(const sparc32_charp) namebuf; } */ *uap = v; struct sys_setlogin_args ua; SPARC32TOP_UAP(namebuf, char); return (sys_setlogin(p, &ua, retval)); } int compat_sparc32_acct(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_acct_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_acct_args ua; SPARC32TOP_UAP(path, const char); return (sys_acct(p, &ua, retval)); } int compat_sparc32_revoke(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_revoke_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_revoke_args ua; caddr_t sg; SPARC32TOP_UAP(path, const char); sg = stackgap_init(p->p_emul); SPARC32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path)); return (sys_revoke(p, &ua, retval)); } int compat_sparc32_symlink(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_symlink_args /* { syscallarg(const sparc32_charp) path; syscallarg(const sparc32_charp) link; } */ *uap = v; struct sys_symlink_args ua; SPARC32TOP_UAP(path, const char); SPARC32TOP_UAP(link, const char); return (sys_symlink(p, &ua, retval)); } int compat_sparc32_readlink(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_readlink_args /* { syscallarg(const sparc32_charp) path; syscallarg(sparc32_charp) buf; syscallarg(sparc32_size_t) count; } */ *uap = v; struct sys_readlink_args ua; caddr_t sg; SPARC32TOP_UAP(path, const char); SPARC32TOP_UAP(buf, char); SPARC32TOX_UAP(count, size_t); sg = stackgap_init(p->p_emul); SPARC32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path)); return (sys_readlink(p, &ua, retval)); } int compat_sparc32_execve(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_execve_args /* { syscallarg(const sparc32_charp) path; syscallarg(sparc32_charpp) argp; syscallarg(sparc32_charpp) envp; } */ *uap = v; struct sys_execve_args ua; caddr_t sg; SPARC32TOP_UAP(path, const char); SPARC32TOP_UAP(argp, char *); SPARC32TOP_UAP(envp, char *); sg = stackgap_init(p->p_emul); SPARC32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path)); return (sys_execve(p, &ua, retval)); } int compat_sparc32_umask(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_umask_args /* { syscallarg(mode_t) newmask; } */ *uap = v; struct sys_umask_args ua; SPARC32TO64_UAP(newmask); return (sys_umask(p, &ua, retval)); } int compat_sparc32_chroot(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_chroot_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_chroot_args ua; SPARC32TOP_UAP(path, const char); return (sys_chroot(p, &ua, retval)); } int compat_sparc32_sbrk(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sbrk_args /* { syscallarg(int) incr; } */ *uap = v; struct sys_sbrk_args ua; SPARC32TO64_UAP(incr); return (sys_sbrk(p, &ua, retval)); } int compat_sparc32_sstk(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sstk_args /* { syscallarg(int) incr; } */ *uap = v; struct sys_sstk_args ua; SPARC32TO64_UAP(incr); return (sys_sstk(p, &ua, retval)); } int compat_sparc32_munmap(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_munmap_args /* { syscallarg(sparc32_voidp) addr; syscallarg(sparc32_size_t) len; } */ *uap = v; struct sys_munmap_args ua; SPARC32TOP_UAP(addr, void); SPARC32TOX_UAP(len, size_t); return (sys_munmap(p, &ua, retval)); } int compat_sparc32_mprotect(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mprotect_args /* { syscallarg(sparc32_voidp) addr; syscallarg(sparc32_size_t) len; syscallarg(int) prot; } */ *uap = v; struct sys_mprotect_args ua; SPARC32TOP_UAP(addr, void); SPARC32TOX_UAP(len, size_t); SPARC32TO64_UAP(prot); return (sys_mprotect(p, &ua, retval)); } int compat_sparc32_madvise(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_madvise_args /* { syscallarg(sparc32_voidp) addr; syscallarg(sparc32_size_t) len; syscallarg(int) behav; } */ *uap = v; struct sys_madvise_args ua; SPARC32TOP_UAP(addr, void); SPARC32TOX_UAP(len, size_t); SPARC32TO64_UAP(behav); return (sys_madvise(p, &ua, retval)); } int compat_sparc32_mincore(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mincore_args /* { syscallarg(sparc32_caddr_t) addr; syscallarg(sparc32_size_t) len; syscallarg(sparc32_charp) vec; } */ *uap = v; struct sys_mincore_args ua; SPARC32TOX64_UAP(addr, caddr_t); SPARC32TOX_UAP(len, size_t); SPARC32TOP_UAP(vec, char); return (sys_mincore(p, &ua, retval)); } int compat_sparc32_getgroups(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getgroups_args /* { syscallarg(int) gidsetsize; syscallarg(sparc32_gid_tp) gidset; } */ *uap = v; register struct pcred *pc = p->p_cred; register int ngrp; int error; ngrp = SCARG(uap, gidsetsize); if (ngrp == 0) { *retval = pc->pc_ucred->cr_ngroups; return (0); } if (ngrp < pc->pc_ucred->cr_ngroups) return (EINVAL); ngrp = pc->pc_ucred->cr_ngroups; /* Should convert gid_t to sparc32_gid_t, but they're the same */ error = copyout((caddr_t)pc->pc_ucred->cr_groups, (caddr_t)(u_long)SCARG(uap, gidset), ngrp * sizeof(gid_t)); if (error) return (error); *retval = ngrp; return (0); } int compat_sparc32_setgroups(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setgroups_args /* { syscallarg(int) gidsetsize; syscallarg(const sparc32_gid_tp) gidset; } */ *uap = v; struct sys_setgroups_args ua; SPARC32TO64_UAP(gidsetsize); SPARC32TOP_UAP(gidset, gid_t); return (sys_setgroups(p, &ua, retval)); } int compat_sparc32_setpgid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setpgid_args /* { syscallarg(int) pid; syscallarg(int) pgid; } */ *uap = v; struct sys_setpgid_args ua; SPARC32TO64_UAP(pid); SPARC32TO64_UAP(pgid); return (sys_setpgid(p, &ua, retval)); } int compat_sparc32_setitimer(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setitimer_args /* { syscallarg(int) which; syscallarg(const sparc32_itimervalp_t) itv; syscallarg(sparc32_itimervalp_t) oitv; } */ *uap = v; struct sparc32_itimerval s32it, *itvp; int which = SCARG(uap, which); struct compat_sparc32_getitimer_args getargs; struct itimerval aitv; int s, error; if ((u_int)which > ITIMER_PROF) return (EINVAL); itvp = (struct sparc32_itimerval *)(u_long)SCARG(uap, itv); if (itvp && (error = copyin(itvp, &s32it, sizeof(s32it)))) return (error); sparc32_to_itimerval(&s32it, &aitv); if (SCARG(uap, oitv) != NULL) { SCARG(&getargs, which) = which; SCARG(&getargs, itv) = SCARG(uap, oitv); if ((error = compat_sparc32_getitimer(p, &getargs, retval)) != 0) return (error); } if (itvp == 0) return (0); if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) return (EINVAL); s = splclock(); if (which == ITIMER_REAL) { untimeout(realitexpire, p); if (timerisset(&aitv.it_value)) { timeradd(&aitv.it_value, &time, &aitv.it_value); timeout(realitexpire, p, hzto(&aitv.it_value)); } p->p_realtimer = aitv; } else p->p_stats->p_timer[which] = aitv; splx(s); return (0); } int compat_sparc32_getitimer(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getitimer_args /* { syscallarg(int) which; syscallarg(sparc32_itimervalp_t) itv; } */ *uap = v; int which = SCARG(uap, which); struct sparc32_itimerval s32it; struct itimerval aitv; int s; if ((u_int)which > ITIMER_PROF) return (EINVAL); s = splclock(); if (which == ITIMER_REAL) { /* * Convert from absolute to relative time in .it_value * part of real time timer. If time for real time timer * has passed return 0, else return difference between * current time and time for the timer to go off. */ aitv = p->p_realtimer; if (timerisset(&aitv.it_value)) { if (timercmp(&aitv.it_value, &time, <)) timerclear(&aitv.it_value); else timersub(&aitv.it_value, &time, &aitv.it_value); } } else aitv = p->p_stats->p_timer[which]; splx(s); sparc32_from_itimerval(&aitv, &s32it); return (copyout(&s32it, (caddr_t)(u_long)SCARG(uap, itv), sizeof(s32it))); } int compat_sparc32_fcntl(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fcntl_args /* { syscallarg(int) fd; syscallarg(int) cmd; syscallarg(sparc32_voidp) arg; } */ *uap = v; struct sys_fcntl_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(cmd); SPARC32TOP_UAP(arg, void); /* XXXX we can do this 'cause flock doesn't change */ return (sys_fcntl(p, &ua, retval)); } int compat_sparc32_dup2(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_dup2_args /* { syscallarg(int) from; syscallarg(int) to; } */ *uap = v; struct sys_dup2_args ua; SPARC32TO64_UAP(from); SPARC32TO64_UAP(to); return (sys_dup2(p, &ua, retval)); } int compat_sparc32_select(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_select_args /* { syscallarg(int) nd; syscallarg(sparc32_fd_setp_t) in; syscallarg(sparc32_fd_setp_t) ou; syscallarg(sparc32_fd_setp_t) ex; syscallarg(sparc32_timevalp_t) tv; } */ *uap = v; /* This one must be done in-line 'cause of the timeval */ struct sparc32_timeval tv32; caddr_t bits; char smallbits[howmany(FD_SETSIZE, NFDBITS) * sizeof(fd_mask) * 6]; struct timeval atv; int s, ncoll, error = 0, timo; size_t ni; extern int selwait, nselcoll; extern int selscan __P((struct proc *, fd_mask *, fd_mask *, int, register_t *)); if (SCARG(uap, nd) < 0) return (EINVAL); if (SCARG(uap, nd) > p->p_fd->fd_nfiles) { /* forgiving; slightly wrong */ SCARG(uap, nd) = p->p_fd->fd_nfiles; } ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask); if (ni * 6 > sizeof(smallbits)) bits = malloc(ni * 6, M_TEMP, M_WAITOK); else bits = smallbits; #define getbits(name, x) \ if (SCARG(uap, name)) { \ error = copyin((caddr_t)(u_long)SCARG(uap, name), bits + ni * x, ni); \ if (error) \ goto done; \ } else \ memset(bits + ni * x, 0, ni); getbits(in, 0); getbits(ou, 1); getbits(ex, 2); #undef getbits if (SCARG(uap, tv)) { error = copyin((caddr_t)(u_long)SCARG(uap, tv), (caddr_t)&tv32, sizeof(tv32)); if (error) goto done; sparc32_to_timeval(&tv32, &atv); if (itimerfix(&atv)) { error = EINVAL; goto done; } s = splclock(); timeradd(&atv, &time, &atv); timo = hzto(&atv); /* * Avoid inadvertently sleeping forever. */ if (timo == 0) timo = 1; splx(s); } else timo = 0; retry: ncoll = nselcoll; p->p_flag |= P_SELECT; error = selscan(p, (fd_mask *)(bits + ni * 0), (fd_mask *)(bits + ni * 3), SCARG(uap, nd), retval); if (error || *retval) goto done; s = splhigh(); if (timo && timercmp(&time, &atv, >=)) { splx(s); goto done; } if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { splx(s); goto retry; } p->p_flag &= ~P_SELECT; error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); splx(s); if (error == 0) goto retry; done: p->p_flag &= ~P_SELECT; /* select is not restarted after signals... */ if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; if (error == 0) { #define putbits(name, x) \ if (SCARG(uap, name)) { \ error = copyout(bits + ni * x, (caddr_t)(u_long)SCARG(uap, name), ni); \ if (error) \ goto out; \ } putbits(in, 3); putbits(ou, 4); putbits(ex, 5); #undef putbits } out: if (ni * 6 > sizeof(smallbits)) free(bits, M_TEMP); return (error); } int compat_sparc32_fsync(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fsync_args /* { syscallarg(int) fd; } */ *uap = v; struct sys_fsync_args ua; SPARC32TO64_UAP(fd); return (sys_fsync(p, &ua, retval)); } int compat_sparc32_setpriority(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setpriority_args /* { syscallarg(int) which; syscallarg(int) who; syscallarg(int) prio; } */ *uap = v; struct sys_setpriority_args ua; SPARC32TO64_UAP(which); SPARC32TO64_UAP(who); SPARC32TO64_UAP(prio); return (sys_setpriority(p, &ua, retval)); } int compat_sparc32_socket(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_socket_args /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; } */ *uap = v; struct sys_socket_args ua; SPARC32TO64_UAP(domain); SPARC32TO64_UAP(type); SPARC32TO64_UAP(protocol); return (sys_socket(p, &ua, retval)); } int compat_sparc32_connect(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_connect_args /* { syscallarg(int) s; syscallarg(const sparc32_sockaddrp_t) name; syscallarg(int) namelen; } */ *uap = v; struct sys_connect_args ua; SPARC32TO64_UAP(s); SPARC32TOP_UAP(name, struct sockaddr); SPARC32TO64_UAP(namelen); return (sys_connect(p, &ua, retval)); } int compat_sparc32_getpriority(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getpriority_args /* { syscallarg(int) which; syscallarg(int) who; } */ *uap = v; struct sys_getpriority_args ua; SPARC32TO64_UAP(which); SPARC32TO64_UAP(who); return (sys_getpriority(p, &ua, retval)); } #undef DEBUG int compat_sparc32_sigreturn(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sigreturn_args /* { syscallarg(struct sparc32_sigcontext *) sigcntxp; } */ *uap = v; struct sparc32_sigcontext *scp; struct sparc32_sigcontext sc; register struct trapframe *tf; struct rwindow32 *rwstack, *kstack; sigset_t mask; /* First ensure consistent stack state (see sendsig). */ write_user_windows(); if (rwindow_save(p)) { #ifdef DEBUG printf("sigreturn: rwindow_save(%p) failed, sending SIGILL\n", p); Debugger(); #endif sigexit(p, SIGILL); } #ifdef DEBUG if (sigdebug & SDB_FOLLOW) { printf("sigreturn: %s[%d], sigcntxp %p\n", p->p_comm, p->p_pid, SCARG(uap, sigcntxp)); if (sigdebug & SDB_DDB) Debugger(); } #endif scp = (struct sparc32_sigcontext *)(u_long)SCARG(uap, sigcntxp); if ((vaddr_t)scp & 3 || (copyin((caddr_t)scp, &sc, sizeof sc) != 0)) #ifdef DEBUG { printf("sigreturn: copyin failed\n"); Debugger(); return (EINVAL); } #else return (EINVAL); #endif tf = p->p_md.md_tf; /* * Only the icc bits in the psr are used, so it need not be * verified. pc and npc must be multiples of 4. This is all * that is required; if it holds, just do it. */ if (((sc.sc_pc | sc.sc_npc) & 3) != 0) #ifdef DEBUG { printf("sigreturn: pc %p or npc %p invalid\n", sc.sc_pc, sc.sc_npc); Debugger(); return (EINVAL); } #else return (EINVAL); #endif /* take only psr ICC field */ tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(sc.sc_psr); tf->tf_pc = (int64_t)sc.sc_pc; tf->tf_npc = (int64_t)sc.sc_npc; tf->tf_global[1] = (int64_t)sc.sc_g1; tf->tf_out[0] = (int64_t)sc.sc_o0; tf->tf_out[6] = (int64_t)sc.sc_sp; rwstack = (struct rwindow32 *)tf->tf_out[6]; kstack = (struct rwindow32 *)(((caddr_t)tf)-CCFSZ); #ifdef DEBUG if (sigdebug & SDB_FOLLOW) { printf("sys_sigreturn: return trapframe pc=%p sp=%p tstate=%x\n", (int)tf->tf_pc, (int)tf->tf_out[6], (int)tf->tf_tstate); if (sigdebug & SDB_DDB) Debugger(); } #endif if (scp->sc_onstack & SS_ONSTACK) p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; else p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; /* Restore signal mask */ native_sigset13_to_sigset(&scp->sc_mask, &mask); (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); return (EJUSTRETURN); } int compat_sparc32_bind(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_bind_args /* { syscallarg(int) s; syscallarg(const sparc32_sockaddrp_t) name; syscallarg(int) namelen; } */ *uap = v; struct sys_bind_args ua; SPARC32TO64_UAP(s); SPARC32TOP_UAP(name, struct sockaddr); SPARC32TO64_UAP(namelen); return (sys_bind(p, &ua, retval)); } int compat_sparc32_setsockopt(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setsockopt_args /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(const sparc32_voidp) val; syscallarg(int) valsize; } */ *uap = v; struct sys_setsockopt_args ua; SPARC32TO64_UAP(s); SPARC32TO64_UAP(level); SPARC32TO64_UAP(name); SPARC32TOP_UAP(val, void); SPARC32TO64_UAP(valsize); /* may be more efficient to do this inline. */ return (sys_setsockopt(p, &ua, retval)); } int compat_sparc32_listen(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_listen_args /* { syscallarg(int) s; syscallarg(int) backlog; } */ *uap = v; struct sys_listen_args ua; SPARC32TO64_UAP(s); SPARC32TO64_UAP(backlog); return (sys_listen(p, &ua, retval)); } int compat_sparc32_vtrace(p, v, retval) struct proc *p; void *v; register_t *retval; { #ifdef TRACE struct compat_sparc32_vtrace_args /* { syscallarg(int) request; syscallarg(int) value; } */ *uap = v; struct sys_vtrace_args ua; SPARC32TO64_UAP(request); SPARC32TO64_UAP(value); return (vtrace(p, &ua, retval)); #else return (ENOSYS); #endif } int compat_sparc32_gettimeofday(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_gettimeofday_args /* { syscallarg(sparc32_timevalp_t) tp; syscallarg(sparc32_timezonep_t) tzp; } */ *uap = v; struct timeval atv; struct sparc32_timeval tv32; int error = 0; struct sparc32_timezone tzfake; if (SCARG(uap, tp)) { microtime(&atv); sparc32_from_timeval(&atv, &tv32); error = copyout(&tv32, (caddr_t)(u_long)SCARG(uap, tp), sizeof(tv32)); if (error) return (error); } if (SCARG(uap, tzp)) { /* * NetBSD has no kernel notion of time zone, so we just * fake up a timezone struct and return it if demanded. */ tzfake.tz_minuteswest = 0; tzfake.tz_dsttime = 0; error = copyout(&tzfake, (caddr_t)(u_long)SCARG(uap, tzp), sizeof(tzfake)); } return (error); } static int settime __P((struct timeval *)); /* This function is used by clock_settime and settimeofday */ static int settime(tv) struct timeval *tv; { struct timeval delta; int s; /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ s = splclock(); timersub(tv, &time, &delta); if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1) return (EPERM); #ifdef notyet if ((delta.tv_sec < 86400) && securelevel > 0) return (EPERM); #endif time = *tv; (void) splsoftclock(); timeradd(&boottime, &delta, &boottime); timeradd(&runtime, &delta, &runtime); # if defined(NFS) || defined(NFSSERVER) nqnfs_lease_updatetime(delta.tv_sec); # endif splx(s); resettodr(); return (0); } int compat_sparc32_settimeofday(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_settimeofday_args /* { syscallarg(const sparc32_timevalp_t) tv; syscallarg(const sparc32_timezonep_t) tzp; } */ *uap = v; struct sparc32_timeval atv32; struct timeval atv; struct sparc32_timezone atz; int error; if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); /* Verify all parameters before changing time. */ if (SCARG(uap, tv) && (error = copyin((caddr_t)(u_long)SCARG(uap, tv), &atv32, sizeof(atv32)))) return (error); sparc32_to_timeval(&atv32, &atv); /* XXX since we don't use tz, probably no point in doing copyin. */ if (SCARG(uap, tzp) && (error = copyin((caddr_t)(u_long)SCARG(uap, tzp), &atz, sizeof(atz)))) return (error); if (SCARG(uap, tv)) if ((error = settime(&atv))) return (error); /* * NetBSD has no kernel notion of time zone, and only an * obsolete program would try to set it, so we log a warning. */ if (SCARG(uap, tzp)) printf("pid %d attempted to set the " "(obsolete) kernel time zone\n", p->p_pid); return (0); } int compat_sparc32_fchown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fchown_args /* { syscallarg(int) fd; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct sys_fchown_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(uid); SPARC32TO64_UAP(gid); return (sys_fchown(p, &ua, retval)); } int compat_sparc32_fchmod(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fchmod_args /* { syscallarg(int) fd; syscallarg(mode_t) mode; } */ *uap = v; struct sys_fchmod_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(mode); return (sys_fchmod(p, &ua, retval)); } int compat_sparc32_setreuid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setreuid_args /* { syscallarg(uid_t) ruid; syscallarg(uid_t) euid; } */ *uap = v; struct sys_setreuid_args ua; SPARC32TO64_UAP(ruid); SPARC32TO64_UAP(euid); return (sys_setreuid(p, &ua, retval)); } int compat_sparc32_setregid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setregid_args /* { syscallarg(gid_t) rgid; syscallarg(gid_t) egid; } */ *uap = v; struct sys_setregid_args ua; SPARC32TO64_UAP(rgid); SPARC32TO64_UAP(egid); return (sys_setregid(p, &ua, retval)); } int compat_sparc32_getrusage(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getrusage_args /* { syscallarg(int) who; syscallarg(sparc32_rusagep_t) rusage; } */ *uap = v; struct rusage *rup; struct sparc32_rusage ru; switch (SCARG(uap, who)) { case RUSAGE_SELF: rup = &p->p_stats->p_ru; calcru(p, &rup->ru_utime, &rup->ru_stime, NULL); break; case RUSAGE_CHILDREN: rup = &p->p_stats->p_cru; break; default: return (EINVAL); } sparc32_from_rusage(rup, &ru); return (copyout(&ru, (caddr_t)(u_long)SCARG(uap, rusage), sizeof(ru))); } int compat_sparc32_getsockopt(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getsockopt_args /* { syscallarg(int) s; syscallarg(int) level; syscallarg(int) name; syscallarg(sparc32_voidp) val; syscallarg(sparc32_intp) avalsize; } */ *uap = v; struct sys_getsockopt_args ua; SPARC32TO64_UAP(s); SPARC32TO64_UAP(level); SPARC32TO64_UAP(name); SPARC32TOP_UAP(val, void); SPARC32TOP_UAP(avalsize, int); return (sys_getsockopt(p, &ua, retval)); } int compat_sparc32_readv(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_readv_args /* { syscallarg(int) fd; syscallarg(const sparc32_iovecp_t) iovp; syscallarg(int) iovcnt; } */ *uap = v; int fd = SCARG(uap, fd); register struct file *fp; register struct filedesc *fdp = p->p_fd; if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL || (fp->f_flag & FREAD) == 0) return (EBADF); return (dofilereadv32(p, fd, fp, (struct sparc32_iovec *)(u_long)SCARG(uap, iovp), SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval)); } /* Damn thing copies in the iovec! */ int dofilereadv32(p, fd, fp, iovp, iovcnt, offset, flags, retval) struct proc *p; int fd; struct file *fp; struct sparc32_iovec *iovp; int iovcnt; off_t *offset; int flags; register_t *retval; { struct uio auio; register struct iovec *iov; struct iovec *needfree; struct iovec aiov[UIO_SMALLIOV]; long i, cnt, error = 0; u_int iovlen; #ifdef KTRACE struct iovec *ktriov = NULL; #endif /* note: can't use iovlen until iovcnt is validated */ iovlen = iovcnt * sizeof(struct iovec); if ((u_int)iovcnt > UIO_SMALLIOV) { if ((u_int)iovcnt > IOV_MAX) return (EINVAL); MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); needfree = iov; } else if ((u_int)iovcnt > 0) { iov = aiov; needfree = NULL; } else return (EINVAL); auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; error = sparc32_to_iovecin(iovp, iov, iovcnt); if (error) goto done; auio.uio_resid = 0; for (i = 0; i < iovcnt; i++) { auio.uio_resid += iov->iov_len; /* * Reads return ssize_t because -1 is returned on error. * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { error = EINVAL; goto done; } iov++; } #ifdef KTRACE /* * if tracing, save a copy of iovec */ if (KTRPOINT(p, KTR_GENIO)) { MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); } #endif cnt = auio.uio_resid; error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred, flags); if (error) if (auio.uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; cnt -= auio.uio_resid; #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) if (error == 0) { ktrgenio(p->p_tracep, fd, UIO_READ, ktriov, cnt, error); FREE(ktriov, M_TEMP); } #endif *retval = cnt; done: if (needfree) FREE(needfree, M_IOV); return (error); } int compat_sparc32_writev(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_writev_args /* { syscallarg(int) fd; syscallarg(const sparc32_iovecp_t) iovp; syscallarg(int) iovcnt; } */ *uap = v; int fd = SCARG(uap, fd); register struct file *fp; register struct filedesc *fdp = p->p_fd; if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL || (fp->f_flag & FWRITE) == 0) return (EBADF); return (dofilewritev32(p, fd, fp, (struct sparc32_iovec *)(u_long)SCARG(uap, iovp), SCARG(uap, iovcnt), &fp->f_offset, FOF_UPDATE_OFFSET, retval)); } int dofilewritev32(p, fd, fp, iovp, iovcnt, offset, flags, retval) struct proc *p; int fd; struct file *fp; struct sparc32_iovec *iovp; int iovcnt; off_t *offset; int flags; register_t *retval; { struct uio auio; register struct iovec *iov; struct iovec *needfree; struct iovec aiov[UIO_SMALLIOV]; long i, cnt, error = 0; u_int iovlen; #ifdef KTRACE struct iovec *ktriov = NULL; #endif /* note: can't use iovlen until iovcnt is validated */ iovlen = iovcnt * sizeof(struct iovec); if ((u_int)iovcnt > UIO_SMALLIOV) { if ((u_int)iovcnt > IOV_MAX) return (EINVAL); MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); needfree = iov; } else if ((u_int)iovcnt > 0) { iov = aiov; needfree = NULL; } else return (EINVAL); auio.uio_iov = iov; auio.uio_iovcnt = iovcnt; auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; error = sparc32_to_iovecin(iovp, iov, iovcnt); if (error) goto done; auio.uio_resid = 0; for (i = 0; i < iovcnt; i++) { auio.uio_resid += iov->iov_len; /* * Writes return ssize_t because -1 is returned on error. * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { error = EINVAL; goto done; } iov++; } #ifdef KTRACE /* * if tracing, save a copy of iovec */ if (KTRPOINT(p, KTR_GENIO)) { MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen); } #endif cnt = auio.uio_resid; error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred, flags); if (error) { if (auio.uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; if (error == EPIPE) psignal(p, SIGPIPE); } cnt -= auio.uio_resid; #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) if (error == 0) { ktrgenio(p->p_tracep, fd, UIO_WRITE, ktriov, cnt, error); FREE(ktriov, M_TEMP); } #endif *retval = cnt; done: if (needfree) FREE(needfree, M_IOV); return (error); } int compat_sparc32_rename(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_rename_args /* { syscallarg(const sparc32_charp) from; syscallarg(const sparc32_charp) to; } */ *uap = v; struct sys_rename_args ua; SPARC32TOP_UAP(from, const char *); SPARC32TOP_UAP(to, const char *) return (sys_rename(p, &ua, retval)); } int compat_sparc32_flock(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_flock_args /* { syscallarg(int) fd; syscallarg(int) how; } */ *uap = v; struct sys_flock_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(how) return (sys_flock(p, &ua, retval)); } int compat_sparc32_mkfifo(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mkfifo_args /* { syscallarg(const sparc32_charp) path; syscallarg(mode_t) mode; } */ *uap = v; struct sys_mkfifo_args ua; SPARC32TOP_UAP(path, const char) SPARC32TO64_UAP(mode); return (sys_mkfifo(p, &ua, retval)); } int compat_sparc32_shutdown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_shutdown_args /* { syscallarg(int) s; syscallarg(int) how; } */ *uap = v; struct sys_shutdown_args ua; SPARC32TO64_UAP(s) SPARC32TO64_UAP(how); return (sys_shutdown(p, &ua, retval)); } int compat_sparc32_socketpair(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_socketpair_args /* { syscallarg(int) domain; syscallarg(int) type; syscallarg(int) protocol; syscallarg(sparc32_intp) rsv; } */ *uap = v; struct sys_socketpair_args ua; SPARC32TO64_UAP(domain); SPARC32TO64_UAP(type); SPARC32TO64_UAP(protocol); SPARC32TOP_UAP(rsv, int); /* Since we're just copying out two `int's we can do this */ return (sys_socketpair(p, &ua, retval)); } int compat_sparc32_mkdir(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mkdir_args /* { syscallarg(const sparc32_charp) path; syscallarg(mode_t) mode; } */ *uap = v; struct sys_mkdir_args ua; SPARC32TOP_UAP(path, const char) SPARC32TO64_UAP(mode); return (sys_mkdir(p, &ua, retval)); } int compat_sparc32_rmdir(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_rmdir_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_rmdir_args ua; SPARC32TOP_UAP(path, const char); return (sys_rmdir(p, &ua, retval)); } int compat_sparc32_utimes(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_utimes_args /* { syscallarg(const sparc32_charp) path; syscallarg(const sparc32_timevalp_t) tptr; } */ *uap = v; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, (char *)(u_long)SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = change_utimes32(nd.ni_vp, (struct timeval *)(u_long)SCARG(uap, tptr), p); vrele(nd.ni_vp); return (error); } /* * Common routine to set access and modification times given a vnode. */ static int change_utimes32(vp, tptr, p) struct vnode *vp; struct timeval *tptr; struct proc *p; { struct sparc32_timeval tv32[2]; struct timeval tv[2]; struct vattr vattr; int error; VATTR_NULL(&vattr); if (tptr == NULL) { microtime(&tv[0]); tv[1] = tv[0]; vattr.va_vaflags |= VA_UTIMES_NULL; } else { error = copyin(tptr, tv, sizeof(tv)); if (error) return (error); } sparc32_to_timeval(&tv32[0], &tv[0]); sparc32_to_timeval(&tv32[1], &tv[1]); VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); vattr.va_atime.tv_sec = tv[0].tv_sec; vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; vattr.va_mtime.tv_sec = tv[1].tv_sec; vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); VOP_UNLOCK(vp, 0); return (error); } int compat_sparc32_adjtime(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_adjtime_args /* { syscallarg(const sparc32_timevalp_t) delta; syscallarg(sparc32_timevalp_t) olddelta; } */ *uap = v; struct sparc32_timeval atv; int32_t ndelta, ntickdelta, odelta; int s, error; extern long bigadj, timedelta; extern int tickdelta; if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); error = copyin((caddr_t)(u_long)SCARG(uap, delta), &atv, sizeof(struct timeval)); if (error) return (error); /* * Compute the total correction and the rate at which to apply it. * Round the adjustment down to a whole multiple of the per-tick * delta, so that after some number of incremental changes in * hardclock(), tickdelta will become zero, lest the correction * overshoot and start taking us away from the desired final time. */ ndelta = atv.tv_sec * 1000000 + atv.tv_usec; if (ndelta > bigadj) ntickdelta = 10 * tickadj; else ntickdelta = tickadj; if (ndelta % ntickdelta) ndelta = ndelta / ntickdelta * ntickdelta; /* * To make hardclock()'s job easier, make the per-tick delta negative * if we want time to run slower; then hardclock can simply compute * tick + tickdelta, and subtract tickdelta from timedelta. */ if (ndelta < 0) ntickdelta = -ntickdelta; s = splclock(); odelta = timedelta; timedelta = ndelta; tickdelta = ntickdelta; splx(s); if (SCARG(uap, olddelta)) { atv.tv_sec = odelta / 1000000; atv.tv_usec = odelta % 1000000; (void) copyout(&atv, (caddr_t)(u_long)SCARG(uap, olddelta), sizeof(struct timeval)); } return (0); } int compat_sparc32_quotactl(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_quotactl_args /* { syscallarg(const sparc32_charp) path; syscallarg(int) cmd; syscallarg(int) uid; syscallarg(sparc32_caddr_t) arg; } */ *uap = v; struct sys_quotactl_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(cmd); SPARC32TO64_UAP(uid); SPARC32TOX64_UAP(arg, caddr_t); return (sys_quotactl(p, &ua, retval)); } #if defined(NFS) || defined(NFSSERVER) int compat_sparc32_nfssvc(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_nfssvc_args /* { syscallarg(int) flag; syscallarg(sparc32_voidp) argp; } */ *uap = v; struct sys_nfssvc_args ua; SPARC32TO64_UAP(flag); SPARC32TOP_UAP(argp, void); return (sys_nfssvc(p, &ua, retval)); #else /* Why would we want to support a 32-bit nfsd? */ return (ENOSYS); #endif } #endif int compat_sparc32_statfs(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_statfs_args /* { syscallarg(const sparc32_charp) path; syscallarg(sparc32_statfsp_t) buf; } */ *uap = v; register struct mount *mp; register struct statfs *sp; struct sparc32_statfs s32; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, (char *)(u_long)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; sparc32_from_statfs(sp, &s32); return (copyout(&s32, (caddr_t)(u_long)SCARG(uap, buf), sizeof(s32))); } int compat_sparc32_fstatfs(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fstatfs_args /* { syscallarg(int) fd; syscallarg(sparc32_statfsp_t) buf; } */ *uap = v; struct file *fp; register struct mount *mp; register struct statfs *sp; struct sparc32_statfs s32; 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; sparc32_from_statfs(sp, &s32); return (copyout(&s32, (caddr_t)(u_long)SCARG(uap, buf), sizeof(s32))); } #if defined(NFS) || defined(NFSSERVER) int compat_sparc32_getfh(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getfh_args /* { syscallarg(const sparc32_charp) fname; syscallarg(sparc32_fhandlep_t) fhp; } */ *uap = v; struct sys_getfh_args ua; SPARC32TOP_UAP(fname, const char); SPARC32TOP_UAP(fhp, struct fhandle); /* Lucky for us a fhandlep_t doesn't change sizes */ return (sys_getfh(p, &ua, retval)); } #endif int compat_sparc32_sysarch(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_sysarch_args /* { syscallarg(int) op; syscallarg(sparc32_voidp) parms; } */ *uap = v; switch (SCARG(uap, op)) { default: printf("(sparc64) compat_sparc32_sysarch(%d)\n", SCARG(uap, op)); return EINVAL; } } int compat_sparc32_pread(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_pread_args /* { syscallarg(int) fd; syscallarg(sparc32_voidp) buf; syscallarg(sparc32_size_t) nbyte; syscallarg(int) pad; syscallarg(off_t) offset; } */ *uap = v; struct sys_pread_args ua; ssize_t rt; int error; SPARC32TO64_UAP(fd); SPARC32TOP_UAP(buf, void); SPARC32TOX_UAP(nbyte, size_t); SPARC32TO64_UAP(pad); SPARC32TO64_UAP(offset); error = sys_pread(p, &ua, (register_t *)&rt); *(sparc32_ssize_t *)retval = rt; return (error); } int compat_sparc32_pwrite(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_pwrite_args /* { syscallarg(int) fd; syscallarg(const sparc32_voidp) buf; syscallarg(sparc32_size_t) nbyte; syscallarg(int) pad; syscallarg(off_t) offset; } */ *uap = v; struct sys_pwrite_args ua; ssize_t rt; int error; SPARC32TO64_UAP(fd); SPARC32TOP_UAP(buf, void); SPARC32TOX_UAP(nbyte, size_t); SPARC32TO64_UAP(pad); SPARC32TO64_UAP(offset); error = sys_pwrite(p, &ua, (register_t *)&rt); *(sparc32_ssize_t *)retval = rt; return (error); } #ifdef NTP int compat_sparc32_ntp_gettime(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_ntp_gettime_args /* { syscallarg(sparc32_ntptimevalp_t) ntvp; } */ *uap = v; struct sparc32_ntptimeval ntv32; struct timeval atv; struct ntptimeval ntv; int error = 0; int s; /* The following are NTP variables */ extern long time_maxerror; extern long time_esterror; extern int time_status; extern int time_state; /* clock state */ extern int time_status; /* clock status bits */ if (SCARG(uap, ntvp)) { s = splclock(); #ifdef EXT_CLOCK /* * The microtime() external clock routine returns a * status code. If less than zero, we declare an error * in the clock status word and return the kernel * (software) time variable. While there are other * places that call microtime(), this is the only place * that matters from an application point of view. */ if (microtime(&atv) < 0) { time_status |= STA_CLOCKERR; ntv.time = time; } else time_status &= ~STA_CLOCKERR; #else /* EXT_CLOCK */ microtime(&atv); #endif /* EXT_CLOCK */ ntv.time = atv; ntv.maxerror = time_maxerror; ntv.esterror = time_esterror; (void) splx(s); sparc32_from_timeval(&ntv.time, &ntv32.time); ntv32.maxerror = (sparc32_long)ntv.maxerror; ntv32.esterror = (sparc32_long)ntv.esterror; error = copyout((caddr_t)&ntv32, (caddr_t)(u_long)SCARG(uap, ntvp), sizeof(ntv32)); } if (!error) { /* * Status word error decode. If any of these conditions * occur, an error is returned, instead of the status * word. Most applications will care only about the fact * the system clock may not be trusted, not about the * details. * * Hardware or software error */ if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || /* * PPS signal lost when either time or frequency * synchronization requested */ (time_status & (STA_PPSFREQ | STA_PPSTIME) && !(time_status & STA_PPSSIGNAL)) || /* * PPS jitter exceeded when time synchronization * requested */ (time_status & STA_PPSTIME && time_status & STA_PPSJITTER) || /* * PPS wander exceeded or calibration error when * frequency synchronization requested */ (time_status & STA_PPSFREQ && time_status & (STA_PPSWANDER | STA_PPSERROR))) *retval = TIME_ERROR; else *retval = (register_t)time_state; } return(error); } int compat_sparc32_ntp_adjtime(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_ntp_adjtime_args /* { syscallarg(sparc32_timexp_t) tp; } */ *uap = v; struct sparc32_timex ntv32; struct timex ntv; int error = 0; int modes; int s; extern long time_freq; /* frequency offset (scaled ppm) */ extern long time_maxerror; extern long time_esterror; extern int time_state; /* clock state */ extern int time_status; /* clock status bits */ extern long time_constant; /* pll time constant */ extern long time_offset; /* time offset (us) */ extern long time_tolerance; /* frequency tolerance (scaled ppm) */ extern long time_precision; /* clock precision (us) */ if ((error = copyin((caddr_t)(u_long)SCARG(uap, tp), (caddr_t)&ntv32, sizeof(ntv32)))) return (error); sparc32_to_timex(&ntv32, &ntv); /* * Update selected clock variables - only the superuser can * change anything. Note that there is no error checking here on * the assumption the superuser should know what it is doing. */ modes = ntv.modes; if (modes != 0 && (error = suser(p->p_ucred, &p->p_acflag))) return (error); s = splclock(); if (modes & MOD_FREQUENCY) #ifdef PPS_SYNC time_freq = ntv.freq - pps_freq; #else /* PPS_SYNC */ time_freq = ntv.freq; #endif /* PPS_SYNC */ if (modes & MOD_MAXERROR) time_maxerror = ntv.maxerror; if (modes & MOD_ESTERROR) time_esterror = ntv.esterror; if (modes & MOD_STATUS) { time_status &= STA_RONLY; time_status |= ntv.status & ~STA_RONLY; } if (modes & MOD_TIMECONST) time_constant = ntv.constant; if (modes & MOD_OFFSET) hardupdate(ntv.offset); /* * Retrieve all clock variables */ if (time_offset < 0) ntv.offset = -(-time_offset >> SHIFT_UPDATE); else ntv.offset = time_offset >> SHIFT_UPDATE; #ifdef PPS_SYNC ntv.freq = time_freq + pps_freq; #else /* PPS_SYNC */ ntv.freq = time_freq; #endif /* PPS_SYNC */ ntv.maxerror = time_maxerror; ntv.esterror = time_esterror; ntv.status = time_status; ntv.constant = time_constant; ntv.precision = time_precision; ntv.tolerance = time_tolerance; #ifdef PPS_SYNC ntv.shift = pps_shift; ntv.ppsfreq = pps_freq; ntv.jitter = pps_jitter >> PPS_AVG; ntv.stabil = pps_stabil; ntv.calcnt = pps_calcnt; ntv.errcnt = pps_errcnt; ntv.jitcnt = pps_jitcnt; ntv.stbcnt = pps_stbcnt; #endif /* PPS_SYNC */ (void)splx(s); sparc32_from_timeval(&ntv, &ntv32); error = copyout((caddr_t)&ntv32, (caddr_t)SCARG(uap, tp), sizeof(ntv32)); if (!error) { /* * Status word error decode. See comments in * ntp_gettime() routine. */ if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || (time_status & (STA_PPSFREQ | STA_PPSTIME) && !(time_status & STA_PPSSIGNAL)) || (time_status & STA_PPSTIME && time_status & STA_PPSJITTER) || (time_status & STA_PPSFREQ && time_status & (STA_PPSWANDER | STA_PPSERROR))) *retval = TIME_ERROR; else *retval = (register_t)time_state; } return error; } #endif int compat_sparc32_setgid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setgid_args /* { syscallarg(gid_t) gid; } */ *uap = v; struct sys_setgid_args ua; SPARC32TO64_UAP(gid); return (sys_setgid(p, v, retval)); } int compat_sparc32_setegid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setegid_args /* { syscallarg(gid_t) egid; } */ *uap = v; struct sys_setegid_args ua; SPARC32TO64_UAP(egid); return (sys_setegid(p, v, retval)); } int compat_sparc32_seteuid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_seteuid_args /* { syscallarg(gid_t) euid; } */ *uap = v; struct sys_seteuid_args ua; SPARC32TO64_UAP(euid); return (sys_seteuid(p, v, retval)); } #ifdef LFS int compat_sparc32_lfs_bmapv(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_lfs_bmapv_args /* { syscallarg(sparc32_fsid_tp_t) fsidp; syscallarg(sparc32_block_infop_t) blkiov; syscallarg(int) blkcnt; } */ *uap = v; struct sys_lfs_bmapv_args ua; SPARC32TOP_UAP(fdidp, struct fsid); SPARC32TO64_UAP(blkcnt); /* XXX finish me */ #else return (ENOSYS); /* XXX */ #endif } int compat_sparc32_lfs_markv(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lfs_markv_args /* { syscallarg(sparc32_fsid_tp_t) fsidp; syscallarg(sparc32_block_infop_t) blkiov; syscallarg(int) blkcnt; } */ *uap = v; return (ENOSYS); /* XXX */ } int compat_sparc32_lfs_segclean(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lfs_segclean_args /* { syscallarg(sparc32_fsid_tp_t) fsidp; syscallarg(sparc32_u_long) segment; } */ *uap = v; return (ENOSYS); /* XXX */ } int compat_sparc32_lfs_segwait(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lfs_segwait_args /* { syscallarg(sparc32_fsid_tp_t) fsidp; syscallarg(sparc32_timevalp_t) tv; } */ *uap = v; return (ENOSYS); /* XXX */ } #endif int compat_sparc32_pathconf(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_pathconf_args /* { syscallarg(int) fd; syscallarg(int) name; } */ *uap = v; struct sys_pathconf_args ua; long rt; int error; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(name); error = sys_pathconf(p, &ua, (register_t *)&rt); *(sparc32_long *)retval = (sparc32_long)rt; return (error); } int compat_sparc32_fpathconf(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fpathconf_args /* { syscallarg(int) fd; syscallarg(int) name; } */ *uap = v; struct sys_fpathconf_args ua; long rt; int error; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(name); error = sys_fpathconf(p, &ua, (register_t *)&rt); *(sparc32_long *)retval = (sparc32_long)rt; return (error); } int compat_sparc32_getrlimit(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getrlimit_args /* { syscallarg(int) which; syscallarg(sparc32_rlimitp_t) rlp; } */ *uap = v; int which = SCARG(uap, which); if ((u_int)which >= RLIM_NLIMITS) return (EINVAL); return (copyout(&p->p_rlimit[which], (caddr_t)(u_long)SCARG(uap, rlp), sizeof(struct rlimit))); } int compat_sparc32_setrlimit(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_setrlimit_args /* { syscallarg(int) which; syscallarg(const sparc32_rlimitp_t) rlp; } */ *uap = v; int which = SCARG(uap, which); struct rlimit alim; int error; error = copyin((caddr_t)(u_long)SCARG(uap, rlp), &alim, sizeof(struct rlimit)); if (error) return (error); return (dosetrlimit(p, which, &alim)); } int compat_sparc32_mmap(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mmap_args /* { syscallarg(sparc32_voidp) addr; syscallarg(sparc32_size_t) len; syscallarg(int) prot; syscallarg(int) flags; syscallarg(int) fd; syscallarg(sparc32_long) pad; syscallarg(off_t) pos; } */ *uap = v; struct sys_mmap_args ua; void *rt; int error; SPARC32TOP_UAP(addr, void); SPARC32TOX_UAP(len, size_t); SPARC32TO64_UAP(prot); SPARC32TO64_UAP(flags); SPARC32TO64_UAP(fd); SPARC32TOX_UAP(pad, long); SPARC32TOX_UAP(pos, off_t); error = sys_mmap(p, &ua, (register_t *)&rt); if ((long)rt > (long)UINT_MAX) printf("compat_sparc32_mmap: retval out of range: 0x%qx", rt); *retval = (sparc32_voidp)(u_long)rt; return (error); } int compat_sparc32_lseek(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lseek_args /* { syscallarg(int) fd; syscallarg(int) pad; syscallarg(off_t) offset; syscallarg(int) whence; } */ *uap = v; struct sys_lseek_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(pad); SPARC32TO64_UAP(offset); SPARC32TO64_UAP(whence); return (sys_lseek(p, &ua, retval)); } int compat_sparc32_truncate(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_truncate_args /* { syscallarg(const sparc32_charp) path; syscallarg(int) pad; syscallarg(off_t) length; } */ *uap = v; struct sys_truncate_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(pad); SPARC32TO64_UAP(length); return (sys_truncate(p, &ua, retval)); } int compat_sparc32_ftruncate(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_ftruncate_args /* { syscallarg(int) fd; syscallarg(int) pad; syscallarg(off_t) length; } */ *uap = v; struct sys_ftruncate_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(pad); SPARC32TO64_UAP(length); return (sys_ftruncate(p, &ua, retval)); } int compat_sparc32___sysctl(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___sysctl_args /* { syscallarg(sparc32_intp) name; syscallarg(u_int) namelen; syscallarg(sparc32_voidp) old; syscallarg(sparc32_size_tp) oldlenp; syscallarg(sparc32_voidp) new; syscallarg(sparc32_size_t) newlen; } */ *uap = v; int error, dolock = 1; sparc32_size_t savelen = 0; size_t oldlen = 0; sysctlfn *fn; int name[CTL_MAXNAME]; /* * Some of these sysctl functions do their own copyin/copyout. * We need to disable or emulate the ones that need their * arguments converted. */ if (SCARG(uap, new) != NULL && (error = suser(p->p_ucred, &p->p_acflag))) return (error); /* * all top-level sysctl names are non-terminal */ if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2) return (EINVAL); error = copyin((caddr_t)(u_long)SCARG(uap, name), &name, SCARG(uap, namelen) * sizeof(int)); if (error) return (error); switch (name[0]) { case CTL_KERN: fn = kern_sysctl; if (name[2] != KERN_VNODE) /* XXX */ dolock = 0; break; case CTL_HW: fn = hw_sysctl; break; case CTL_VM: fn = uvm_sysctl; break; case CTL_NET: fn = net_sysctl; break; case CTL_VFS: fn = vfs_sysctl; break; case CTL_MACHDEP: fn = cpu_sysctl; break; #ifdef DEBUG case CTL_DEBUG: fn = debug_sysctl; break; #endif #ifdef DDB case CTL_DDB: fn = ddb_sysctl; break; #endif default: return (EOPNOTSUPP); } if (SCARG(uap, oldlenp) && (error = copyin((caddr_t)(u_long)SCARG(uap, oldlenp), &savelen, sizeof(savelen)))) return (error); if (SCARG(uap, old) != NULL) { if (!uvm_useracc((caddr_t)(u_long)SCARG(uap, old), savelen, B_WRITE)) return (EFAULT); #if 0 /* XXXXXXXX */ while (memlock.sl_lock) { memlock.sl_want = 1; sleep((caddr_t)&memlock, PRIBIO+1); memlock.sl_locked++; } memlock.sl_lock = 1; #endif /* XXXXXXXX */ if (dolock) uvm_vslock(p, SCARG(uap, old), savelen); oldlen = savelen; } error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old), &oldlen, SCARG(uap, new), SCARG(uap, newlen), p); if (SCARG(uap, old) != NULL) { if (dolock) uvm_vsunlock(p, SCARG(uap, old), savelen); #if 0 /* XXXXXXXXXXX */ memlock.sl_lock = 0; if (memlock.sl_want) { memlock.sl_want = 0; wakeup((caddr_t)&memlock); } #endif /* XXXXXXXXX */ } savelen = oldlen; if (error) return (error); if (SCARG(uap, oldlenp)) error = copyout(&savelen, (caddr_t)(u_long)SCARG(uap, oldlenp), sizeof(savelen)); return (error); } int compat_sparc32_mlock(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_mlock_args /* { syscallarg(const sparc32_voidp) addr; syscallarg(sparc32_size_t) len; } */ *uap = v; struct sys_mlock_args ua; SPARC32TOP_UAP(addr, const void); SPARC32TO64_UAP(len); return (sys_mlock(p, &ua, retval)); } int compat_sparc32_munlock(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_munlock_args /* { syscallarg(const sparc32_voidp) addr; syscallarg(sparc32_size_t) len; } */ *uap = v; struct sys_munlock_args ua; SPARC32TOP_UAP(addr, const void); SPARC32TO64_UAP(len); return (sys_munlock(p, &ua, retval)); } int compat_sparc32_undelete(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_undelete_args /* { syscallarg(const sparc32_charp) path; } */ *uap = v; struct sys_undelete_args ua; SPARC32TOP_UAP(path, const char); return (sys_undelete(p, &ua, retval)); } int compat_sparc32_futimes(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_futimes_args /* { syscallarg(int) fd; syscallarg(const sparc32_timevalp_t) tptr; } */ *uap = v; int error; struct file *fp; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); return (change_utimes32((struct vnode *)fp->f_data, (struct timeval *)(u_long)SCARG(uap, tptr), p)); } int compat_sparc32_getpgid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getpgid_args /* { syscallarg(pid_t) pid; } */ *uap = v; struct sys_getpgid_args ua; SPARC32TO64_UAP(pid); return (sys_getpgid(p, &ua, retval)); } int compat_sparc32_reboot(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_reboot_args /* { syscallarg(int) opt; syscallarg(sparc32_charp) bootstr; } */ *uap = v; struct sys_reboot_args ua; SPARC32TO64_UAP(opt); SPARC32TOP_UAP(bootstr, char); return (sys_reboot(p, &ua, retval)); } int compat_sparc32_poll(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_poll_args /* { syscallarg(sparc32_pollfdp_t) fds; syscallarg(u_int) nfds; syscallarg(int) timeout; } */ *uap = v; struct sys_poll_args ua; SPARC32TOP_UAP(fds, struct pollfd); SPARC32TO64_UAP(nfds); SPARC32TO64_UAP(timeout); return (sys_poll(p, &ua, retval)); } /* * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * * This is BSD. We won't support System V IPC. * Too much work. * * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ int compat_sparc32___semctl(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32___semctl_args /* { syscallarg(int) semid; syscallarg(int) semnum; syscallarg(int) cmd; syscallarg(sparc32_semunu_t) arg; } */ *uap = v; union sparc32_semun sem32; int semid = SCARG(uap, semid); int semnum = SCARG(uap, semnum); int cmd = SCARG(uap, cmd); union sparc32_semun *arg = (void*)(u_long)SCARG(uap, arg); union sparc32_semun real_arg; struct ucred *cred = p->p_ucred; int i, rval, eval; struct sparc32_semid_ds sbuf; register struct semid_ds *semaptr; semlock(p); semid = IPCID_TO_IX(semid); if (semid < 0 || semid >= seminfo.semmsl) return(EINVAL); semaptr = &sema[semid]; if ((semaptr->sem_perm.mode & SEM_ALLOC) == 0 || semaptr->sem_perm.seq != IPCID_TO_SEQ(SCARG(uap, semid))) return(EINVAL); eval = 0; rval = 0; switch (cmd) { case IPC_RMID: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M)) != 0) return(eval); semaptr->sem_perm.cuid = cred->cr_uid; semaptr->sem_perm.uid = cred->cr_uid; semtot -= semaptr->sem_nsems; for (i = semaptr->sem_base - sem; i < semtot; i++) sem[i] = sem[i + semaptr->sem_nsems]; for (i = 0; i < seminfo.semmni; i++) { if ((sema[i].sem_perm.mode & SEM_ALLOC) && sema[i].sem_base > semaptr->sem_base) sema[i].sem_base -= semaptr->sem_nsems; } semaptr->sem_perm.mode = 0; semundo_clear(semid, -1); wakeup((caddr_t)semaptr); break; case IPC_SET: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_M))) return(eval); if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) return(eval); if ((eval = copyin((caddr_t)(u_long)real_arg.buf, (caddr_t)&sbuf, sizeof(sbuf))) != 0) return(eval); semaptr->sem_perm.uid = sbuf.sem_perm.uid; semaptr->sem_perm.gid = sbuf.sem_perm.gid; semaptr->sem_perm.mode = (semaptr->sem_perm.mode & ~0777) | (sbuf.sem_perm.mode & 0777); semaptr->sem_ctime = time.tv_sec; break; case IPC_STAT: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return(eval); if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) return(eval); eval = copyout((caddr_t)semaptr, (caddr_t)(u_long)real_arg.buf, sizeof(struct semid_ds)); break; case GETNCNT: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return(eval); if (semnum < 0 || semnum >= semaptr->sem_nsems) return(EINVAL); rval = semaptr->sem_base[semnum].semncnt; break; case GETPID: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return(eval); if (semnum < 0 || semnum >= semaptr->sem_nsems) return(EINVAL); rval = semaptr->sem_base[semnum].sempid; break; case GETVAL: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return(eval); if (semnum < 0 || semnum >= semaptr->sem_nsems) return(EINVAL); rval = semaptr->sem_base[semnum].semval; break; case GETALL: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return(eval); if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) return(eval); for (i = 0; i < semaptr->sem_nsems; i++) { eval = copyout((caddr_t)&semaptr->sem_base[i].semval, &real_arg.array[i], sizeof(real_arg.array[0])); if (eval != 0) break; } break; case GETZCNT: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_R))) return(eval); if (semnum < 0 || semnum >= semaptr->sem_nsems) return(EINVAL); rval = semaptr->sem_base[semnum].semzcnt; break; case SETVAL: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W))) return(eval); if (semnum < 0 || semnum >= semaptr->sem_nsems) return(EINVAL); if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) return(eval); semaptr->sem_base[semnum].semval = real_arg.val; semundo_clear(semid, semnum); wakeup((caddr_t)semaptr); break; case SETALL: if ((eval = ipcperm(cred, &semaptr->sem_perm, IPC_W))) return(eval); if ((eval = copyin(arg, &real_arg, sizeof(real_arg))) != 0) return(eval); for (i = 0; i < semaptr->sem_nsems; i++) { eval = copyin(&real_arg.array[i], (caddr_t)&semaptr->sem_base[i].semval, sizeof(real_arg.array[0])); if (eval != 0) break; } semundo_clear(semid, -1); wakeup((caddr_t)semaptr); break; default: return(EINVAL); } if (eval == 0) *retval = rval; return(eval); #else return (ENOSYS); #endif } int compat_sparc32_semget(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_semget_args /* { syscallarg(sparc32_key_t) key; syscallarg(int) nsems; syscallarg(int) semflg; } */ *uap = v; struct sys_semget_args ua; SPARC32TOX_UAP(key, key_t); SPARC32TO64_UAP(nsems); SPARC32TO64_UAP(semflg); return (sys_semget(p, &ua, retval)); } int compat_sparc32_semop(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_semop_args /* { syscallarg(int) semid; syscallarg(sparc32_sembufp_t) sops; syscallarg(sparc32_size_t) nsops; } */ *uap = v; struct sys_semop_args ua; SPARC32TO64_UAP(semid); SPARC32TOP_UAP(sops, struct sembuf); SPARC32TOX_UAP(nsops, size_t); return (sys_semop(p, &ua, retval)); } int compat_sparc32_semconfig(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_semconfig_args /* { syscallarg(int) flag; } */ *uap = v; struct sys_semconfig_args ua; SPARC32TO64_UAP(flag); return (sys_semconfig(p, &ua, retval)); } int compat_sparc32_msgctl(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_msgctl_args /* { syscallarg(int) msqid; syscallarg(int) cmd; syscallarg(sparc32_msqid_dsp_t) buf; } */ *uap = v; struct sys_msgctl_args ua; struct msqid_ds ds; struct sparc32_msqid_ds *ds32p; int error; SPARC32TO64_UAP(msqid); SPARC32TO64_UAP(cmd); ds32p = (struct sparc32_msqid_ds *)(u_long)SCARG(uap, buf); if (ds32p) { SCARG(&ua, buf) = NULL; sparc32_to_msqid_ds(ds32p, &ds); } else SCARG(&ua, buf) = NULL; error = sys_msgctl(p, &ua, retval); if (error) return (error); if (ds32p) sparc32_from_msqid_ds(&ds, ds32p); return (0); #else return (ENOSYS); #endif } int compat_sparc32_msgget(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_msgget_args /* { syscallarg(sparc32_key_t) key; syscallarg(int) msgflg; } */ *uap = v; struct sys_msgget_args ua; SPARC32TOX_UAP(key, key_t); SPARC32TO64_UAP(msgflg); return (sys_msgget(p, &ua, retval)); #else return (ENOSYS); #endif } int compat_sparc32_msgsnd(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_msgsnd_args /* { syscallarg(int) msqid; syscallarg(const sparc32_voidp) msgp; syscallarg(sparc32_size_t) msgsz; syscallarg(int) msgflg; } */ *uap = v; struct sys_msgsnd_args ua; SPARC32TO64_UAP(msqid); SPARC32TOP_UAP(msgp, void); SPARC32TOX_UAP(msgsz, size_t); SPARC32TO64_UAP(msgflg); return (sys_msgsnd(p, &ua, retval)); #else return (ENOSYS); #endif } int compat_sparc32_msgrcv(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_msgrcv_args /* { syscallarg(int) msqid; syscallarg(sparc32_voidp) msgp; syscallarg(sparc32_size_t) msgsz; syscallarg(sparc32_long) msgtyp; syscallarg(int) msgflg; } */ *uap = v; struct sys_msgrcv_args ua; ssize_t rt; int error; SPARC32TO64_UAP(msqid); SPARC32TOP_UAP(msgp, void); SPARC32TOX_UAP(msgsz, size_t); SPARC32TOX_UAP(msgtyp, long); SPARC32TO64_UAP(msgflg); error = sys_msgrcv(p, &ua, (register_t *)&rt); *(sparc32_ssize_t *)retval = rt; return (error); #else return (ENOSYS); #endif } int compat_sparc32_shmat(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_shmat_args /* { syscallarg(int) shmid; syscallarg(const sparc32_voidp) shmaddr; syscallarg(int) shmflg; } */ *uap = v; struct sys_shmat_args ua; void *rt; int error; SPARC32TO64_UAP(shmid); SPARC32TOP_UAP(shmaddr, void); SPARC32TO64_UAP(shmflg); error = sys_shmat(p, &ua, (register_t *)&rt); *retval = (sparc32_voidp)(u_long)rt; return (error); #else return (ENOSYS); #endif } int compat_sparc32_shmctl(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_shmctl_args /* { syscallarg(int) shmid; syscallarg(int) cmd; syscallarg(sparc32_shmid_dsp_t) buf; } */ *uap = v; struct sys_shmctl_args ua; struct shmid_ds ds; struct sparc32_shmid_ds *ds32p; int error; SPARC32TO64_UAP(shmid); SPARC32TO64_UAP(cmd); ds32p = (struct sparc32_shmid_ds *)(u_long)SCARG(uap, buf); if (ds32p) { SCARG(&ua, buf) = NULL; sparc32_to_shmid_ds(ds32p, &ds); } else SCARG(&ua, buf) = NULL; error = sys_shmctl(p, &ua, retval); if (error) return (error); if (ds32p) sparc32_from_shmid_ds(&ds, ds32p); return (0); #else return (ENOSYS); #endif } int compat_sparc32_shmdt(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_shmdt_args /* { syscallarg(const sparc32_voidp) shmaddr; } */ *uap = v; struct sys_shmdt_args ua; SPARC32TOP_UAP(shmaddr, const char); return (sys_shmdt(p, &ua, retval)); #else return (ENOSYS); #endif } int compat_sparc32_shmget(p, v, retval) struct proc *p; void *v; register_t *retval; { #if 0 struct compat_sparc32_shmget_args /* { syscallarg(sparc32_key_t) key; syscallarg(sparc32_size_t) size; syscallarg(int) shmflg; } */ *uap = v; struct sys_shmget_args ua; SPARC32TOX_UAP(key, key_t) SPARC32TOX_UAP(size, size_t) SPARC32TO64_UAP(shmflg); return (sys_shmget(p, &ua, retval)); #else return (ENOSYS); #endif } int compat_sparc32_clock_gettime(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_clock_gettime_args /* { syscallarg(sparc32_clockid_t) clock_id; syscallarg(sparc32_timespecp_t) tp; } */ *uap = v; clockid_t clock_id; struct timeval atv; struct timespec ats; struct sparc32_timespec ts32; clock_id = SCARG(uap, clock_id); if (clock_id != CLOCK_REALTIME) return (EINVAL); microtime(&atv); TIMEVAL_TO_TIMESPEC(&atv,&ats); sparc32_from_timespec(&ats, &ts32); return copyout(&ts32, (caddr_t)(u_long)SCARG(uap, tp), sizeof(ts32)); } int compat_sparc32_clock_settime(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_clock_settime_args /* { syscallarg(sparc32_clockid_t) clock_id; syscallarg(const sparc32_timespecp_t) tp; } */ *uap = v; struct sparc32_timespec ts32; clockid_t clock_id; struct timeval atv; struct timespec ats; int error; if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); clock_id = SCARG(uap, clock_id); if (clock_id != CLOCK_REALTIME) return (EINVAL); if ((error = copyin((caddr_t)(u_long)SCARG(uap, tp), &ts32, sizeof(ts32))) != 0) return (error); sparc32_to_timespec(&ts32, &ats); TIMESPEC_TO_TIMEVAL(&atv,&ats); if ((error = settime(&atv))) return (error); return 0; } int compat_sparc32_clock_getres(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_clock_getres_args /* { syscallarg(sparc32_clockid_t) clock_id; syscallarg(sparc32_timespecp_t) tp; } */ *uap = v; struct sparc32_timespec ts32; clockid_t clock_id; struct timespec ts; int error = 0; clock_id = SCARG(uap, clock_id); if (clock_id != CLOCK_REALTIME) return (EINVAL); if (SCARG(uap, tp)) { ts.tv_sec = 0; ts.tv_nsec = 1000000000 / hz; sparc32_from_timespec(&ts, &ts32); error = copyout(&ts, (caddr_t)(u_long)SCARG(uap, tp), sizeof(ts)); } return error; } int compat_sparc32_nanosleep(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_nanosleep_args /* { syscallarg(const sparc32_timespecp_t) rqtp; syscallarg(sparc32_timespecp_t) rmtp; } */ *uap = v; static int nanowait; struct sparc32_timespec ts32; struct timespec rqt; struct timespec rmt; struct timeval atv, utv; int error, s, timo; error = copyin((caddr_t)(u_long)SCARG(uap, rqtp), (caddr_t)&ts32, sizeof(ts32)); if (error) return (error); sparc32_to_timespec(&ts32, &rqt); TIMESPEC_TO_TIMEVAL(&atv,&rqt) if (itimerfix(&atv)) return (EINVAL); s = splclock(); timeradd(&atv,&time,&atv); timo = hzto(&atv); /* * Avoid inadvertantly sleeping forever */ if (timo == 0) timo = 1; splx(s); error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo); if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; if (SCARG(uap, rmtp)) { int error; s = splclock(); utv = time; splx(s); timersub(&atv, &utv, &utv); if (utv.tv_sec < 0) timerclear(&utv); TIMEVAL_TO_TIMESPEC(&utv,&rmt); sparc32_from_timespec(&rmt, &ts32); error = copyout((caddr_t)&ts32, (caddr_t)(u_long)SCARG(uap,rmtp), sizeof(ts32)); if (error) return (error); } return error; } int compat_sparc32_fdatasync(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fdatasync_args /* { syscallarg(int) fd; } */ *uap = v; struct sys_fdatasync_args ua; SPARC32TO64_UAP(fd); return (sys_fdatasync(p, &ua, retval)); } int compat_sparc32___posix_rename(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___posix_rename_args /* { syscallarg(const sparc32_charp) from; syscallarg(const sparc32_charp) to; } */ *uap = v; struct sys___posix_rename_args ua; SPARC32TOP_UAP(from, const char *); SPARC32TOP_UAP(to, const char *); return (sys___posix_rename(p, &ua, retval)); } int compat_sparc32_swapctl(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_swapctl_args /* { syscallarg(int) cmd; syscallarg(const sparc32_voidp) arg; syscallarg(int) misc; } */ *uap = v; struct sys_swapctl_args ua; SPARC32TO64_UAP(cmd); SPARC32TOP_UAP(arg, const void); SPARC32TO64_UAP(misc); return (sys_swapctl(p, &ua, retval)); } int compat_sparc32_getdents(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getdents_args /* { syscallarg(int) fd; syscallarg(sparc32_charp) buf; syscallarg(sparc32_size_t) count; } */ *uap = v; struct file *fp; int error, done; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); if ((fp->f_flag & FREAD) == 0) return (EBADF); error = vn_readdir(fp, (caddr_t)(u_long)SCARG(uap, buf), UIO_USERSPACE, SCARG(uap, count), &done, p, 0, 0); *retval = done; return (error); } int compat_sparc32_minherit(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_minherit_args /* { syscallarg(sparc32_voidp) addr; syscallarg(sparc32_size_t) len; syscallarg(int) inherit; } */ *uap = v; struct sys_minherit_args ua; SPARC32TOP_UAP(addr, void); SPARC32TOX_UAP(len, size_t); SPARC32TO64_UAP(inherit); return (sys_minherit(p, &ua, retval)); } int compat_sparc32_lchmod(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lchmod_args /* { syscallarg(const sparc32_charp) path; syscallarg(mode_t) mode; } */ *uap = v; struct sys_lchmod_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(mode); return (sys_lchmod(p, &ua, retval)); } int compat_sparc32_lchown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lchown_args /* { syscallarg(const sparc32_charp) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct sys_lchown_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(uid); SPARC32TO64_UAP(gid); return (sys_lchown(p, &ua, retval)); } int compat_sparc32_lutimes(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_lutimes_args /* { syscallarg(const sparc32_charp) path; syscallarg(const sparc32_timevalp_t) tptr; } */ *uap = v; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, (caddr_t)(u_long)SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = change_utimes32(nd.ni_vp, (struct timeval *)(u_long)SCARG(uap, tptr), p); vrele(nd.ni_vp); return (error); } int compat_sparc32___msync13(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___msync13_args /* { syscallarg(sparc32_voidp) addr; syscallarg(sparc32_size_t) len; syscallarg(int) flags; } */ *uap = v; struct sys___msync13_args ua; SPARC32TOP_UAP(addr, void); SPARC32TOX_UAP(len, size_t); SPARC32TO64_UAP(flags); return (sys___msync13(p, &ua, retval)); } int compat_sparc32___stat13(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___stat13_args /* { syscallarg(const sparc32_charp) path; syscallarg(sparc32_statp_t) ub; } */ *uap = v; struct sparc32_stat sb32; struct stat sb; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, (caddr_t)(u_long)SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); sparc32_from___stat13(&sb, &sb32); error = copyout(&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof(sb32)); return (error); } int compat_sparc32___fstat13(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___fstat13_args /* { syscallarg(int) fd; syscallarg(sparc32_statp_t) sb; } */ *uap = v; int fd = SCARG(uap, fd); register struct filedesc *fdp = p->p_fd; register struct file *fp; struct sparc32_stat sb32; struct stat ub; int error = 0; 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("fstat"); /*NOTREACHED*/ } if (error == 0) { sparc32_from___stat13(&ub, &sb32); error = copyout(&sb32, (caddr_t)(u_long)SCARG(uap, sb), sizeof(sb32)); } return (error); } int compat_sparc32___lstat13(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___lstat13_args /* { syscallarg(const sparc32_charp) path; syscallarg(sparc32_statp_t) ub; } */ *uap = v; struct sparc32_stat sb32; struct stat sb; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, (caddr_t)(u_long)SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); sparc32_from___stat13(&sb, &sb32); error = copyout(&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof(sb32)); return (error); } int compat_sparc32___sigaltstack14(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___sigaltstack14_args /* { syscallarg(const sparc32_sigaltstackp_t) nss; syscallarg(sparc32_sigaltstackp_t) oss; } */ *uap = v; struct sparc32_sigaltstack s32; struct sigaltstack nss, oss; int error; if (SCARG(uap, nss)) { error = copyin((caddr_t)(u_long)SCARG(uap, nss), &s32, sizeof(s32)); if (error) return (error); nss.ss_sp = (void *)(u_long)s32.ss_sp; nss.ss_size = (size_t)s32.ss_size; nss.ss_flags = s32.ss_flags; } error = sigaltstack1(p, SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0); if (error) return (error); if (SCARG(uap, oss)) { s32.ss_sp = (sparc32_voidp)(u_long)oss.ss_sp; s32.ss_size = (sparc32_size_t)oss.ss_size; s32.ss_flags = oss.ss_flags; error = copyout(&s32, (caddr_t)(u_long)SCARG(uap, oss), sizeof(s32)); if (error) return (error); } return (0); } int compat_sparc32___posix_chown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___posix_chown_args /* { syscallarg(const sparc32_charp) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct sys___posix_chown_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(uid); SPARC32TO64_UAP(gid); return (sys___posix_chown(p, &ua, retval)); } int compat_sparc32___posix_fchown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___posix_fchown_args /* { syscallarg(int) fd; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct sys___posix_fchown_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(uid); SPARC32TO64_UAP(gid); return (sys___posix_fchown(p, &ua, retval)); } int compat_sparc32___posix_lchown(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32___posix_lchown_args /* { syscallarg(const sparc32_charp) path; syscallarg(uid_t) uid; syscallarg(gid_t) gid; } */ *uap = v; struct sys___posix_lchown_args ua; SPARC32TOP_UAP(path, const char); SPARC32TO64_UAP(uid); SPARC32TO64_UAP(gid); return (sys___posix_lchown(p, &ua, retval)); } int compat_sparc32_getsid(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_getsid_args /* { syscallarg(pid_t) pid; } */ *uap = v; struct sys_getsid_args ua; SPARC32TO64_UAP(pid); return (sys_getsid(p, &ua, retval)); } int compat_sparc32_fktrace(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_fktrace_args /* { syscallarg(const int) fd; syscallarg(int) ops; syscallarg(int) facs; syscallarg(int) pid; } */ *uap = v; struct sys_fktrace_args ua; SPARC32TO64_UAP(fd); SPARC32TO64_UAP(ops); SPARC32TO64_UAP(facs); SPARC32TO64_UAP(pid); return (sys_fktrace(p, &ua, retval)); } int compat_sparc32_preadv(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_preadv_args /* { syscallarg(int) fd; syscallarg(const sparc32_iovecp_t) iovp; syscallarg(int) iovcnt; syscallarg(int) pad; syscallarg(off_t) offset; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; off_t offset; int error, fd = SCARG(uap, fd); if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL || (fp->f_flag & FREAD) == 0) return (EBADF); vp = (struct vnode *)fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) return (ESPIPE); offset = SCARG(uap, offset); /* * XXX This works because no file systems actually * XXX take any action on the seek operation. */ if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) return (error); return (dofilereadv32(p, fd, fp, (struct sparc32_iovec *)(u_long)SCARG(uap, iovp), SCARG(uap, iovcnt), &offset, 0, retval)); } int compat_sparc32_pwritev(p, v, retval) struct proc *p; void *v; register_t *retval; { struct compat_sparc32_pwritev_args /* { syscallarg(int) fd; syscallarg(const sparc32_iovecp_t) iovp; syscallarg(int) iovcnt; syscallarg(int) pad; syscallarg(off_t) offset; } */ *uap = v; struct filedesc *fdp = p->p_fd; struct file *fp; struct vnode *vp; off_t offset; int error, fd = SCARG(uap, fd); if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL || (fp->f_flag & FWRITE) == 0) return (EBADF); vp = (struct vnode *)fp->f_data; if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) return (ESPIPE); offset = SCARG(uap, offset); /* * XXX This works because no file systems actually * XXX take any action on the seek operation. */ if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) return (error); return (dofilewritev32(p, fd, fp, (struct sparc32_iovec *)(u_long)SCARG(uap, iovp), SCARG(uap, iovcnt), &offset, 0, retval)); } int compat_13_compat_sparc32_sigprocmask(p, v, retval) register struct proc *p; void *v; register_t *retval; { struct compat_13_compat_sparc32_sigprocmask_args /* { syscallarg(int) how; syscallarg(int) mask; } */ *uap = v; sigset13_t ness, oess; sigset_t nbss, obss; int error; ness = SCARG(uap, mask); native_sigset13_to_sigset(&ness, &nbss); error = sigprocmask1(p, SCARG(uap, how), &nbss, &obss); if (error) return (error); native_sigset_to_sigset13(&obss, &oess); *retval = oess; return (0); } int compat_13_compat_sparc32_sigsuspend(p, v, retval) register struct proc *p; void *v; register_t *retval; { struct compat_13_compat_sparc32_sigsuspend_args /* { syscallarg(sigset13_t) mask; } */ *uap = v; sigset13_t ess; sigset_t bss; ess = SCARG(uap, mask); native_sigset13_to_sigset(&ess, &bss); return (sigsuspend1(p, &bss)); }