e3669c3393
count is 0, wait for use count to drain before finishing the close. This is necessary in order for multiple processes to safely share file descriptor tables.
5087 lines
116 KiB
C
5087 lines
116 KiB
C
/* $NetBSD: netbsd32_netbsd.c,v 1.12 1999/05/05 20:01:04 thorpej 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 <sys/socket.h> */
|
|
#endif
|
|
|
|
#include "fs_lfs.h"
|
|
#include "fs_nfs.h"
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/ipc.h>
|
|
#include <sys/msg.h>
|
|
#include <sys/sem.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/sockio.h>
|
|
#include <sys/socketvar.h>
|
|
#include <sys/mbuf.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <sys/timex.h>
|
|
#include <sys/signalvar.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/ptrace.h>
|
|
#include <sys/ktrace.h>
|
|
#include <sys/trace.h>
|
|
#include <sys/resourcevar.h>
|
|
#include <sys/pool.h>
|
|
#include <sys/vnode.h>
|
|
#include <sys/file.h>
|
|
#include <sys/filedesc.h>
|
|
#include <sys/namei.h>
|
|
|
|
#include <vm/vm.h>
|
|
#include <sys/syscallargs.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <compat/netbsd32/netbsd32.h>
|
|
#include <compat/netbsd32/netbsd32_syscallargs.h>
|
|
|
|
#include <machine/frame.h>
|
|
|
|
static __inline void netbsd32_from_timeval __P((struct timeval *, struct netbsd32_timeval *));
|
|
static __inline void netbsd32_to_timeval __P((struct netbsd32_timeval *, struct timeval *));
|
|
static __inline void netbsd32_from_itimerval __P((struct itimerval *, struct netbsd32_itimerval *));
|
|
static __inline void netbsd32_to_itimerval __P((struct netbsd32_itimerval *, struct itimerval *));
|
|
static __inline void netbsd32_to_timespec __P((struct netbsd32_timespec *, struct timespec *));
|
|
static __inline void netbsd32_from_timespec __P((struct timespec *, struct netbsd32_timespec *));
|
|
static __inline void netbsd32_from_rusage __P((struct rusage *, struct netbsd32_rusage *));
|
|
static __inline void netbsd32_to_rusage __P((struct netbsd32_rusage *, struct rusage *));
|
|
static __inline int netbsd32_to_iovecin __P((struct netbsd32_iovec *, struct iovec *, int));
|
|
static __inline void netbsd32_to_msghdr __P((struct netbsd32_msghdr *, struct msghdr *));
|
|
static __inline void netbsd32_from_msghdr __P((struct netbsd32_msghdr *, struct msghdr *));
|
|
static __inline void netbsd32_from_statfs __P((struct statfs *, struct netbsd32_statfs *));
|
|
static __inline void netbsd32_from_timex __P((struct timex *, struct netbsd32_timex *));
|
|
static __inline void netbsd32_to_timex __P((struct netbsd32_timex *, struct timex *));
|
|
static __inline void netbsd32_from___stat13 __P((struct stat *, struct netbsd32_stat *));
|
|
static __inline void netbsd32_to_ipc_perm __P((struct netbsd32_ipc_perm *, struct ipc_perm *));
|
|
static __inline void netbsd32_from_ipc_perm __P((struct ipc_perm *, struct netbsd32_ipc_perm *));
|
|
static __inline void netbsd32_to_msg __P((struct netbsd32_msg *, struct msg *));
|
|
static __inline void netbsd32_from_msg __P((struct msg *, struct netbsd32_msg *));
|
|
static __inline void netbsd32_to_msqid_ds __P((struct netbsd32_msqid_ds *, struct msqid_ds *));
|
|
static __inline void netbsd32_from_msqid_ds __P((struct msqid_ds *, struct netbsd32_msqid_ds *));
|
|
static __inline void netbsd32_to_shmid_ds __P((struct netbsd32_shmid_ds *, struct shmid_ds *));
|
|
static __inline void netbsd32_from_shmid_ds __P((struct shmid_ds *, struct netbsd32_shmid_ds *));
|
|
static __inline void netbsd32_to_semid_ds __P((struct netbsd32_semid_ds *, struct semid_ds *));
|
|
static __inline void netbsd32_from_semid_ds __P((struct semid_ds *, struct netbsd32_semid_ds *));
|
|
|
|
|
|
static int recvit32 __P((struct proc *, int, struct netbsd32_msghdr *, struct iovec *, caddr_t,
|
|
register_t *));
|
|
static int dofilereadv32 __P((struct proc *, int, struct file *, struct netbsd32_iovec *,
|
|
int, off_t *, int, register_t *));
|
|
static int dofilewritev32 __P((struct proc *, int, struct file *, struct netbsd32_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
|
|
netbsd32_from_timeval(tv, tv32)
|
|
struct timeval *tv;
|
|
struct netbsd32_timeval *tv32;
|
|
{
|
|
|
|
tv32->tv_sec = (netbsd32_long)tv->tv_sec;
|
|
tv32->tv_usec = (netbsd32_long)tv->tv_usec;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_timeval(tv32, tv)
|
|
struct netbsd32_timeval *tv32;
|
|
struct timeval *tv;
|
|
{
|
|
|
|
tv->tv_sec = (long)tv32->tv_sec;
|
|
tv->tv_usec = (long)tv32->tv_usec;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_from_itimerval(itv, itv32)
|
|
struct itimerval *itv;
|
|
struct netbsd32_itimerval *itv32;
|
|
{
|
|
|
|
netbsd32_from_timeval(&itv->it_interval,
|
|
&itv32->it_interval);
|
|
netbsd32_from_timeval(&itv->it_value,
|
|
&itv32->it_value);
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_itimerval(itv32, itv)
|
|
struct netbsd32_itimerval *itv32;
|
|
struct itimerval *itv;
|
|
{
|
|
|
|
netbsd32_to_timeval(&itv32->it_interval, &itv->it_interval);
|
|
netbsd32_to_timeval(&itv32->it_value, &itv->it_value);
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_timespec(s32p, p)
|
|
struct netbsd32_timespec *s32p;
|
|
struct timespec *p;
|
|
{
|
|
|
|
p->tv_sec = s32p->tv_sec;
|
|
p->tv_nsec = (long)s32p->tv_nsec;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_from_timespec(p, s32p)
|
|
struct timespec *p;
|
|
struct netbsd32_timespec *s32p;
|
|
{
|
|
|
|
s32p->tv_sec = p->tv_sec;
|
|
s32p->tv_nsec = (netbsd32_long)p->tv_nsec;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_from_rusage(rup, ru32p)
|
|
struct rusage *rup;
|
|
struct netbsd32_rusage *ru32p;
|
|
{
|
|
|
|
netbsd32_from_timeval(&rup->ru_utime, &ru32p->ru_utime);
|
|
netbsd32_from_timeval(&rup->ru_stime, &ru32p->ru_stime);
|
|
#define C(var) ru32p->var = (netbsd32_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
|
|
netbsd32_to_rusage(ru32p, rup)
|
|
struct netbsd32_rusage *ru32p;
|
|
struct rusage *rup;
|
|
{
|
|
|
|
netbsd32_to_timeval(&ru32p->ru_utime, &rup->ru_utime);
|
|
netbsd32_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
|
|
netbsd32_to_iovecin(iov32p, iovp, len)
|
|
struct netbsd32_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
|
|
netbsd32_to_msghdr(mhp32, mhp)
|
|
struct netbsd32_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
|
|
netbsd32_from_msghdr(mhp32, mhp)
|
|
struct netbsd32_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
|
|
netbsd32_from_statfs(sbp, sb32p)
|
|
struct statfs *sbp;
|
|
struct netbsd32_statfs *sb32p;
|
|
{
|
|
|
|
sb32p->f_type = sbp->f_type;
|
|
sb32p->f_flags = sbp->f_flags;
|
|
sb32p->f_bsize = (netbsd32_long)sbp->f_bsize;
|
|
sb32p->f_iosize = (netbsd32_long)sbp->f_iosize;
|
|
sb32p->f_blocks = (netbsd32_long)sbp->f_blocks;
|
|
sb32p->f_bfree = (netbsd32_long)sbp->f_bfree;
|
|
sb32p->f_bavail = (netbsd32_long)sbp->f_bavail;
|
|
sb32p->f_files = (netbsd32_long)sbp->f_files;
|
|
sb32p->f_ffree = (netbsd32_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
|
|
netbsd32_from_timex(txp, tx32p)
|
|
struct timex *txp;
|
|
struct netbsd32_timex *tx32p;
|
|
{
|
|
|
|
tx32p->modes = txp->modes;
|
|
tx32p->offset = (netbsd32_long)txp->offset;
|
|
tx32p->freq = (netbsd32_long)txp->freq;
|
|
tx32p->maxerror = (netbsd32_long)txp->maxerror;
|
|
tx32p->esterror = (netbsd32_long)txp->esterror;
|
|
tx32p->status = txp->status;
|
|
tx32p->constant = (netbsd32_long)txp->constant;
|
|
tx32p->precision = (netbsd32_long)txp->precision;
|
|
tx32p->tolerance = (netbsd32_long)txp->tolerance;
|
|
tx32p->ppsfreq = (netbsd32_long)txp->ppsfreq;
|
|
tx32p->jitter = (netbsd32_long)txp->jitter;
|
|
tx32p->shift = txp->shift;
|
|
tx32p->stabil = (netbsd32_long)txp->stabil;
|
|
tx32p->jitcnt = (netbsd32_long)txp->jitcnt;
|
|
tx32p->calcnt = (netbsd32_long)txp->calcnt;
|
|
tx32p->errcnt = (netbsd32_long)txp->errcnt;
|
|
tx32p->stbcnt = (netbsd32_long)txp->stbcnt;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_timex(tx32p, txp)
|
|
struct netbsd32_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
|
|
netbsd32_from___stat13(sbp, sb32p)
|
|
struct stat *sbp;
|
|
struct netbsd32_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 = (netbsd32_long)sbp->st_atimespec.tv_nsec;
|
|
sb32p->st_mtimespec.tv_sec = sbp->st_mtimespec.tv_sec;
|
|
sb32p->st_mtimespec.tv_nsec = (netbsd32_long)sbp->st_mtimespec.tv_nsec;
|
|
sb32p->st_ctimespec.tv_sec = sbp->st_ctimespec.tv_sec;
|
|
sb32p->st_ctimespec.tv_nsec = (netbsd32_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
|
|
netbsd32_to_ipc_perm(ip32p, ipp)
|
|
struct netbsd32_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
|
|
netbsd32_from_ipc_perm(ipp, ip32p)
|
|
struct ipc_perm *ipp;
|
|
struct netbsd32_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 = (netbsd32_key_t)ipp->key;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_msg(m32p, mp)
|
|
struct netbsd32_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
|
|
netbsd32_from_msg(mp, m32p)
|
|
struct msg *mp;
|
|
struct netbsd32_msg *m32p;
|
|
{
|
|
|
|
m32p->msg_next = (netbsd32_msgp_t)(u_long)mp->msg_next;
|
|
m32p->msg_type = (netbsd32_long)mp->msg_type;
|
|
m32p->msg_ts = mp->msg_ts;
|
|
m32p->msg_spot = mp->msg_spot;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_msqid_ds(ds32p, dsp)
|
|
struct netbsd32_msqid_ds *ds32p;
|
|
struct msqid_ds *dsp;
|
|
{
|
|
|
|
netbsd32_to_ipc_perm(&ds32p->msg_perm, &dsp->msg_perm);
|
|
netbsd32_to_msg((struct netbsd32_msg *)(u_long)ds32p->msg_first, dsp->msg_first);
|
|
netbsd32_to_msg((struct netbsd32_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
|
|
netbsd32_from_msqid_ds(dsp, ds32p)
|
|
struct msqid_ds *dsp;
|
|
struct netbsd32_msqid_ds *ds32p;
|
|
{
|
|
|
|
netbsd32_from_ipc_perm(&dsp->msg_perm, &ds32p->msg_perm);
|
|
netbsd32_from_msg(dsp->msg_first, (struct netbsd32_msg *)(u_long)ds32p->msg_first);
|
|
netbsd32_from_msg(dsp->msg_last, (struct netbsd32_msg *)(u_long)ds32p->msg_last);
|
|
ds32p->msg_cbytes = (netbsd32_u_long)dsp->msg_cbytes;
|
|
ds32p->msg_qnum = (netbsd32_u_long)dsp->msg_qnum;
|
|
ds32p->msg_qbytes = (netbsd32_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
|
|
netbsd32_to_shmid_ds(ds32p, dsp)
|
|
struct netbsd32_shmid_ds *ds32p;
|
|
struct shmid_ds *dsp;
|
|
{
|
|
|
|
netbsd32_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
|
|
netbsd32_from_shmid_ds(dsp, ds32p)
|
|
struct shmid_ds *dsp;
|
|
struct netbsd32_shmid_ds *ds32p;
|
|
{
|
|
|
|
netbsd32_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 = (netbsd32_long)dsp->shm_atime;
|
|
ds32p->shm_dtime = (netbsd32_long)dsp->shm_dtime;
|
|
ds32p->shm_ctime = (netbsd32_long)dsp->shm_ctime;
|
|
ds32p->shm_internal = (netbsd32_voidp)(u_long)dsp->shm_internal;
|
|
}
|
|
|
|
static __inline void
|
|
netbsd32_to_semid_ds(s32dsp, dsp)
|
|
struct netbsd32_semid_ds *s32dsp;
|
|
struct semid_ds *dsp;
|
|
{
|
|
|
|
netbsd32_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
|
|
netbsd32_from_semid_ds(dsp, s32dsp)
|
|
struct semid_ds *dsp;
|
|
struct netbsd32_semid_ds *s32dsp;
|
|
{
|
|
|
|
netbsd32_to_ipc_perm(&s32dsp->sem_perm, &dsp->sem_perm);
|
|
s32dsp->sem_base = (netbsd32_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_netbsd32_exit(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_exit_args /* {
|
|
syscallarg(int) rval;
|
|
} */ *uap = v;
|
|
struct sys_exit_args ua;
|
|
|
|
NETBSD32TO64_UAP(rval);
|
|
sys_exit(p, &ua, retval);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_read(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_read_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_voidp) buf;
|
|
syscallarg(netbsd32_size_t) nbyte;
|
|
} */ *uap = v;
|
|
struct sys_read_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TOP_UAP(buf, void *);
|
|
NETBSD32TOX_UAP(nbyte, size_t);
|
|
return sys_read(p, &ua, retval);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_write(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_write_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_voidp) buf;
|
|
syscallarg(netbsd32_size_t) nbyte;
|
|
} */ *uap = v;
|
|
struct sys_write_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TOP_UAP(buf, void *);
|
|
NETBSD32TOX_UAP(nbyte, size_t);
|
|
return sys_write(p, &ua, retval);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_close(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_close_args /* {
|
|
syscallarg(int) fd;
|
|
} */ *uap = v;
|
|
struct sys_close_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
return sys_write(p, &ua, retval);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_open(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_open_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(int) flags;
|
|
syscallarg(mode_t) mode;
|
|
} */ *uap = v;
|
|
struct sys_open_args ua;
|
|
caddr_t sg;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(flags);
|
|
NETBSD32TO64_UAP(mode);
|
|
sg = stackgap_init(p->p_emul);
|
|
NETBSD32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
|
|
|
|
return (sys_open(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_wait4(q, v, retval)
|
|
struct proc *q;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_wait4_args /* {
|
|
syscallarg(int) pid;
|
|
syscallarg(netbsd32_intp) status;
|
|
syscallarg(int) options;
|
|
syscallarg(netbsd32_rusagep_t) rusage;
|
|
} */ *uap = v;
|
|
struct netbsd32_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)) {
|
|
netbsd32_from_rusage(p->p_ru, &ru32);
|
|
if ((error = copyout((caddr_t)&ru32,
|
|
(caddr_t)(u_long)SCARG(uap, rusage),
|
|
sizeof(struct netbsd32_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_netbsd32_link(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_link_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(const netbsd32_charp) link;
|
|
} */ *uap = v;
|
|
struct sys_link_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TOP_UAP(link, const char);
|
|
return (sys_link(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_unlink(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_unlink_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_unlink_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
|
|
return (sys_unlink(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_chdir(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_chdir_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_chdir_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
|
|
return (sys_chdir(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fchdir(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fchdir_args /* {
|
|
syscallarg(int) fd;
|
|
} */ *uap = v;
|
|
struct sys_fchdir_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
|
|
return (sys_fchdir(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_mknod(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mknod_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(mode_t) mode;
|
|
syscallarg(dev_t) dev;
|
|
} */ *uap = v;
|
|
struct sys_mknod_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(dev);
|
|
NETBSD32TO64_UAP(mode);
|
|
|
|
return (sys_mknod(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_chmod(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_chmod_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(mode_t) mode;
|
|
} */ *uap = v;
|
|
struct sys_chmod_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(mode);
|
|
|
|
return (sys_chmod(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_chown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_chown_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(uid_t) uid;
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys_chown_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TO64_UAP(gid);
|
|
|
|
return (sys_chown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_break(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_break_args /* {
|
|
syscallarg(netbsd32_charp) nsize;
|
|
} */ *uap = v;
|
|
struct sys_obreak_args ua;
|
|
|
|
SCARG(&ua, nsize) = (char *)(u_long)SCARG(uap, nsize);
|
|
NETBSD32TOP_UAP(nsize, char);
|
|
return (sys_obreak(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getfsstat(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getfsstat_args /* {
|
|
syscallarg(netbsd32_statfsp_t) buf;
|
|
syscallarg(netbsd32_long) bufsize;
|
|
syscallarg(int) flags;
|
|
} */ *uap = v;
|
|
struct sys_getfsstat_args ua;
|
|
struct statfs sb;
|
|
struct netbsd32_statfs *sb32p;
|
|
int error;
|
|
|
|
sb32p = (struct netbsd32_statfs *)(u_long)SCARG(uap, buf);
|
|
if (sb32p)
|
|
SCARG(&ua, buf) = &sb;
|
|
else
|
|
SCARG(&ua, buf) = NULL;
|
|
NETBSD32TOX_UAP(bufsize, long);
|
|
NETBSD32TO64_UAP(flags);
|
|
error = sys_getfsstat(p, &ua, retval);
|
|
if (error)
|
|
return (error);
|
|
|
|
if (sb32p) {
|
|
struct netbsd32_statfs sb32;
|
|
netbsd32_from_statfs(&sb, &sb32);
|
|
if (copyout(&sb32, sb32p, sizeof(sb32)))
|
|
return EFAULT;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_mount(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mount_args /* {
|
|
syscallarg(const netbsd32_charp) type;
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(int) flags;
|
|
syscallarg(netbsd32_voidp) data;
|
|
} */ *uap = v;
|
|
struct sys_mount_args ua;
|
|
|
|
NETBSD32TOP_UAP(type, const char);
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(flags);
|
|
NETBSD32TOP_UAP(data, void);
|
|
return (sys_mount(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_unmount(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_unmount_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(int) flags;
|
|
} */ *uap = v;
|
|
struct sys_unmount_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(flags);
|
|
return (sys_unmount(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setuid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setuid_args /* {
|
|
syscallarg(uid_t) uid;
|
|
} */ *uap = v;
|
|
struct sys_setuid_args ua;
|
|
|
|
NETBSD32TO64_UAP(uid);
|
|
return (sys_setuid(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_ptrace(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_ptrace_args /* {
|
|
syscallarg(int) req;
|
|
syscallarg(pid_t) pid;
|
|
syscallarg(netbsd32_caddr_t) addr;
|
|
syscallarg(int) data;
|
|
} */ *uap = v;
|
|
struct sys_ptrace_args ua;
|
|
|
|
NETBSD32TO64_UAP(req);
|
|
NETBSD32TO64_UAP(pid);
|
|
NETBSD32TOX64_UAP(addr, caddr_t);
|
|
NETBSD32TO64_UAP(data);
|
|
return (sys_ptrace(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_recvmsg(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_recvmsg_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(netbsd32_msghdrp_t) msg;
|
|
syscallarg(int) flags;
|
|
} */ *uap = v;
|
|
struct netbsd32_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));
|
|
/* netbsd32_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 = netbsd32_to_iovecin((struct netbsd32_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 netbsd32_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
|
|
|
|
/* getsock() will use the descriptor for us */
|
|
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) {
|
|
error = EINVAL;
|
|
goto out1;
|
|
}
|
|
#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) {
|
|
error = EINVAL;
|
|
goto out1;
|
|
}
|
|
}
|
|
#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);
|
|
out1:
|
|
FILE_UNUSE(fp);
|
|
return (error);
|
|
}
|
|
|
|
|
|
int
|
|
compat_netbsd32_sendmsg(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_sendmsg_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(const netbsd32_msghdrp_t) msg;
|
|
syscallarg(int) flags;
|
|
} */ *uap = v;
|
|
struct msghdr msg;
|
|
struct netbsd32_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);
|
|
netbsd32_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 = netbsd32_to_iovecin((struct netbsd32_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_netbsd32_recvfrom(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_recvfrom_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(netbsd32_voidp) buf;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) flags;
|
|
syscallarg(netbsd32_sockaddrp_t) from;
|
|
syscallarg(netbsd32_intp) fromlenaddr;
|
|
} */ *uap = v;
|
|
struct netbsd32_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_netbsd32_sendto(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_sendto_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(const netbsd32_voidp) buf;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) flags;
|
|
syscallarg(const netbsd32_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_netbsd32_accept(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_accept_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(netbsd32_sockaddrp_t) name;
|
|
syscallarg(netbsd32_intp) anamelen;
|
|
} */ *uap = v;
|
|
struct sys_accept_args ua;
|
|
|
|
NETBSD32TO64_UAP(s);
|
|
NETBSD32TOP_UAP(name, struct sockaddr);
|
|
NETBSD32TOP_UAP(anamelen, int);
|
|
return (sys_accept(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getpeername(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getpeername_args /* {
|
|
syscallarg(int) fdes;
|
|
syscallarg(netbsd32_sockaddrp_t) asa;
|
|
syscallarg(netbsd32_intp) alen;
|
|
} */ *uap = v;
|
|
struct sys_getpeername_args ua;
|
|
|
|
NETBSD32TO64_UAP(fdes);
|
|
NETBSD32TOP_UAP(asa, struct sockaddr);
|
|
NETBSD32TOP_UAP(alen, int);
|
|
/* NB: do the protocol specific sockaddrs need to be converted? */
|
|
return (sys_getpeername(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getsockname(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getsockname_args /* {
|
|
syscallarg(int) fdes;
|
|
syscallarg(netbsd32_sockaddrp_t) asa;
|
|
syscallarg(netbsd32_intp) alen;
|
|
} */ *uap = v;
|
|
struct sys_getsockname_args ua;
|
|
|
|
NETBSD32TO64_UAP(fdes);
|
|
NETBSD32TOP_UAP(asa, struct sockaddr);
|
|
NETBSD32TOP_UAP(alen, int);
|
|
return (sys_getsockname(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_access(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_access_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(int) flags;
|
|
} */ *uap = v;
|
|
struct sys_access_args ua;
|
|
caddr_t sg;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(flags);
|
|
sg = stackgap_init(p->p_emul);
|
|
NETBSD32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
|
|
|
|
return (sys_access(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_chflags(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_chflags_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(netbsd32_u_long) flags;
|
|
} */ *uap = v;
|
|
struct sys_chflags_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(flags);
|
|
|
|
return (sys_chflags(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fchflags(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fchflags_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_u_long) flags;
|
|
} */ *uap = v;
|
|
struct sys_fchflags_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(flags);
|
|
|
|
return (sys_fchflags(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_kill(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_kill_args /* {
|
|
syscallarg(int) pid;
|
|
syscallarg(int) signum;
|
|
} */ *uap = v;
|
|
struct sys_kill_args ua;
|
|
|
|
NETBSD32TO64_UAP(pid);
|
|
NETBSD32TO64_UAP(signum);
|
|
|
|
return (sys_kill(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_dup(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_dup_args /* {
|
|
syscallarg(int) fd;
|
|
} */ *uap = v;
|
|
struct sys_dup_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
|
|
return (sys_dup(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_profil(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_profil_args /* {
|
|
syscallarg(netbsd32_caddr_t) samples;
|
|
syscallarg(netbsd32_size_t) size;
|
|
syscallarg(netbsd32_u_long) offset;
|
|
syscallarg(u_int) scale;
|
|
} */ *uap = v;
|
|
struct sys_profil_args ua;
|
|
|
|
NETBSD32TOX64_UAP(samples, caddr_t);
|
|
NETBSD32TOX_UAP(size, size_t);
|
|
NETBSD32TOX_UAP(offset, u_long);
|
|
NETBSD32TO64_UAP(scale);
|
|
return (sys_profil(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_ktrace(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_ktrace_args /* {
|
|
syscallarg(const netbsd32_charp) fname;
|
|
syscallarg(int) ops;
|
|
syscallarg(int) facs;
|
|
syscallarg(int) pid;
|
|
} */ *uap = v;
|
|
struct sys_ktrace_args ua;
|
|
|
|
NETBSD32TOP_UAP(fname, const char);
|
|
NETBSD32TO64_UAP(ops);
|
|
NETBSD32TO64_UAP(facs);
|
|
NETBSD32TO64_UAP(pid);
|
|
return (sys_ktrace(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_sigaction(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_sigaction_args /* {
|
|
syscallarg(int) signum;
|
|
syscallarg(const netbsd32_sigactionp_t) nsa;
|
|
syscallarg(netbsd32_sigactionp_t) osa;
|
|
} */ *uap = v;
|
|
struct sigaction nsa, osa;
|
|
struct netbsd32_sigaction *sa32p, sa32;
|
|
int error;
|
|
|
|
if (SCARG(uap, nsa)) {
|
|
sa32p = (struct netbsd32_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 = (netbsd32_sigactionp_t)(u_long)osa.sa_handler;
|
|
sa32.sa_mask = osa.sa_mask;
|
|
sa32.sa_flags = osa.sa_flags;
|
|
sa32p = (struct netbsd32_sigaction *)(u_long)SCARG(uap, osa);
|
|
if (copyout(&sa32, sa32p, sizeof(sa32)))
|
|
return EFAULT;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___getlogin(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___getlogin_args /* {
|
|
syscallarg(netbsd32_charp) namebuf;
|
|
syscallarg(u_int) namelen;
|
|
} */ *uap = v;
|
|
struct sys___getlogin_args ua;
|
|
|
|
NETBSD32TOP_UAP(namebuf, char);
|
|
NETBSD32TO64_UAP(namelen);
|
|
return (sys___getlogin(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setlogin(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setlogin_args /* {
|
|
syscallarg(const netbsd32_charp) namebuf;
|
|
} */ *uap = v;
|
|
struct sys_setlogin_args ua;
|
|
|
|
NETBSD32TOP_UAP(namebuf, char);
|
|
return (sys_setlogin(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_acct(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_acct_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_acct_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
return (sys_acct(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_revoke(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_revoke_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_revoke_args ua;
|
|
caddr_t sg;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
sg = stackgap_init(p->p_emul);
|
|
NETBSD32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
|
|
|
|
return (sys_revoke(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_symlink(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_symlink_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(const netbsd32_charp) link;
|
|
} */ *uap = v;
|
|
struct sys_symlink_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TOP_UAP(link, const char);
|
|
|
|
return (sys_symlink(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_readlink(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_readlink_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(netbsd32_charp) buf;
|
|
syscallarg(netbsd32_size_t) count;
|
|
} */ *uap = v;
|
|
struct sys_readlink_args ua;
|
|
caddr_t sg;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TOP_UAP(buf, char);
|
|
NETBSD32TOX_UAP(count, size_t);
|
|
sg = stackgap_init(p->p_emul);
|
|
NETBSD32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
|
|
|
|
return (sys_readlink(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_execve(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_execve_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(netbsd32_charpp) argp;
|
|
syscallarg(netbsd32_charpp) envp;
|
|
} */ *uap = v;
|
|
struct sys_execve_args ua;
|
|
caddr_t sg;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TOP_UAP(argp, char *);
|
|
NETBSD32TOP_UAP(envp, char *);
|
|
sg = stackgap_init(p->p_emul);
|
|
NETBSD32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
|
|
|
|
return (sys_execve(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_umask(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_umask_args /* {
|
|
syscallarg(mode_t) newmask;
|
|
} */ *uap = v;
|
|
struct sys_umask_args ua;
|
|
|
|
NETBSD32TO64_UAP(newmask);
|
|
return (sys_umask(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_chroot(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_chroot_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_chroot_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
return (sys_chroot(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_sbrk(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_sbrk_args /* {
|
|
syscallarg(int) incr;
|
|
} */ *uap = v;
|
|
struct sys_sbrk_args ua;
|
|
|
|
NETBSD32TO64_UAP(incr);
|
|
return (sys_sbrk(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_sstk(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_sstk_args /* {
|
|
syscallarg(int) incr;
|
|
} */ *uap = v;
|
|
struct sys_sstk_args ua;
|
|
|
|
NETBSD32TO64_UAP(incr);
|
|
return (sys_sstk(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_munmap(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_munmap_args /* {
|
|
syscallarg(netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
} */ *uap = v;
|
|
struct sys_munmap_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, void);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
return (sys_munmap(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_mprotect(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mprotect_args /* {
|
|
syscallarg(netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) prot;
|
|
} */ *uap = v;
|
|
struct sys_mprotect_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, void);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
NETBSD32TO64_UAP(prot);
|
|
return (sys_mprotect(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_madvise(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_madvise_args /* {
|
|
syscallarg(netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) behav;
|
|
} */ *uap = v;
|
|
struct sys_madvise_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, void);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
NETBSD32TO64_UAP(behav);
|
|
return (sys_madvise(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_mincore(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mincore_args /* {
|
|
syscallarg(netbsd32_caddr_t) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(netbsd32_charp) vec;
|
|
} */ *uap = v;
|
|
struct sys_mincore_args ua;
|
|
|
|
NETBSD32TOX64_UAP(addr, caddr_t);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
NETBSD32TOP_UAP(vec, char);
|
|
return (sys_mincore(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getgroups(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getgroups_args /* {
|
|
syscallarg(int) gidsetsize;
|
|
syscallarg(netbsd32_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 netbsd32_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_netbsd32_setgroups(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setgroups_args /* {
|
|
syscallarg(int) gidsetsize;
|
|
syscallarg(const netbsd32_gid_tp) gidset;
|
|
} */ *uap = v;
|
|
struct sys_setgroups_args ua;
|
|
|
|
NETBSD32TO64_UAP(gidsetsize);
|
|
NETBSD32TOP_UAP(gidset, gid_t);
|
|
return (sys_setgroups(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setpgid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setpgid_args /* {
|
|
syscallarg(int) pid;
|
|
syscallarg(int) pgid;
|
|
} */ *uap = v;
|
|
struct sys_setpgid_args ua;
|
|
|
|
NETBSD32TO64_UAP(pid);
|
|
NETBSD32TO64_UAP(pgid);
|
|
return (sys_setpgid(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setitimer(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setitimer_args /* {
|
|
syscallarg(int) which;
|
|
syscallarg(const netbsd32_itimervalp_t) itv;
|
|
syscallarg(netbsd32_itimervalp_t) oitv;
|
|
} */ *uap = v;
|
|
struct netbsd32_itimerval s32it, *itvp;
|
|
int which = SCARG(uap, which);
|
|
struct compat_netbsd32_getitimer_args getargs;
|
|
struct itimerval aitv;
|
|
int s, error;
|
|
|
|
if ((u_int)which > ITIMER_PROF)
|
|
return (EINVAL);
|
|
itvp = (struct netbsd32_itimerval *)(u_long)SCARG(uap, itv);
|
|
if (itvp && (error = copyin(itvp, &s32it, sizeof(s32it))))
|
|
return (error);
|
|
netbsd32_to_itimerval(&s32it, &aitv);
|
|
if (SCARG(uap, oitv) != NULL) {
|
|
SCARG(&getargs, which) = which;
|
|
SCARG(&getargs, itv) = SCARG(uap, oitv);
|
|
if ((error = compat_netbsd32_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_netbsd32_getitimer(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getitimer_args /* {
|
|
syscallarg(int) which;
|
|
syscallarg(netbsd32_itimervalp_t) itv;
|
|
} */ *uap = v;
|
|
int which = SCARG(uap, which);
|
|
struct netbsd32_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);
|
|
netbsd32_from_itimerval(&aitv, &s32it);
|
|
return (copyout(&s32it, (caddr_t)(u_long)SCARG(uap, itv), sizeof(s32it)));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fcntl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fcntl_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(int) cmd;
|
|
syscallarg(netbsd32_voidp) arg;
|
|
} */ *uap = v;
|
|
struct sys_fcntl_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(cmd);
|
|
NETBSD32TOP_UAP(arg, void);
|
|
/* XXXX we can do this 'cause flock doesn't change */
|
|
return (sys_fcntl(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_dup2(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_dup2_args /* {
|
|
syscallarg(int) from;
|
|
syscallarg(int) to;
|
|
} */ *uap = v;
|
|
struct sys_dup2_args ua;
|
|
|
|
NETBSD32TO64_UAP(from);
|
|
NETBSD32TO64_UAP(to);
|
|
return (sys_dup2(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_select(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_select_args /* {
|
|
syscallarg(int) nd;
|
|
syscallarg(netbsd32_fd_setp_t) in;
|
|
syscallarg(netbsd32_fd_setp_t) ou;
|
|
syscallarg(netbsd32_fd_setp_t) ex;
|
|
syscallarg(netbsd32_timevalp_t) tv;
|
|
} */ *uap = v;
|
|
/* This one must be done in-line 'cause of the timeval */
|
|
struct netbsd32_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;
|
|
netbsd32_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_netbsd32_fsync(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fsync_args /* {
|
|
syscallarg(int) fd;
|
|
} */ *uap = v;
|
|
struct sys_fsync_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
return (sys_fsync(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setpriority(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setpriority_args /* {
|
|
syscallarg(int) which;
|
|
syscallarg(int) who;
|
|
syscallarg(int) prio;
|
|
} */ *uap = v;
|
|
struct sys_setpriority_args ua;
|
|
|
|
NETBSD32TO64_UAP(which);
|
|
NETBSD32TO64_UAP(who);
|
|
NETBSD32TO64_UAP(prio);
|
|
return (sys_setpriority(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_socket(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_socket_args /* {
|
|
syscallarg(int) domain;
|
|
syscallarg(int) type;
|
|
syscallarg(int) protocol;
|
|
} */ *uap = v;
|
|
struct sys_socket_args ua;
|
|
|
|
NETBSD32TO64_UAP(domain);
|
|
NETBSD32TO64_UAP(type);
|
|
NETBSD32TO64_UAP(protocol);
|
|
return (sys_socket(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_connect(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_connect_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(const netbsd32_sockaddrp_t) name;
|
|
syscallarg(int) namelen;
|
|
} */ *uap = v;
|
|
struct sys_connect_args ua;
|
|
|
|
NETBSD32TO64_UAP(s);
|
|
NETBSD32TOP_UAP(name, struct sockaddr);
|
|
NETBSD32TO64_UAP(namelen);
|
|
return (sys_connect(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getpriority(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getpriority_args /* {
|
|
syscallarg(int) which;
|
|
syscallarg(int) who;
|
|
} */ *uap = v;
|
|
struct sys_getpriority_args ua;
|
|
|
|
NETBSD32TO64_UAP(which);
|
|
NETBSD32TO64_UAP(who);
|
|
return (sys_getpriority(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_bind(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_bind_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(const netbsd32_sockaddrp_t) name;
|
|
syscallarg(int) namelen;
|
|
} */ *uap = v;
|
|
struct sys_bind_args ua;
|
|
|
|
NETBSD32TO64_UAP(s);
|
|
NETBSD32TOP_UAP(name, struct sockaddr);
|
|
NETBSD32TO64_UAP(namelen);
|
|
return (sys_bind(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setsockopt(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setsockopt_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(int) level;
|
|
syscallarg(int) name;
|
|
syscallarg(const netbsd32_voidp) val;
|
|
syscallarg(int) valsize;
|
|
} */ *uap = v;
|
|
struct sys_setsockopt_args ua;
|
|
|
|
NETBSD32TO64_UAP(s);
|
|
NETBSD32TO64_UAP(level);
|
|
NETBSD32TO64_UAP(name);
|
|
NETBSD32TOP_UAP(val, void);
|
|
NETBSD32TO64_UAP(valsize);
|
|
/* may be more efficient to do this inline. */
|
|
return (sys_setsockopt(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_listen(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_listen_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(int) backlog;
|
|
} */ *uap = v;
|
|
struct sys_listen_args ua;
|
|
|
|
NETBSD32TO64_UAP(s);
|
|
NETBSD32TO64_UAP(backlog);
|
|
return (sys_listen(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_vtrace(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#ifdef TRACE
|
|
struct compat_netbsd32_vtrace_args /* {
|
|
syscallarg(int) request;
|
|
syscallarg(int) value;
|
|
} */ *uap = v;
|
|
struct sys_vtrace_args ua;
|
|
|
|
NETBSD32TO64_UAP(request);
|
|
NETBSD32TO64_UAP(value);
|
|
return (vtrace(p, &ua, retval));
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_gettimeofday(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_gettimeofday_args /* {
|
|
syscallarg(netbsd32_timevalp_t) tp;
|
|
syscallarg(netbsd32_timezonep_t) tzp;
|
|
} */ *uap = v;
|
|
struct timeval atv;
|
|
struct netbsd32_timeval tv32;
|
|
int error = 0;
|
|
struct netbsd32_timezone tzfake;
|
|
|
|
if (SCARG(uap, tp)) {
|
|
microtime(&atv);
|
|
netbsd32_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_netbsd32_settimeofday(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_settimeofday_args /* {
|
|
syscallarg(const netbsd32_timevalp_t) tv;
|
|
syscallarg(const netbsd32_timezonep_t) tzp;
|
|
} */ *uap = v;
|
|
struct netbsd32_timeval atv32;
|
|
struct timeval atv;
|
|
struct netbsd32_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);
|
|
netbsd32_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_netbsd32_fchown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fchown_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(uid_t) uid;
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys_fchown_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TO64_UAP(gid);
|
|
return (sys_fchown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fchmod(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fchmod_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(mode_t) mode;
|
|
} */ *uap = v;
|
|
struct sys_fchmod_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(mode);
|
|
return (sys_fchmod(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setreuid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setreuid_args /* {
|
|
syscallarg(uid_t) ruid;
|
|
syscallarg(uid_t) euid;
|
|
} */ *uap = v;
|
|
struct sys_setreuid_args ua;
|
|
|
|
NETBSD32TO64_UAP(ruid);
|
|
NETBSD32TO64_UAP(euid);
|
|
return (sys_setreuid(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setregid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setregid_args /* {
|
|
syscallarg(gid_t) rgid;
|
|
syscallarg(gid_t) egid;
|
|
} */ *uap = v;
|
|
struct sys_setregid_args ua;
|
|
|
|
NETBSD32TO64_UAP(rgid);
|
|
NETBSD32TO64_UAP(egid);
|
|
return (sys_setregid(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getrusage(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getrusage_args /* {
|
|
syscallarg(int) who;
|
|
syscallarg(netbsd32_rusagep_t) rusage;
|
|
} */ *uap = v;
|
|
struct rusage *rup;
|
|
struct netbsd32_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);
|
|
}
|
|
netbsd32_from_rusage(rup, &ru);
|
|
return (copyout(&ru, (caddr_t)(u_long)SCARG(uap, rusage), sizeof(ru)));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getsockopt(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getsockopt_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(int) level;
|
|
syscallarg(int) name;
|
|
syscallarg(netbsd32_voidp) val;
|
|
syscallarg(netbsd32_intp) avalsize;
|
|
} */ *uap = v;
|
|
struct sys_getsockopt_args ua;
|
|
|
|
NETBSD32TO64_UAP(s);
|
|
NETBSD32TO64_UAP(level);
|
|
NETBSD32TO64_UAP(name);
|
|
NETBSD32TOP_UAP(val, void);
|
|
NETBSD32TOP_UAP(avalsize, int);
|
|
return (sys_getsockopt(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_readv(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_readv_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_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 netbsd32_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 netbsd32_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 = netbsd32_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_netbsd32_writev(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_writev_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_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 netbsd32_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 netbsd32_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 = netbsd32_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_netbsd32_rename(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_rename_args /* {
|
|
syscallarg(const netbsd32_charp) from;
|
|
syscallarg(const netbsd32_charp) to;
|
|
} */ *uap = v;
|
|
struct sys_rename_args ua;
|
|
|
|
NETBSD32TOP_UAP(from, const char *);
|
|
NETBSD32TOP_UAP(to, const char *)
|
|
|
|
return (sys_rename(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_flock(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_flock_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(int) how;
|
|
} */ *uap = v;
|
|
struct sys_flock_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(how)
|
|
|
|
return (sys_flock(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_mkfifo(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mkfifo_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(mode_t) mode;
|
|
} */ *uap = v;
|
|
struct sys_mkfifo_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char)
|
|
NETBSD32TO64_UAP(mode);
|
|
return (sys_mkfifo(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_shutdown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_shutdown_args /* {
|
|
syscallarg(int) s;
|
|
syscallarg(int) how;
|
|
} */ *uap = v;
|
|
struct sys_shutdown_args ua;
|
|
|
|
NETBSD32TO64_UAP(s)
|
|
NETBSD32TO64_UAP(how);
|
|
return (sys_shutdown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_socketpair(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_socketpair_args /* {
|
|
syscallarg(int) domain;
|
|
syscallarg(int) type;
|
|
syscallarg(int) protocol;
|
|
syscallarg(netbsd32_intp) rsv;
|
|
} */ *uap = v;
|
|
struct sys_socketpair_args ua;
|
|
|
|
NETBSD32TO64_UAP(domain);
|
|
NETBSD32TO64_UAP(type);
|
|
NETBSD32TO64_UAP(protocol);
|
|
NETBSD32TOP_UAP(rsv, int);
|
|
/* Since we're just copying out two `int's we can do this */
|
|
return (sys_socketpair(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_mkdir(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mkdir_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(mode_t) mode;
|
|
} */ *uap = v;
|
|
struct sys_mkdir_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char)
|
|
NETBSD32TO64_UAP(mode);
|
|
return (sys_mkdir(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_rmdir(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_rmdir_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_rmdir_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
return (sys_rmdir(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_utimes(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_utimes_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(const netbsd32_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 netbsd32_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);
|
|
}
|
|
netbsd32_to_timeval(&tv32[0], &tv[0]);
|
|
netbsd32_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_netbsd32_adjtime(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_adjtime_args /* {
|
|
syscallarg(const netbsd32_timevalp_t) delta;
|
|
syscallarg(netbsd32_timevalp_t) olddelta;
|
|
} */ *uap = v;
|
|
struct netbsd32_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_netbsd32_quotactl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_quotactl_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(int) cmd;
|
|
syscallarg(int) uid;
|
|
syscallarg(netbsd32_caddr_t) arg;
|
|
} */ *uap = v;
|
|
struct sys_quotactl_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(cmd);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TOX64_UAP(arg, caddr_t);
|
|
return (sys_quotactl(p, &ua, retval));
|
|
}
|
|
|
|
#if defined(NFS) || defined(NFSSERVER)
|
|
int
|
|
compat_netbsd32_nfssvc(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_nfssvc_args /* {
|
|
syscallarg(int) flag;
|
|
syscallarg(netbsd32_voidp) argp;
|
|
} */ *uap = v;
|
|
struct sys_nfssvc_args ua;
|
|
|
|
NETBSD32TO64_UAP(flag);
|
|
NETBSD32TOP_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_netbsd32_statfs(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_statfs_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(netbsd32_statfsp_t) buf;
|
|
} */ *uap = v;
|
|
register struct mount *mp;
|
|
register struct statfs *sp;
|
|
struct netbsd32_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;
|
|
netbsd32_from_statfs(sp, &s32);
|
|
return (copyout(&s32, (caddr_t)(u_long)SCARG(uap, buf), sizeof(s32)));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fstatfs(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fstatfs_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_statfsp_t) buf;
|
|
} */ *uap = v;
|
|
struct file *fp;
|
|
register struct mount *mp;
|
|
register struct statfs *sp;
|
|
struct netbsd32_statfs s32;
|
|
int error;
|
|
|
|
/* getvnode() will use the descriptor for us */
|
|
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)
|
|
goto out;
|
|
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
|
|
netbsd32_from_statfs(sp, &s32);
|
|
error = copyout(&s32, (caddr_t)(u_long)SCARG(uap, buf), sizeof(s32));
|
|
out:
|
|
FILE_UNUSE(fp);
|
|
return (error);
|
|
}
|
|
|
|
#if defined(NFS) || defined(NFSSERVER)
|
|
int
|
|
compat_netbsd32_getfh(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getfh_args /* {
|
|
syscallarg(const netbsd32_charp) fname;
|
|
syscallarg(netbsd32_fhandlep_t) fhp;
|
|
} */ *uap = v;
|
|
struct sys_getfh_args ua;
|
|
|
|
NETBSD32TOP_UAP(fname, const char);
|
|
NETBSD32TOP_UAP(fhp, struct fhandle);
|
|
/* Lucky for us a fhandlep_t doesn't change sizes */
|
|
return (sys_getfh(p, &ua, retval));
|
|
}
|
|
#endif
|
|
|
|
int
|
|
compat_netbsd32_sysarch(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_sysarch_args /* {
|
|
syscallarg(int) op;
|
|
syscallarg(netbsd32_voidp) parms;
|
|
} */ *uap = v;
|
|
|
|
switch (SCARG(uap, op)) {
|
|
default:
|
|
printf("(sparc64) compat_netbsd32_sysarch(%d)\n", SCARG(uap, op));
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_pread(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_pread_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_voidp) buf;
|
|
syscallarg(netbsd32_size_t) nbyte;
|
|
syscallarg(int) pad;
|
|
syscallarg(off_t) offset;
|
|
} */ *uap = v;
|
|
struct sys_pread_args ua;
|
|
ssize_t rt;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TOP_UAP(buf, void);
|
|
NETBSD32TOX_UAP(nbyte, size_t);
|
|
NETBSD32TO64_UAP(pad);
|
|
NETBSD32TO64_UAP(offset);
|
|
error = sys_pread(p, &ua, (register_t *)&rt);
|
|
*(netbsd32_ssize_t *)retval = rt;
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_pwrite(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_pwrite_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_voidp) buf;
|
|
syscallarg(netbsd32_size_t) nbyte;
|
|
syscallarg(int) pad;
|
|
syscallarg(off_t) offset;
|
|
} */ *uap = v;
|
|
struct sys_pwrite_args ua;
|
|
ssize_t rt;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TOP_UAP(buf, void);
|
|
NETBSD32TOX_UAP(nbyte, size_t);
|
|
NETBSD32TO64_UAP(pad);
|
|
NETBSD32TO64_UAP(offset);
|
|
error = sys_pwrite(p, &ua, (register_t *)&rt);
|
|
*(netbsd32_ssize_t *)retval = rt;
|
|
return (error);
|
|
}
|
|
|
|
#ifdef NTP
|
|
int
|
|
compat_netbsd32_ntp_gettime(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_ntp_gettime_args /* {
|
|
syscallarg(netbsd32_ntptimevalp_t) ntvp;
|
|
} */ *uap = v;
|
|
struct netbsd32_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);
|
|
|
|
netbsd32_from_timeval(&ntv.time, &ntv32.time);
|
|
ntv32.maxerror = (netbsd32_long)ntv.maxerror;
|
|
ntv32.esterror = (netbsd32_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_netbsd32_ntp_adjtime(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_ntp_adjtime_args /* {
|
|
syscallarg(netbsd32_timexp_t) tp;
|
|
} */ *uap = v;
|
|
struct netbsd32_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);
|
|
netbsd32_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);
|
|
|
|
netbsd32_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_netbsd32_setgid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setgid_args /* {
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys_setgid_args ua;
|
|
|
|
NETBSD32TO64_UAP(gid);
|
|
return (sys_setgid(p, v, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_setegid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setegid_args /* {
|
|
syscallarg(gid_t) egid;
|
|
} */ *uap = v;
|
|
struct sys_setegid_args ua;
|
|
|
|
NETBSD32TO64_UAP(egid);
|
|
return (sys_setegid(p, v, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_seteuid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_seteuid_args /* {
|
|
syscallarg(gid_t) euid;
|
|
} */ *uap = v;
|
|
struct sys_seteuid_args ua;
|
|
|
|
NETBSD32TO64_UAP(euid);
|
|
return (sys_seteuid(p, v, retval));
|
|
}
|
|
|
|
#ifdef LFS
|
|
int
|
|
compat_netbsd32_lfs_bmapv(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_lfs_bmapv_args /* {
|
|
syscallarg(netbsd32_fsid_tp_t) fsidp;
|
|
syscallarg(netbsd32_block_infop_t) blkiov;
|
|
syscallarg(int) blkcnt;
|
|
} */ *uap = v;
|
|
struct sys_lfs_bmapv_args ua;
|
|
|
|
NETBSD32TOP_UAP(fdidp, struct fsid);
|
|
NETBSD32TO64_UAP(blkcnt);
|
|
/* XXX finish me */
|
|
#else
|
|
|
|
return (ENOSYS); /* XXX */
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lfs_markv(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lfs_markv_args /* {
|
|
syscallarg(netbsd32_fsid_tp_t) fsidp;
|
|
syscallarg(netbsd32_block_infop_t) blkiov;
|
|
syscallarg(int) blkcnt;
|
|
} */ *uap = v;
|
|
|
|
return (ENOSYS); /* XXX */
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lfs_segclean(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lfs_segclean_args /* {
|
|
syscallarg(netbsd32_fsid_tp_t) fsidp;
|
|
syscallarg(netbsd32_u_long) segment;
|
|
} */ *uap = v;
|
|
return (ENOSYS); /* XXX */
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lfs_segwait(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lfs_segwait_args /* {
|
|
syscallarg(netbsd32_fsid_tp_t) fsidp;
|
|
syscallarg(netbsd32_timevalp_t) tv;
|
|
} */ *uap = v;
|
|
return (ENOSYS); /* XXX */
|
|
}
|
|
#endif
|
|
|
|
int
|
|
compat_netbsd32_pathconf(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_pathconf_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(int) name;
|
|
} */ *uap = v;
|
|
struct sys_pathconf_args ua;
|
|
long rt;
|
|
int error;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(name);
|
|
error = sys_pathconf(p, &ua, (register_t *)&rt);
|
|
*(netbsd32_long *)retval = (netbsd32_long)rt;
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fpathconf(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fpathconf_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(int) name;
|
|
} */ *uap = v;
|
|
struct sys_fpathconf_args ua;
|
|
long rt;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(name);
|
|
error = sys_fpathconf(p, &ua, (register_t *)&rt);
|
|
*(netbsd32_long *)retval = (netbsd32_long)rt;
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getrlimit(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getrlimit_args /* {
|
|
syscallarg(int) which;
|
|
syscallarg(netbsd32_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_netbsd32_setrlimit(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_setrlimit_args /* {
|
|
syscallarg(int) which;
|
|
syscallarg(const netbsd32_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_netbsd32_mmap(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mmap_args /* {
|
|
syscallarg(netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) prot;
|
|
syscallarg(int) flags;
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_long) pad;
|
|
syscallarg(off_t) pos;
|
|
} */ *uap = v;
|
|
struct sys_mmap_args ua;
|
|
void *rt;
|
|
int error;
|
|
|
|
NETBSD32TOP_UAP(addr, void);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
NETBSD32TO64_UAP(prot);
|
|
NETBSD32TO64_UAP(flags);
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TOX_UAP(pad, long);
|
|
NETBSD32TOX_UAP(pos, off_t);
|
|
error = sys_mmap(p, &ua, (register_t *)&rt);
|
|
if ((long)rt > (long)UINT_MAX)
|
|
printf("compat_netbsd32_mmap: retval out of range: 0x%qx",
|
|
rt);
|
|
*retval = (netbsd32_voidp)(u_long)rt;
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lseek(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lseek_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(int) pad;
|
|
syscallarg(off_t) offset;
|
|
syscallarg(int) whence;
|
|
} */ *uap = v;
|
|
struct sys_lseek_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(pad);
|
|
NETBSD32TO64_UAP(offset);
|
|
NETBSD32TO64_UAP(whence);
|
|
return (sys_lseek(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_truncate(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_truncate_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(int) pad;
|
|
syscallarg(off_t) length;
|
|
} */ *uap = v;
|
|
struct sys_truncate_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(pad);
|
|
NETBSD32TO64_UAP(length);
|
|
return (sys_truncate(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_ftruncate(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_ftruncate_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(int) pad;
|
|
syscallarg(off_t) length;
|
|
} */ *uap = v;
|
|
struct sys_ftruncate_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(pad);
|
|
NETBSD32TO64_UAP(length);
|
|
return (sys_ftruncate(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___sysctl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___sysctl_args /* {
|
|
syscallarg(netbsd32_intp) name;
|
|
syscallarg(u_int) namelen;
|
|
syscallarg(netbsd32_voidp) old;
|
|
syscallarg(netbsd32_size_tp) oldlenp;
|
|
syscallarg(netbsd32_voidp) new;
|
|
syscallarg(netbsd32_size_t) newlen;
|
|
} */ *uap = v;
|
|
int error, dolock = 1;
|
|
netbsd32_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_netbsd32_mlock(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_mlock_args /* {
|
|
syscallarg(const netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
} */ *uap = v;
|
|
struct sys_mlock_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, const void);
|
|
NETBSD32TO64_UAP(len);
|
|
return (sys_mlock(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_munlock(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_munlock_args /* {
|
|
syscallarg(const netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
} */ *uap = v;
|
|
struct sys_munlock_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, const void);
|
|
NETBSD32TO64_UAP(len);
|
|
return (sys_munlock(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_undelete(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_undelete_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
} */ *uap = v;
|
|
struct sys_undelete_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
return (sys_undelete(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_futimes(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_futimes_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_timevalp_t) tptr;
|
|
} */ *uap = v;
|
|
int error;
|
|
struct file *fp;
|
|
|
|
/* getvnode() will use the descriptor for us */
|
|
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
|
return (error);
|
|
|
|
error = change_utimes32((struct vnode *)fp->f_data,
|
|
(struct timeval *)(u_long)SCARG(uap, tptr), p);
|
|
FILE_UNUSE(fp);
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getpgid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getpgid_args /* {
|
|
syscallarg(pid_t) pid;
|
|
} */ *uap = v;
|
|
struct sys_getpgid_args ua;
|
|
|
|
NETBSD32TO64_UAP(pid);
|
|
return (sys_getpgid(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_reboot(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_reboot_args /* {
|
|
syscallarg(int) opt;
|
|
syscallarg(netbsd32_charp) bootstr;
|
|
} */ *uap = v;
|
|
struct sys_reboot_args ua;
|
|
|
|
NETBSD32TO64_UAP(opt);
|
|
NETBSD32TOP_UAP(bootstr, char);
|
|
return (sys_reboot(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_poll(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_poll_args /* {
|
|
syscallarg(netbsd32_pollfdp_t) fds;
|
|
syscallarg(u_int) nfds;
|
|
syscallarg(int) timeout;
|
|
} */ *uap = v;
|
|
struct sys_poll_args ua;
|
|
|
|
NETBSD32TOP_UAP(fds, struct pollfd);
|
|
NETBSD32TO64_UAP(nfds);
|
|
NETBSD32TO64_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_netbsd32___semctl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32___semctl_args /* {
|
|
syscallarg(int) semid;
|
|
syscallarg(int) semnum;
|
|
syscallarg(int) cmd;
|
|
syscallarg(netbsd32_semunu_t) arg;
|
|
} */ *uap = v;
|
|
union netbsd32_semun sem32;
|
|
int semid = SCARG(uap, semid);
|
|
int semnum = SCARG(uap, semnum);
|
|
int cmd = SCARG(uap, cmd);
|
|
union netbsd32_semun *arg = (void*)(u_long)SCARG(uap, arg);
|
|
union netbsd32_semun real_arg;
|
|
struct ucred *cred = p->p_ucred;
|
|
int i, rval, eval;
|
|
struct netbsd32_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_netbsd32_semget(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_semget_args /* {
|
|
syscallarg(netbsd32_key_t) key;
|
|
syscallarg(int) nsems;
|
|
syscallarg(int) semflg;
|
|
} */ *uap = v;
|
|
struct sys_semget_args ua;
|
|
|
|
NETBSD32TOX_UAP(key, key_t);
|
|
NETBSD32TO64_UAP(nsems);
|
|
NETBSD32TO64_UAP(semflg);
|
|
return (sys_semget(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_semop(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_semop_args /* {
|
|
syscallarg(int) semid;
|
|
syscallarg(netbsd32_sembufp_t) sops;
|
|
syscallarg(netbsd32_size_t) nsops;
|
|
} */ *uap = v;
|
|
struct sys_semop_args ua;
|
|
|
|
NETBSD32TO64_UAP(semid);
|
|
NETBSD32TOP_UAP(sops, struct sembuf);
|
|
NETBSD32TOX_UAP(nsops, size_t);
|
|
return (sys_semop(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_semconfig(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_semconfig_args /* {
|
|
syscallarg(int) flag;
|
|
} */ *uap = v;
|
|
struct sys_semconfig_args ua;
|
|
|
|
NETBSD32TO64_UAP(flag);
|
|
return (sys_semconfig(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_msgctl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_msgctl_args /* {
|
|
syscallarg(int) msqid;
|
|
syscallarg(int) cmd;
|
|
syscallarg(netbsd32_msqid_dsp_t) buf;
|
|
} */ *uap = v;
|
|
struct sys_msgctl_args ua;
|
|
struct msqid_ds ds;
|
|
struct netbsd32_msqid_ds *ds32p;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(msqid);
|
|
NETBSD32TO64_UAP(cmd);
|
|
ds32p = (struct netbsd32_msqid_ds *)(u_long)SCARG(uap, buf);
|
|
if (ds32p) {
|
|
SCARG(&ua, buf) = NULL;
|
|
netbsd32_to_msqid_ds(ds32p, &ds);
|
|
} else
|
|
SCARG(&ua, buf) = NULL;
|
|
error = sys_msgctl(p, &ua, retval);
|
|
if (error)
|
|
return (error);
|
|
|
|
if (ds32p)
|
|
netbsd32_from_msqid_ds(&ds, ds32p);
|
|
return (0);
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_msgget(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_msgget_args /* {
|
|
syscallarg(netbsd32_key_t) key;
|
|
syscallarg(int) msgflg;
|
|
} */ *uap = v;
|
|
struct sys_msgget_args ua;
|
|
|
|
NETBSD32TOX_UAP(key, key_t);
|
|
NETBSD32TO64_UAP(msgflg);
|
|
return (sys_msgget(p, &ua, retval));
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_msgsnd(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_msgsnd_args /* {
|
|
syscallarg(int) msqid;
|
|
syscallarg(const netbsd32_voidp) msgp;
|
|
syscallarg(netbsd32_size_t) msgsz;
|
|
syscallarg(int) msgflg;
|
|
} */ *uap = v;
|
|
struct sys_msgsnd_args ua;
|
|
|
|
NETBSD32TO64_UAP(msqid);
|
|
NETBSD32TOP_UAP(msgp, void);
|
|
NETBSD32TOX_UAP(msgsz, size_t);
|
|
NETBSD32TO64_UAP(msgflg);
|
|
return (sys_msgsnd(p, &ua, retval));
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_msgrcv(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_msgrcv_args /* {
|
|
syscallarg(int) msqid;
|
|
syscallarg(netbsd32_voidp) msgp;
|
|
syscallarg(netbsd32_size_t) msgsz;
|
|
syscallarg(netbsd32_long) msgtyp;
|
|
syscallarg(int) msgflg;
|
|
} */ *uap = v;
|
|
struct sys_msgrcv_args ua;
|
|
ssize_t rt;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(msqid);
|
|
NETBSD32TOP_UAP(msgp, void);
|
|
NETBSD32TOX_UAP(msgsz, size_t);
|
|
NETBSD32TOX_UAP(msgtyp, long);
|
|
NETBSD32TO64_UAP(msgflg);
|
|
error = sys_msgrcv(p, &ua, (register_t *)&rt);
|
|
*(netbsd32_ssize_t *)retval = rt;
|
|
return (error);
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_shmat(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_shmat_args /* {
|
|
syscallarg(int) shmid;
|
|
syscallarg(const netbsd32_voidp) shmaddr;
|
|
syscallarg(int) shmflg;
|
|
} */ *uap = v;
|
|
struct sys_shmat_args ua;
|
|
void *rt;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(shmid);
|
|
NETBSD32TOP_UAP(shmaddr, void);
|
|
NETBSD32TO64_UAP(shmflg);
|
|
error = sys_shmat(p, &ua, (register_t *)&rt);
|
|
*retval = (netbsd32_voidp)(u_long)rt;
|
|
return (error);
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_shmctl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_shmctl_args /* {
|
|
syscallarg(int) shmid;
|
|
syscallarg(int) cmd;
|
|
syscallarg(netbsd32_shmid_dsp_t) buf;
|
|
} */ *uap = v;
|
|
struct sys_shmctl_args ua;
|
|
struct shmid_ds ds;
|
|
struct netbsd32_shmid_ds *ds32p;
|
|
int error;
|
|
|
|
NETBSD32TO64_UAP(shmid);
|
|
NETBSD32TO64_UAP(cmd);
|
|
ds32p = (struct netbsd32_shmid_ds *)(u_long)SCARG(uap, buf);
|
|
if (ds32p) {
|
|
SCARG(&ua, buf) = NULL;
|
|
netbsd32_to_shmid_ds(ds32p, &ds);
|
|
} else
|
|
SCARG(&ua, buf) = NULL;
|
|
error = sys_shmctl(p, &ua, retval);
|
|
if (error)
|
|
return (error);
|
|
|
|
if (ds32p)
|
|
netbsd32_from_shmid_ds(&ds, ds32p);
|
|
return (0);
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_shmdt(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_shmdt_args /* {
|
|
syscallarg(const netbsd32_voidp) shmaddr;
|
|
} */ *uap = v;
|
|
struct sys_shmdt_args ua;
|
|
|
|
NETBSD32TOP_UAP(shmaddr, const char);
|
|
return (sys_shmdt(p, &ua, retval));
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_shmget(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
#if 0
|
|
struct compat_netbsd32_shmget_args /* {
|
|
syscallarg(netbsd32_key_t) key;
|
|
syscallarg(netbsd32_size_t) size;
|
|
syscallarg(int) shmflg;
|
|
} */ *uap = v;
|
|
struct sys_shmget_args ua;
|
|
|
|
NETBSD32TOX_UAP(key, key_t)
|
|
NETBSD32TOX_UAP(size, size_t)
|
|
NETBSD32TO64_UAP(shmflg);
|
|
return (sys_shmget(p, &ua, retval));
|
|
#else
|
|
return (ENOSYS);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_clock_gettime(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_clock_gettime_args /* {
|
|
syscallarg(netbsd32_clockid_t) clock_id;
|
|
syscallarg(netbsd32_timespecp_t) tp;
|
|
} */ *uap = v;
|
|
clockid_t clock_id;
|
|
struct timeval atv;
|
|
struct timespec ats;
|
|
struct netbsd32_timespec ts32;
|
|
|
|
clock_id = SCARG(uap, clock_id);
|
|
if (clock_id != CLOCK_REALTIME)
|
|
return (EINVAL);
|
|
|
|
microtime(&atv);
|
|
TIMEVAL_TO_TIMESPEC(&atv,&ats);
|
|
netbsd32_from_timespec(&ats, &ts32);
|
|
|
|
return copyout(&ts32, (caddr_t)(u_long)SCARG(uap, tp), sizeof(ts32));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_clock_settime(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_clock_settime_args /* {
|
|
syscallarg(netbsd32_clockid_t) clock_id;
|
|
syscallarg(const netbsd32_timespecp_t) tp;
|
|
} */ *uap = v;
|
|
struct netbsd32_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);
|
|
|
|
netbsd32_to_timespec(&ts32, &ats);
|
|
TIMESPEC_TO_TIMEVAL(&atv,&ats);
|
|
if ((error = settime(&atv)))
|
|
return (error);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_clock_getres(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_clock_getres_args /* {
|
|
syscallarg(netbsd32_clockid_t) clock_id;
|
|
syscallarg(netbsd32_timespecp_t) tp;
|
|
} */ *uap = v;
|
|
struct netbsd32_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;
|
|
|
|
netbsd32_from_timespec(&ts, &ts32);
|
|
error = copyout(&ts, (caddr_t)(u_long)SCARG(uap, tp), sizeof(ts));
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_nanosleep(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_nanosleep_args /* {
|
|
syscallarg(const netbsd32_timespecp_t) rqtp;
|
|
syscallarg(netbsd32_timespecp_t) rmtp;
|
|
} */ *uap = v;
|
|
static int nanowait;
|
|
struct netbsd32_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);
|
|
|
|
netbsd32_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);
|
|
netbsd32_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_netbsd32_fdatasync(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fdatasync_args /* {
|
|
syscallarg(int) fd;
|
|
} */ *uap = v;
|
|
struct sys_fdatasync_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
|
|
return (sys_fdatasync(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___posix_rename(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___posix_rename_args /* {
|
|
syscallarg(const netbsd32_charp) from;
|
|
syscallarg(const netbsd32_charp) to;
|
|
} */ *uap = v;
|
|
struct sys___posix_rename_args ua;
|
|
|
|
NETBSD32TOP_UAP(from, const char *);
|
|
NETBSD32TOP_UAP(to, const char *);
|
|
|
|
return (sys___posix_rename(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_swapctl(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_swapctl_args /* {
|
|
syscallarg(int) cmd;
|
|
syscallarg(const netbsd32_voidp) arg;
|
|
syscallarg(int) misc;
|
|
} */ *uap = v;
|
|
struct sys_swapctl_args ua;
|
|
|
|
NETBSD32TO64_UAP(cmd);
|
|
NETBSD32TOP_UAP(arg, const void);
|
|
NETBSD32TO64_UAP(misc);
|
|
return (sys_swapctl(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getdents(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getdents_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_charp) buf;
|
|
syscallarg(netbsd32_size_t) count;
|
|
} */ *uap = v;
|
|
struct file *fp;
|
|
int error, done;
|
|
|
|
/* getvnode() will use the descriptor for us */
|
|
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
|
return (error);
|
|
if ((fp->f_flag & FREAD) == 0) {
|
|
error = EBADF;
|
|
goto out;
|
|
}
|
|
error = vn_readdir(fp, (caddr_t)(u_long)SCARG(uap, buf), UIO_USERSPACE,
|
|
SCARG(uap, count), &done, p, 0, 0);
|
|
*retval = done;
|
|
out:
|
|
FILE_UNUSE(fp);
|
|
return (error);
|
|
}
|
|
|
|
|
|
int
|
|
compat_netbsd32_minherit(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_minherit_args /* {
|
|
syscallarg(netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) inherit;
|
|
} */ *uap = v;
|
|
struct sys_minherit_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, void);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
NETBSD32TO64_UAP(inherit);
|
|
return (sys_minherit(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lchmod(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lchmod_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(mode_t) mode;
|
|
} */ *uap = v;
|
|
struct sys_lchmod_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(mode);
|
|
return (sys_lchmod(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lchown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lchown_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(uid_t) uid;
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys_lchown_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TO64_UAP(gid);
|
|
return (sys_lchown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_lutimes(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_lutimes_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(const netbsd32_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_netbsd32___msync13(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___msync13_args /* {
|
|
syscallarg(netbsd32_voidp) addr;
|
|
syscallarg(netbsd32_size_t) len;
|
|
syscallarg(int) flags;
|
|
} */ *uap = v;
|
|
struct sys___msync13_args ua;
|
|
|
|
NETBSD32TOP_UAP(addr, void);
|
|
NETBSD32TOX_UAP(len, size_t);
|
|
NETBSD32TO64_UAP(flags);
|
|
return (sys___msync13(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___stat13(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___stat13_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(netbsd32_statp_t) ub;
|
|
} */ *uap = v;
|
|
struct netbsd32_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);
|
|
netbsd32_from___stat13(&sb, &sb32);
|
|
error = copyout(&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof(sb32));
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___fstat13(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___fstat13_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(netbsd32_statp_t) sb;
|
|
} */ *uap = v;
|
|
int fd = SCARG(uap, fd);
|
|
register struct filedesc *fdp = p->p_fd;
|
|
register struct file *fp;
|
|
struct netbsd32_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) {
|
|
netbsd32_from___stat13(&ub, &sb32);
|
|
error = copyout(&sb32, (caddr_t)(u_long)SCARG(uap, sb), sizeof(sb32));
|
|
}
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___lstat13(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___lstat13_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(netbsd32_statp_t) ub;
|
|
} */ *uap = v;
|
|
struct netbsd32_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);
|
|
netbsd32_from___stat13(&sb, &sb32);
|
|
error = copyout(&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof(sb32));
|
|
return (error);
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___sigaltstack14(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___sigaltstack14_args /* {
|
|
syscallarg(const netbsd32_sigaltstackp_t) nss;
|
|
syscallarg(netbsd32_sigaltstackp_t) oss;
|
|
} */ *uap = v;
|
|
struct netbsd32_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 = (netbsd32_voidp)(u_long)oss.ss_sp;
|
|
s32.ss_size = (netbsd32_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_netbsd32___posix_chown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___posix_chown_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(uid_t) uid;
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys___posix_chown_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TO64_UAP(gid);
|
|
return (sys___posix_chown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___posix_fchown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___posix_fchown_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(uid_t) uid;
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys___posix_fchown_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TO64_UAP(gid);
|
|
return (sys___posix_fchown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32___posix_lchown(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32___posix_lchown_args /* {
|
|
syscallarg(const netbsd32_charp) path;
|
|
syscallarg(uid_t) uid;
|
|
syscallarg(gid_t) gid;
|
|
} */ *uap = v;
|
|
struct sys___posix_lchown_args ua;
|
|
|
|
NETBSD32TOP_UAP(path, const char);
|
|
NETBSD32TO64_UAP(uid);
|
|
NETBSD32TO64_UAP(gid);
|
|
return (sys___posix_lchown(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_getsid(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_getsid_args /* {
|
|
syscallarg(pid_t) pid;
|
|
} */ *uap = v;
|
|
struct sys_getsid_args ua;
|
|
|
|
NETBSD32TO64_UAP(pid);
|
|
return (sys_getsid(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_fktrace(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_fktrace_args /* {
|
|
syscallarg(const int) fd;
|
|
syscallarg(int) ops;
|
|
syscallarg(int) facs;
|
|
syscallarg(int) pid;
|
|
} */ *uap = v;
|
|
struct sys_fktrace_args ua;
|
|
|
|
NETBSD32TO64_UAP(fd);
|
|
NETBSD32TO64_UAP(ops);
|
|
NETBSD32TO64_UAP(facs);
|
|
NETBSD32TO64_UAP(pid);
|
|
return (sys_fktrace(p, &ua, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_preadv(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_preadv_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_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 netbsd32_iovec *)(u_long)SCARG(uap, iovp), SCARG(uap, iovcnt),
|
|
&offset, 0, retval));
|
|
}
|
|
|
|
int
|
|
compat_netbsd32_pwritev(p, v, retval)
|
|
struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_netbsd32_pwritev_args /* {
|
|
syscallarg(int) fd;
|
|
syscallarg(const netbsd32_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 netbsd32_iovec *)(u_long)SCARG(uap, iovp), SCARG(uap, iovcnt),
|
|
&offset, 0, retval));
|
|
}
|
|
|
|
int
|
|
compat_13_compat_netbsd32_sigprocmask(p, v, retval)
|
|
register struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_13_compat_netbsd32_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_netbsd32_sigsuspend(p, v, retval)
|
|
register struct proc *p;
|
|
void *v;
|
|
register_t *retval;
|
|
{
|
|
struct compat_13_compat_netbsd32_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));
|
|
}
|