freebsd32_misc.c revision 109623
1159307Spjd/*- 2220922Spjd * Copyright (c) 2002 Doug Rabson 3159307Spjd * All rights reserved. 4159307Spjd * 5159307Spjd * Redistribution and use in source and binary forms, with or without 6159307Spjd * modification, are permitted provided that the following conditions 7159307Spjd * are met: 8159307Spjd * 1. Redistributions of source code must retain the above copyright 9159307Spjd * notice, this list of conditions and the following disclaimer. 10159307Spjd * 2. Redistributions in binary form must reproduce the above copyright 11159307Spjd * notice, this list of conditions and the following disclaimer in the 12159307Spjd * documentation and/or other materials provided with the distribution. 13159307Spjd * 14159307Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15159307Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16159307Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17159307Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18159307Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19159307Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20159307Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21159307Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22159307Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23159307Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24159307Spjd * SUCH DAMAGE. 25159307Spjd * 26159307Spjd * $FreeBSD: head/sys/compat/freebsd32/freebsd32_misc.c 109623 2003-01-21 08:56:16Z alfred $ 27159307Spjd */ 28159307Spjd 29159307Spjd#include "opt_compat.h" 30159307Spjd 31159307Spjd#include <sys/param.h> 32159307Spjd#include <sys/systm.h> 33159307Spjd#include <sys/bus.h> 34159307Spjd#include <sys/dkstat.h> 35159307Spjd#include <sys/exec.h> 36159307Spjd#include <sys/fcntl.h> 37159307Spjd#include <sys/filedesc.h> 38159307Spjd#include <sys/imgact.h> 39159307Spjd#include <sys/kernel.h> 40159307Spjd#include <sys/lock.h> 41159307Spjd#include <sys/malloc.h> 42159307Spjd#include <sys/file.h> /* Must come after sys/malloc.h */ 43159307Spjd#include <sys/mman.h> 44159307Spjd#include <sys/module.h> 45159307Spjd#include <sys/mount.h> 46159307Spjd#include <sys/mutex.h> 47159307Spjd#include <sys/namei.h> 48159307Spjd#include <sys/param.h> 49159307Spjd#include <sys/proc.h> 50159307Spjd#include <sys/reboot.h> 51159307Spjd#include <sys/resource.h> 52159307Spjd#include <sys/resourcevar.h> 53159307Spjd#include <sys/selinfo.h> 54159307Spjd#include <sys/pipe.h> /* Must come after sys/selinfo.h */ 55159307Spjd#include <sys/signal.h> 56159307Spjd#include <sys/signalvar.h> 57159307Spjd#include <sys/socket.h> 58159307Spjd#include <sys/socketvar.h> 59159307Spjd#include <sys/stat.h> 60159307Spjd#include <sys/sysctl.h> 61159307Spjd#include <sys/sysent.h> 62159307Spjd#include <sys/sysproto.h> 63159307Spjd#include <sys/systm.h> 64159307Spjd#include <sys/unistd.h> 65159307Spjd#include <sys/user.h> 66159307Spjd#include <sys/utsname.h> 67159307Spjd#include <sys/vnode.h> 68159307Spjd 69159307Spjd#include <vm/vm.h> 70159307Spjd#include <vm/vm_kern.h> 71159307Spjd#include <vm/vm_param.h> 72159307Spjd#include <vm/pmap.h> 73159307Spjd#include <vm/vm_map.h> 74159307Spjd#include <vm/vm_object.h> 75159307Spjd#include <vm/vm_extern.h> 76159307Spjd 77159307Spjd#include <ia64/ia32/ia32_util.h> 78159307Spjd#include <ia64/ia32/ia32.h> 79159307Spjd#include <ia64/ia32/ia32_proto.h> 80159307Spjd 81159307Spjdstatic const char ia32_emul_path[] = "/compat/ia32"; 82159307Spjd/* 83159307Spjd * [ taken from the linux emulator ] 84159307Spjd * Search an alternate path before passing pathname arguments on 85159307Spjd * to system calls. Useful for keeping a separate 'emulation tree'. 86159307Spjd * 87159307Spjd * If cflag is set, we check if an attempt can be made to create 88159307Spjd * the named file, i.e. we check if the directory it should 89159307Spjd * be in exists. 90159307Spjd */ 91159307Spjdint 92159307Spjdia32_emul_find(td, sgp, prefix, path, pbuf, cflag) 93159307Spjd struct thread *td; 94159307Spjd caddr_t *sgp; /* Pointer to stackgap memory */ 95159307Spjd const char *prefix; 96159307Spjd char *path; 97159307Spjd char **pbuf; 98159307Spjd int cflag; 99159307Spjd{ 100159307Spjd int error; 101159307Spjd size_t len, sz; 102159307Spjd char *buf, *cp, *ptr; 103159307Spjd struct ucred *ucred; 104159307Spjd struct nameidata nd; 105159307Spjd struct nameidata ndroot; 106159307Spjd struct vattr vat; 107159307Spjd struct vattr vatroot; 108159307Spjd 109159307Spjd buf = (char *) malloc(MAXPATHLEN, M_TEMP, 0); 110159307Spjd *pbuf = path; 111159307Spjd 112159307Spjd for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++) 113159307Spjd continue; 114159307Spjd 115159307Spjd sz = MAXPATHLEN - (ptr - buf); 116159307Spjd 117159307Spjd /* 118159307Spjd * If sgp is not given then the path is already in kernel space 119159307Spjd */ 120159307Spjd if (sgp == NULL) 121159307Spjd error = copystr(path, ptr, sz, &len); 122159307Spjd else 123159307Spjd error = copyinstr(path, ptr, sz, &len); 124159307Spjd 125159307Spjd if (error) { 126159307Spjd free(buf, M_TEMP); 127159307Spjd return error; 128159307Spjd } 129159307Spjd 130159307Spjd if (*ptr != '/') { 131159307Spjd free(buf, M_TEMP); 132214118Spjd return EINVAL; 133159307Spjd } 134159307Spjd 135159307Spjd /* 136159307Spjd * We know that there is a / somewhere in this pathname. 137159307Spjd * Search backwards for it, to find the file's parent dir 138159307Spjd * to see if it exists in the alternate tree. If it does, 139159307Spjd * and we want to create a file (cflag is set). We don't 140159307Spjd * need to worry about the root comparison in this case. 141159307Spjd */ 142159307Spjd 143159307Spjd if (cflag) { 144159307Spjd for (cp = &ptr[len] - 1; *cp != '/'; cp--) 145159307Spjd ; 146159307Spjd *cp = '\0'; 147159307Spjd 148159307Spjd NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 149159307Spjd 150159307Spjd if ((error = namei(&nd)) != 0) { 151220922Spjd free(buf, M_TEMP); 152220922Spjd return error; 153159307Spjd } 154159307Spjd 155159307Spjd *cp = '/'; 156159307Spjd } else { 157159307Spjd NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td); 158159307Spjd 159159307Spjd if ((error = namei(&nd)) != 0) { 160159307Spjd free(buf, M_TEMP); 161159307Spjd return error; 162159307Spjd } 163159307Spjd 164159307Spjd /* 165159307Spjd * We now compare the vnode of the ia32_root to the one 166159307Spjd * vnode asked. If they resolve to be the same, then we 167159307Spjd * ignore the match so that the real root gets used. 168159307Spjd * This avoids the problem of traversing "../.." to find the 169159307Spjd * root directory and never finding it, because "/" resolves 170159307Spjd * to the emulation root directory. This is expensive :-( 171159307Spjd */ 172159307Spjd NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, ia32_emul_path, 173159307Spjd td); 174159307Spjd 175159307Spjd if ((error = namei(&ndroot)) != 0) { 176159307Spjd /* Cannot happen! */ 177159307Spjd free(buf, M_TEMP); 178159307Spjd vrele(nd.ni_vp); 179159307Spjd return error; 180159307Spjd } 181159307Spjd 182159307Spjd ucred = td->td_ucred; 183159307Spjd if ((error = VOP_GETATTR(nd.ni_vp, &vat, ucred, td)) != 0) { 184159307Spjd goto bad; 185159307Spjd } 186159307Spjd 187159307Spjd if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, ucred, 188159307Spjd td)) != 0) { 189159307Spjd goto bad; 190159307Spjd } 191159307Spjd 192159307Spjd if (vat.va_fsid == vatroot.va_fsid && 193159307Spjd vat.va_fileid == vatroot.va_fileid) { 194159307Spjd error = ENOENT; 195159307Spjd goto bad; 196159307Spjd } 197159307Spjd 198159307Spjd } 199159307Spjd if (sgp == NULL) 200159307Spjd *pbuf = buf; 201159307Spjd else { 202159307Spjd sz = &ptr[len] - buf; 203159307Spjd *pbuf = stackgap_alloc(sgp, sz + 1); 204159307Spjd error = copyout(buf, *pbuf, sz); 205159307Spjd free(buf, M_TEMP); 206159307Spjd } 207159307Spjd 208159307Spjd vrele(nd.ni_vp); 209159307Spjd if (!cflag) 210159307Spjd vrele(ndroot.ni_vp); 211159307Spjd 212159307Spjd return error; 213159307Spjd 214159307Spjdbad: 215159307Spjd vrele(ndroot.ni_vp); 216159307Spjd vrele(nd.ni_vp); 217159307Spjd free(buf, M_TEMP); 218159307Spjd return error; 219159307Spjd} 220159307Spjd 221159307Spjdint 222159307Spjdia32_open(struct thread *td, struct ia32_open_args *uap) 223159307Spjd{ 224159307Spjd caddr_t sg; 225159307Spjd 226159307Spjd sg = stackgap_init(); 227159307Spjd CHECKALTEXIST(td, &sg, uap->path); 228159307Spjd 229159307Spjd return open(td, (struct open_args *) uap); 230159307Spjd} 231159307Spjd 232159307Spjdint 233159307Spjdia32_wait4(struct thread *td, struct ia32_wait4_args *uap) 234159307Spjd{ 235159307Spjd int error; 236159307Spjd caddr_t sg; 237159307Spjd struct rusage32 *rusage32, ru32; 238159307Spjd struct rusage *rusage = NULL, ru; 239159307Spjd 240159307Spjd rusage32 = uap->rusage; 241159307Spjd if (rusage32) { 242159307Spjd sg = stackgap_init(); 243159307Spjd rusage = stackgap_alloc(&sg, sizeof(struct rusage)); 244214118Spjd uap->rusage = (struct rusage32 *)rusage; 245159307Spjd } 246159307Spjd error = wait4(td, (struct wait_args *)uap); 247159307Spjd if (error) 248159307Spjd return (error); 249159307Spjd if (rusage32 && (error = copyin(rusage, &ru, sizeof(ru)) == 0)) { 250159307Spjd TV_CP(ru, ru32, ru_utime); 251159307Spjd TV_CP(ru, ru32, ru_stime); 252159307Spjd CP(ru, ru32, ru_maxrss); 253159307Spjd CP(ru, ru32, ru_ixrss); 254159307Spjd CP(ru, ru32, ru_idrss); 255159307Spjd CP(ru, ru32, ru_isrss); 256159307Spjd CP(ru, ru32, ru_minflt); 257159307Spjd CP(ru, ru32, ru_majflt); 258159307Spjd CP(ru, ru32, ru_nswap); 259159307Spjd CP(ru, ru32, ru_inblock); 260159307Spjd CP(ru, ru32, ru_oublock); 261159307Spjd CP(ru, ru32, ru_msgsnd); 262159307Spjd CP(ru, ru32, ru_msgrcv); 263159307Spjd CP(ru, ru32, ru_nsignals); 264159307Spjd CP(ru, ru32, ru_nvcsw); 265159307Spjd CP(ru, ru32, ru_nivcsw); 266159307Spjd error = copyout(&ru32, rusage32, sizeof(ru32)); 267159307Spjd } 268159307Spjd return (error); 269159307Spjd} 270159307Spjd 271159307Spjdstatic void 272159307Spjdcopy_statfs(struct statfs *in, struct statfs32 *out) 273159307Spjd{ 274159307Spjd CP(*in, *out, f_bsize); 275159307Spjd CP(*in, *out, f_iosize); 276220922Spjd CP(*in, *out, f_blocks); 277220922Spjd CP(*in, *out, f_bfree); 278159307Spjd CP(*in, *out, f_bavail); 279159307Spjd CP(*in, *out, f_files); 280159307Spjd CP(*in, *out, f_ffree); 281159307Spjd CP(*in, *out, f_fsid); 282159307Spjd CP(*in, *out, f_owner); 283159307Spjd CP(*in, *out, f_type); 284159307Spjd CP(*in, *out, f_flags); 285159307Spjd CP(*in, *out, f_flags); 286159307Spjd CP(*in, *out, f_syncwrites); 287159307Spjd CP(*in, *out, f_asyncwrites); 288159307Spjd bcopy(in->f_fstypename, 289159307Spjd out->f_fstypename, MFSNAMELEN); 290159307Spjd bcopy(in->f_mntonname, 291159307Spjd out->f_mntonname, MNAMELEN); 292214118Spjd CP(*in, *out, f_syncreads); 293159307Spjd CP(*in, *out, f_asyncreads); 294159307Spjd bcopy(in->f_mntfromname, 295159307Spjd out->f_mntfromname, MNAMELEN); 296159307Spjd} 297159307Spjd 298159307Spjdint 299159307Spjdia32_getfsstat(struct thread *td, struct ia32_getfsstat_args *uap) 300159307Spjd{ 301159307Spjd int error; 302159307Spjd caddr_t sg; 303159307Spjd struct statfs32 *sp32, stat32; 304159307Spjd struct statfs *sp = NULL, stat; 305159307Spjd int maxcount, count, i; 306159307Spjd 307159307Spjd sp32 = uap->buf; 308159307Spjd maxcount = uap->bufsize / sizeof(struct statfs32); 309159307Spjd 310159307Spjd if (sp32) { 311159307Spjd sg = stackgap_init(); 312159307Spjd sp = stackgap_alloc(&sg, sizeof(struct statfs) * maxcount); 313159307Spjd uap->buf = (struct statfs32 *)sp; 314159307Spjd } 315159307Spjd error = getfsstat(td, (struct getfsstat_args *) uap); 316159307Spjd if (sp32 && !error) { 317159307Spjd count = td->td_retval[0]; 318159307Spjd for (i = 0; i < count; i++) { 319159307Spjd error = copyin(&sp[i], &stat, sizeof(stat)); 320159307Spjd if (error) 321159307Spjd return (error); 322159307Spjd copy_statfs(&stat, &stat32); 323159307Spjd error = copyout(&stat32, &sp32[i], sizeof(stat32)); 324159307Spjd if (error) 325159307Spjd return (error); 326159307Spjd } 327159307Spjd } 328159307Spjd return (error); 329159307Spjd} 330159307Spjd 331159307Spjdint 332159307Spjdia32_access(struct thread *td, struct ia32_access_args *uap) 333159307Spjd{ 334159307Spjd caddr_t sg; 335159307Spjd 336159307Spjd sg = stackgap_init(); 337159307Spjd CHECKALTEXIST(td, &sg, uap->path); 338159307Spjd 339159307Spjd return access(td, (struct access_args *)uap); 340159307Spjd} 341159307Spjd 342159307Spjdint 343159307Spjdia32_chflags(struct thread *td, struct ia32_chflags_args *uap) 344159307Spjd{ 345159307Spjd caddr_t sg; 346159307Spjd 347159307Spjd sg = stackgap_init(); 348159307Spjd CHECKALTEXIST(td, &sg, uap->path); 349159307Spjd 350159307Spjd return chflags(td, (struct chflags_args *)uap); 351159307Spjd} 352159307Spjd 353159307Spjdstruct sigaltstack32 { 354159307Spjd u_int32_t ss_sp; 355159307Spjd u_int32_t ss_size; 356159307Spjd int ss_flags; 357159307Spjd}; 358159307Spjd 359159307Spjdint 360159307Spjdia32_sigaltstack(struct thread *td, struct ia32_sigaltstack_args *uap) 361159307Spjd{ 362159307Spjd int error; 363159307Spjd caddr_t sg; 364159307Spjd struct sigaltstack32 *p32, *op32, s32; 365159307Spjd struct sigaltstack *p = NULL, *op = NULL, s; 366159307Spjd 367159307Spjd p32 = uap->ss; 368159307Spjd if (p32) { 369159307Spjd sg = stackgap_init(); 370159307Spjd p = stackgap_alloc(&sg, sizeof(struct sigaltstack)); 371159307Spjd uap->ss = (struct sigaltstack32 *)p; 372159307Spjd error = copyin(p32, &s32, sizeof(s32)); 373159307Spjd if (error) 374159307Spjd return (error); 375159307Spjd PTRIN_CP(s32, s, ss_sp); 376159307Spjd CP(s32, s, ss_size); 377159307Spjd CP(s32, s, ss_flags); 378159307Spjd error = copyout(&s, p, sizeof(s)); 379159307Spjd if (error) 380159307Spjd return (error); 381159307Spjd } 382159307Spjd op32 = uap->oss; 383159307Spjd if (op32) { 384159307Spjd sg = stackgap_init(); 385159307Spjd op = stackgap_alloc(&sg, sizeof(struct sigaltstack)); 386159307Spjd uap->oss = (struct sigaltstack32 *)op; 387159307Spjd } 388159307Spjd error = sigaltstack(td, (struct sigaltstack_args *) uap); 389159307Spjd if (error) 390159307Spjd return (error); 391159307Spjd if (op32) { 392159307Spjd error = copyin(op, &s, sizeof(s)); 393159307Spjd if (error) 394159307Spjd return (error); 395159307Spjd PTROUT_CP(s, s32, ss_sp); 396159307Spjd CP(s, s32, ss_size); 397159307Spjd CP(s, s32, ss_flags); 398159307Spjd error = copyout(&s32, op32, sizeof(s32)); 399214116Spjd } 400214116Spjd return (error); 401214116Spjd} 402214116Spjd 403214116Spjdint 404159307Spjdia32_execve(struct thread *td, struct ia32_execve_args *uap) 405159307Spjd{ 406159307Spjd int error; 407159307Spjd caddr_t sg; 408159307Spjd struct execve_args ap; 409159307Spjd u_int32_t *p32, arg; 410159307Spjd char **p; 411159307Spjd int count; 412159307Spjd 413159307Spjd sg = stackgap_init(); 414159307Spjd CHECKALTEXIST(td, &sg, uap->fname); 415159307Spjd ap.fname = uap->fname; 416159307Spjd 417159307Spjd if (uap->argv) { 418159307Spjd count = 0; 419159307Spjd p32 = uap->argv; 420159307Spjd do { 421159307Spjd error = copyin(p32++, &arg, sizeof(arg)); 422159307Spjd if (error) 423159307Spjd return error; 424159307Spjd count++; 425159307Spjd } while (arg != 0); 426159307Spjd p = stackgap_alloc(&sg, count * sizeof(char *)); 427159307Spjd ap.argv = p; 428159307Spjd p32 = uap->argv; 429159307Spjd do { 430159307Spjd error = copyin(p32++, &arg, sizeof(arg)); 431159307Spjd if (error) 432159307Spjd return error; 433159307Spjd *p++ = PTRIN(arg); 434159307Spjd } while (arg != 0); 435159307Spjd } 436159307Spjd if (uap->envv) { 437159343Spjd count = 0; 438159307Spjd p32 = uap->envv; 439159307Spjd do { 440159307Spjd error = copyin(p32++, &arg, sizeof(arg)); 441159307Spjd if (error) 442159307Spjd return error; 443159307Spjd count++; 444159307Spjd } while (arg != 0); 445159307Spjd p = stackgap_alloc(&sg, count * sizeof(char *)); 446159307Spjd ap.envv = p; 447159307Spjd p32 = uap->envv; 448159307Spjd do { 449159307Spjd error = copyin(p32++, &arg, sizeof(arg)); 450159307Spjd if (error) 451159307Spjd return error; 452159307Spjd *p++ = PTRIN(arg); 453159307Spjd } while (arg != 0); 454159307Spjd } 455159307Spjd 456159307Spjd return execve(td, &ap); 457159307Spjd} 458159307Spjd 459159307Spjdstatic int 460159307Spjdia32_mmap_partial(struct thread *td, vm_offset_t start, vm_offset_t end, 461159307Spjd int prot, int fd, off_t pos) 462159307Spjd{ 463159307Spjd vm_map_t map; 464159307Spjd vm_map_entry_t entry; 465159307Spjd int rv; 466159307Spjd 467159307Spjd map = &td->td_proc->p_vmspace->vm_map; 468159307Spjd if (fd != -1) 469159307Spjd prot |= VM_PROT_WRITE; 470159307Spjd 471159307Spjd if (vm_map_lookup_entry(map, start, &entry)) { 472159307Spjd if ((entry->protection & prot) != prot) { 473159307Spjd rv = vm_map_protect(map, 474159307Spjd trunc_page(start), 475159307Spjd round_page(end), 476159307Spjd entry->protection | prot, 477159307Spjd FALSE); 478159307Spjd if (rv != KERN_SUCCESS) 479159307Spjd return (EINVAL); 480159307Spjd } 481159307Spjd } else { 482159307Spjd vm_offset_t addr = trunc_page(start); 483159307Spjd rv = vm_map_find(map, 0, 0, 484159307Spjd &addr, PAGE_SIZE, FALSE, prot, 485159307Spjd VM_PROT_ALL, 0); 486159307Spjd if (rv != KERN_SUCCESS) 487159307Spjd return (EINVAL); 488159307Spjd } 489159307Spjd 490159307Spjd if (fd != -1) { 491159307Spjd struct pread_args r; 492159307Spjd r.fd = fd; 493159307Spjd r.buf = (void *) start; 494159343Spjd r.nbyte = end - start; 495160569Spjd r.offset = pos; 496159307Spjd return (pread(td, &r)); 497159307Spjd } else { 498159307Spjd while (start < end) { 499159307Spjd subyte((void *) start, 0); 500159307Spjd start++; 501159307Spjd } 502159307Spjd return (0); 503159307Spjd } 504159307Spjd} 505159307Spjd 506159307Spjdint 507159307Spjdia32_mmap(struct thread *td, struct ia32_mmap_args *uap) 508159307Spjd{ 509159307Spjd struct mmap_args ap; 510159307Spjd vm_offset_t addr = (vm_offset_t) uap->addr; 511159307Spjd vm_size_t len = uap->len; 512159307Spjd int prot = uap->prot; 513159307Spjd int flags = uap->flags; 514159307Spjd int fd = uap->fd; 515159307Spjd off_t pos = (uap->poslo 516159307Spjd | ((off_t)uap->poshi << 32)); 517159307Spjd vm_size_t pageoff; 518159307Spjd int error; 519220922Spjd 520159307Spjd /* 521213070Spjd * Attempt to handle page size hassles. 522213070Spjd */ 523159307Spjd pageoff = (pos & PAGE_MASK); 524159307Spjd if (flags & MAP_FIXED) { 525159307Spjd vm_offset_t start, end; 526159307Spjd start = addr; 527159307Spjd end = addr + len; 528159307Spjd 529159307Spjd if (start != trunc_page(start)) { 530159307Spjd error = ia32_mmap_partial(td, start, round_page(start), 531159307Spjd prot, fd, pos); 532159307Spjd if (fd != -1) 533159307Spjd pos += round_page(start) - start; 534159307Spjd start = round_page(start); 535159307Spjd } 536159307Spjd if (end != round_page(end)) { 537159307Spjd vm_offset_t t = trunc_page(end); 538159307Spjd error = ia32_mmap_partial(td, t, end, 539159307Spjd prot, fd, 540159307Spjd pos + t - start); 541159307Spjd end = trunc_page(end); 542159307Spjd } 543 if (end > start && fd != -1 && (pos & PAGE_MASK)) { 544 /* 545 * We can't map this region at all. The specified 546 * address doesn't have the same alignment as the file 547 * position. Fake the mapping by simply reading the 548 * entire region into memory. First we need to make 549 * sure the region exists. 550 */ 551 vm_map_t map; 552 struct pread_args r; 553 int rv; 554 555 prot |= VM_PROT_WRITE; 556 map = &td->td_proc->p_vmspace->vm_map; 557 rv = vm_map_remove(map, start, end); 558 if (rv != KERN_SUCCESS) 559 return (EINVAL); 560 rv = vm_map_find(map, 0, 0, 561 &start, end - start, FALSE, 562 prot, VM_PROT_ALL, 0); 563 if (rv != KERN_SUCCESS) 564 return (EINVAL); 565 r.fd = fd; 566 r.buf = (void *) start; 567 r.nbyte = end - start; 568 r.offset = pos; 569 error = pread(td, &r); 570 if (error) 571 return (error); 572 573 td->td_retval[0] = addr; 574 return (0); 575 } 576 if (end == start) { 577 /* 578 * After dealing with the ragged ends, there 579 * might be none left. 580 */ 581 td->td_retval[0] = addr; 582 return (0); 583 } 584 addr = start; 585 len = end - start; 586 } 587 588 ap.addr = (void *) addr; 589 ap.len = len; 590 ap.prot = prot; 591 ap.flags = flags; 592 ap.fd = fd; 593 ap.pos = pos; 594 595 return (mmap(td, &ap)); 596} 597 598struct itimerval32 { 599 struct timeval32 it_interval; 600 struct timeval32 it_value; 601}; 602 603int 604ia32_setitimer(struct thread *td, struct ia32_setitimer_args *uap) 605{ 606 int error; 607 caddr_t sg; 608 struct itimerval32 *p32, *op32, s32; 609 struct itimerval *p = NULL, *op = NULL, s; 610 611 p32 = uap->itv; 612 if (p32) { 613 sg = stackgap_init(); 614 p = stackgap_alloc(&sg, sizeof(struct itimerval)); 615 uap->itv = (struct itimerval32 *)p; 616 error = copyin(p32, &s32, sizeof(s32)); 617 if (error) 618 return (error); 619 TV_CP(s32, s, it_interval); 620 TV_CP(s32, s, it_value); 621 error = copyout(&s, p, sizeof(s)); 622 if (error) 623 return (error); 624 } 625 op32 = uap->oitv; 626 if (op32) { 627 sg = stackgap_init(); 628 op = stackgap_alloc(&sg, sizeof(struct itimerval)); 629 uap->oitv = (struct itimerval32 *)op; 630 } 631 error = setitimer(td, (struct setitimer_args *) uap); 632 if (error) 633 return (error); 634 if (op32) { 635 error = copyin(op, &s, sizeof(s)); 636 if (error) 637 return (error); 638 TV_CP(s, s32, it_interval); 639 TV_CP(s, s32, it_value); 640 error = copyout(&s32, op32, sizeof(s32)); 641 } 642 return (error); 643} 644 645int 646ia32_select(struct thread *td, struct ia32_select_args *uap) 647{ 648 int error; 649 caddr_t sg; 650 struct timeval32 *p32, s32; 651 struct timeval *p = NULL, s; 652 653 p32 = uap->tv; 654 if (p32) { 655 sg = stackgap_init(); 656 p = stackgap_alloc(&sg, sizeof(struct timeval)); 657 uap->tv = (struct timeval32 *)p; 658 error = copyin(p32, &s32, sizeof(s32)); 659 if (error) 660 return (error); 661 CP(s32, s, tv_sec); 662 CP(s32, s, tv_usec); 663 error = copyout(&s, p, sizeof(s)); 664 if (error) 665 return (error); 666 } 667 /* 668 * XXX big-endian needs to convert the fd_sets too. 669 */ 670 return (select(td, (struct select_args *) uap)); 671} 672 673int 674ia32_gettimeofday(struct thread *td, struct ia32_gettimeofday_args *uap) 675{ 676 int error; 677 caddr_t sg; 678 struct timeval32 *p32, s32; 679 struct timeval *p = NULL, s; 680 681 p32 = uap->tp; 682 if (p32) { 683 sg = stackgap_init(); 684 p = stackgap_alloc(&sg, sizeof(struct timeval)); 685 uap->tp = (struct timeval32 *)p; 686 } 687 error = gettimeofday(td, (struct gettimeofday_args *) uap); 688 if (error) 689 return (error); 690 if (p32) { 691 error = copyin(p, &s, sizeof(s)); 692 if (error) 693 return (error); 694 CP(s, s32, tv_sec); 695 CP(s, s32, tv_usec); 696 error = copyout(&s32, p32, sizeof(s32)); 697 if (error) 698 return (error); 699 } 700 return (error); 701} 702 703int 704ia32_getrusage(struct thread *td, struct ia32_getrusage_args *uap) 705{ 706 int error; 707 caddr_t sg; 708 struct rusage32 *p32, s32; 709 struct rusage *p = NULL, s; 710 711 p32 = uap->rusage; 712 if (p32) { 713 sg = stackgap_init(); 714 p = stackgap_alloc(&sg, sizeof(struct rusage)); 715 uap->rusage = (struct rusage32 *)p; 716 } 717 error = getrusage(td, (struct getrusage_args *) uap); 718 if (error) 719 return (error); 720 if (p32) { 721 error = copyin(p, &s, sizeof(s)); 722 if (error) 723 return (error); 724 TV_CP(s, s32, ru_utime); 725 TV_CP(s, s32, ru_stime); 726 CP(s, s32, ru_maxrss); 727 CP(s, s32, ru_ixrss); 728 CP(s, s32, ru_idrss); 729 CP(s, s32, ru_isrss); 730 CP(s, s32, ru_minflt); 731 CP(s, s32, ru_majflt); 732 CP(s, s32, ru_nswap); 733 CP(s, s32, ru_inblock); 734 CP(s, s32, ru_oublock); 735 CP(s, s32, ru_msgsnd); 736 CP(s, s32, ru_msgrcv); 737 CP(s, s32, ru_nsignals); 738 CP(s, s32, ru_nvcsw); 739 CP(s, s32, ru_nivcsw); 740 error = copyout(&s32, p32, sizeof(s32)); 741 } 742 return (error); 743} 744 745struct iovec32 { 746 u_int32_t iov_base; 747 int iov_len; 748}; 749#define STACKGAPLEN 400 750 751int 752ia32_readv(struct thread *td, struct ia32_readv_args *uap) 753{ 754 int error, osize, nsize, i; 755 caddr_t sg; 756 struct readv_args /* { 757 syscallarg(int) fd; 758 syscallarg(struct iovec *) iovp; 759 syscallarg(u_int) iovcnt; 760 } */ a; 761 struct iovec32 *oio; 762 struct iovec *nio; 763 764 sg = stackgap_init(); 765 766 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 767 return (EINVAL); 768 769 osize = uap->iovcnt * sizeof (struct iovec32); 770 nsize = uap->iovcnt * sizeof (struct iovec); 771 772 oio = malloc(osize, M_TEMP, 0); 773 nio = malloc(nsize, M_TEMP, 0); 774 775 error = 0; 776 if ((error = copyin(uap->iovp, oio, osize))) 777 goto punt; 778 for (i = 0; i < uap->iovcnt; i++) { 779 nio[i].iov_base = PTRIN(oio[i].iov_base); 780 nio[i].iov_len = oio[i].iov_len; 781 } 782 783 a.fd = uap->fd; 784 a.iovp = stackgap_alloc(&sg, nsize); 785 a.iovcnt = uap->iovcnt; 786 787 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 788 goto punt; 789 error = readv(td, &a); 790 791punt: 792 free(oio, M_TEMP); 793 free(nio, M_TEMP); 794 return (error); 795} 796 797int 798ia32_writev(struct thread *td, struct ia32_writev_args *uap) 799{ 800 int error, i, nsize, osize; 801 caddr_t sg; 802 struct writev_args /* { 803 syscallarg(int) fd; 804 syscallarg(struct iovec *) iovp; 805 syscallarg(u_int) iovcnt; 806 } */ a; 807 struct iovec32 *oio; 808 struct iovec *nio; 809 810 sg = stackgap_init(); 811 812 if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) 813 return (EINVAL); 814 815 osize = uap->iovcnt * sizeof (struct iovec32); 816 nsize = uap->iovcnt * sizeof (struct iovec); 817 818 oio = malloc(osize, M_TEMP, 0); 819 nio = malloc(nsize, M_TEMP, 0); 820 821 error = 0; 822 if ((error = copyin(uap->iovp, oio, osize))) 823 goto punt; 824 for (i = 0; i < uap->iovcnt; i++) { 825 nio[i].iov_base = PTRIN(oio[i].iov_base); 826 nio[i].iov_len = oio[i].iov_len; 827 } 828 829 a.fd = uap->fd; 830 a.iovp = stackgap_alloc(&sg, nsize); 831 a.iovcnt = uap->iovcnt; 832 833 if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) 834 goto punt; 835 error = writev(td, &a); 836 837punt: 838 free(oio, M_TEMP); 839 free(nio, M_TEMP); 840 return (error); 841} 842 843int 844ia32_settimeofday(struct thread *td, struct ia32_settimeofday_args *uap) 845{ 846 int error; 847 caddr_t sg; 848 struct timeval32 *p32, s32; 849 struct timeval *p = NULL, s; 850 851 p32 = uap->tv; 852 if (p32) { 853 sg = stackgap_init(); 854 p = stackgap_alloc(&sg, sizeof(struct timeval)); 855 uap->tv = (struct timeval32 *)p; 856 error = copyin(p32, &s32, sizeof(s32)); 857 if (error) 858 return (error); 859 CP(s32, s, tv_sec); 860 CP(s32, s, tv_usec); 861 error = copyout(&s, p, sizeof(s)); 862 if (error) 863 return (error); 864 } 865 return (settimeofday(td, (struct settimeofday_args *) uap)); 866} 867 868int 869ia32_utimes(struct thread *td, struct ia32_utimes_args *uap) 870{ 871 int error; 872 caddr_t sg; 873 struct timeval32 *p32, s32[2]; 874 struct timeval *p = NULL, s[2]; 875 876 p32 = uap->tptr; 877 if (p32) { 878 sg = stackgap_init(); 879 p = stackgap_alloc(&sg, 2*sizeof(struct timeval)); 880 uap->tptr = (struct timeval32 *)p; 881 error = copyin(p32, s32, sizeof(s32)); 882 if (error) 883 return (error); 884 CP(s32[0], s[0], tv_sec); 885 CP(s32[0], s[0], tv_usec); 886 CP(s32[1], s[1], tv_sec); 887 CP(s32[1], s[1], tv_usec); 888 error = copyout(s, p, sizeof(s)); 889 if (error) 890 return (error); 891 } 892 return (utimes(td, (struct utimes_args *) uap)); 893} 894 895int 896ia32_adjtime(struct thread *td, struct ia32_adjtime_args *uap) 897{ 898 int error; 899 caddr_t sg; 900 struct timeval32 *p32, *op32, s32; 901 struct timeval *p = NULL, *op = NULL, s; 902 903 p32 = uap->delta; 904 if (p32) { 905 sg = stackgap_init(); 906 p = stackgap_alloc(&sg, sizeof(struct timeval)); 907 uap->delta = (struct timeval32 *)p; 908 error = copyin(p32, &s32, sizeof(s32)); 909 if (error) 910 return (error); 911 CP(s32, s, tv_sec); 912 CP(s32, s, tv_usec); 913 error = copyout(&s, p, sizeof(s)); 914 if (error) 915 return (error); 916 } 917 op32 = uap->olddelta; 918 if (op32) { 919 sg = stackgap_init(); 920 op = stackgap_alloc(&sg, sizeof(struct timeval)); 921 uap->olddelta = (struct timeval32 *)op; 922 } 923 error = utimes(td, (struct utimes_args *) uap); 924 if (error) 925 return error; 926 if (op32) { 927 error = copyin(op, &s, sizeof(s)); 928 if (error) 929 return (error); 930 CP(s, s32, tv_sec); 931 CP(s, s32, tv_usec); 932 error = copyout(&s32, op32, sizeof(s32)); 933 } 934 return (error); 935} 936 937int 938ia32_statfs(struct thread *td, struct ia32_statfs_args *uap) 939{ 940 int error; 941 caddr_t sg; 942 struct statfs32 *p32, s32; 943 struct statfs *p = NULL, s; 944 945 p32 = uap->buf; 946 if (p32) { 947 sg = stackgap_init(); 948 p = stackgap_alloc(&sg, sizeof(struct statfs)); 949 uap->buf = (struct statfs32 *)p; 950 } 951 error = statfs(td, (struct statfs_args *) uap); 952 if (error) 953 return (error); 954 if (p32) { 955 error = copyin(p, &s, sizeof(s)); 956 if (error) 957 return (error); 958 copy_statfs(&s, &s32); 959 error = copyout(&s32, p32, sizeof(s32)); 960 } 961 return (error); 962} 963 964int 965ia32_fstatfs(struct thread *td, struct ia32_fstatfs_args *uap) 966{ 967 int error; 968 caddr_t sg; 969 struct statfs32 *p32, s32; 970 struct statfs *p = NULL, s; 971 972 p32 = uap->buf; 973 if (p32) { 974 sg = stackgap_init(); 975 p = stackgap_alloc(&sg, sizeof(struct statfs)); 976 uap->buf = (struct statfs32 *)p; 977 } 978 error = fstatfs(td, (struct fstatfs_args *) uap); 979 if (error) 980 return (error); 981 if (p32) { 982 error = copyin(p, &s, sizeof(s)); 983 if (error) 984 return (error); 985 copy_statfs(&s, &s32); 986 error = copyout(&s32, p32, sizeof(s32)); 987 } 988 return (error); 989} 990 991int 992ia32_semsys(struct thread *td, struct ia32_semsys_args *uap) 993{ 994 /* 995 * Vector through to semsys if it is loaded. 996 */ 997 return sysent[169].sy_call(td, uap); 998} 999 1000int 1001ia32_msgsys(struct thread *td, struct ia32_msgsys_args *uap) 1002{ 1003 /* 1004 * Vector through to msgsys if it is loaded. 1005 */ 1006 return sysent[170].sy_call(td, uap); 1007} 1008 1009int 1010ia32_shmsys(struct thread *td, struct ia32_shmsys_args *uap) 1011{ 1012 /* 1013 * Vector through to shmsys if it is loaded. 1014 */ 1015 return sysent[171].sy_call(td, uap); 1016} 1017 1018int 1019ia32_pread(struct thread *td, struct ia32_pread_args *uap) 1020{ 1021 struct pread_args ap; 1022 1023 ap.fd = uap->fd; 1024 ap.buf = uap->buf; 1025 ap.nbyte = uap->nbyte; 1026 ap.offset = (uap->offsetlo 1027 | ((off_t)uap->offsethi << 32)); 1028 return (pread(td, &ap)); 1029} 1030 1031int 1032ia32_pwrite(struct thread *td, struct ia32_pwrite_args *uap) 1033{ 1034 struct pwrite_args ap; 1035 1036 ap.fd = uap->fd; 1037 ap.buf = uap->buf; 1038 ap.nbyte = uap->nbyte; 1039 ap.offset = (uap->offsetlo 1040 | ((off_t)uap->offsethi << 32)); 1041 return (pwrite(td, &ap)); 1042} 1043 1044int 1045ia32_lseek(struct thread *td, struct ia32_lseek_args *uap) 1046{ 1047 int error; 1048 struct lseek_args ap; 1049 off_t pos; 1050 1051 ap.fd = uap->fd; 1052 ap.offset = (uap->offsetlo 1053 | ((off_t)uap->offsethi << 32)); 1054 ap.whence = uap->whence; 1055 error = lseek(td, &ap); 1056 /* Expand the quad return into two parts for eax and edx */ 1057 pos = *(off_t *)(td->td_retval); 1058 td->td_retval[0] = pos & 0xffffffff; /* %eax */ 1059 td->td_retval[1] = pos >> 32; /* %edx */ 1060 return error; 1061} 1062 1063int 1064ia32_truncate(struct thread *td, struct ia32_truncate_args *uap) 1065{ 1066 struct truncate_args ap; 1067 1068 ap.path = uap->path; 1069 ap.length = (uap->lengthlo 1070 | ((off_t)uap->lengthhi << 32)); 1071 return (truncate(td, &ap)); 1072} 1073 1074int 1075ia32_ftruncate(struct thread *td, struct ia32_ftruncate_args *uap) 1076{ 1077 struct ftruncate_args ap; 1078 1079 ap.fd = uap->fd; 1080 ap.length = (uap->lengthlo 1081 | ((off_t)uap->lengthhi << 32)); 1082 return (ftruncate(td, &ap)); 1083} 1084 1085#ifdef COMPAT_FREEBSD4 1086int 1087freebsd4_ia32_sendfile(struct thread *td, 1088 struct freebsd4_ia32_sendfile_args *uap) 1089{ 1090 struct freebsd4_sendfile_args ap; 1091 1092 ap.fd = uap->fd; 1093 ap.s = uap->s; 1094 ap.offset = (uap->offsetlo 1095 | ((off_t)uap->offsethi << 32)); 1096 ap.nbytes = uap->nbytes; /* XXX check */ 1097 ap.hdtr = uap->hdtr; /* XXX check */ 1098 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1099 ap.flags = uap->flags; 1100 return (freebsd4_sendfile(td, &ap)); 1101} 1102#endif 1103 1104int 1105ia32_sendfile(struct thread *td, struct ia32_sendfile_args *uap) 1106{ 1107 struct sendfile_args ap; 1108 1109 ap.fd = uap->fd; 1110 ap.s = uap->s; 1111 ap.offset = (uap->offsetlo 1112 | ((off_t)uap->offsethi << 32)); 1113 ap.nbytes = uap->nbytes; /* XXX check */ 1114 ap.hdtr = uap->hdtr; /* XXX check */ 1115 ap.sbytes = uap->sbytes; /* XXX FIXME!! */ 1116 ap.flags = uap->flags; 1117 return (sendfile(td, &ap)); 1118} 1119 1120struct stat32 { 1121 udev_t st_dev; 1122 ino_t st_ino; 1123 mode_t st_mode; 1124 nlink_t st_nlink; 1125 uid_t st_uid; 1126 gid_t st_gid; 1127 udev_t st_rdev; 1128 struct timespec32 st_atimespec; 1129 struct timespec32 st_mtimespec; 1130 struct timespec32 st_ctimespec; 1131 off_t st_size; 1132 int64_t st_blocks; 1133 u_int32_t st_blksize; 1134 u_int32_t st_flags; 1135 u_int32_t st_gen; 1136}; 1137 1138static void 1139copy_stat( struct stat *in, struct stat32 *out) 1140{ 1141 CP(*in, *out, st_dev); 1142 CP(*in, *out, st_ino); 1143 CP(*in, *out, st_mode); 1144 CP(*in, *out, st_nlink); 1145 CP(*in, *out, st_uid); 1146 CP(*in, *out, st_gid); 1147 CP(*in, *out, st_rdev); 1148 TS_CP(*in, *out, st_atimespec); 1149 TS_CP(*in, *out, st_mtimespec); 1150 TS_CP(*in, *out, st_ctimespec); 1151 CP(*in, *out, st_size); 1152 CP(*in, *out, st_blocks); 1153 CP(*in, *out, st_blksize); 1154 CP(*in, *out, st_flags); 1155 CP(*in, *out, st_gen); 1156} 1157 1158int 1159ia32_stat(struct thread *td, struct ia32_stat_args *uap) 1160{ 1161 int error; 1162 caddr_t sg; 1163 struct stat32 *p32, s32; 1164 struct stat *p = NULL, s; 1165 1166 p32 = uap->ub; 1167 if (p32) { 1168 sg = stackgap_init(); 1169 p = stackgap_alloc(&sg, sizeof(struct stat)); 1170 uap->ub = (struct stat32 *)p; 1171 } 1172 error = stat(td, (struct stat_args *) uap); 1173 if (error) 1174 return (error); 1175 if (p32) { 1176 error = copyin(p, &s, sizeof(s)); 1177 if (error) 1178 return (error); 1179 copy_stat(&s, &s32); 1180 error = copyout(&s32, p32, sizeof(s32)); 1181 } 1182 return (error); 1183} 1184 1185int 1186ia32_fstat(struct thread *td, struct ia32_fstat_args *uap) 1187{ 1188 int error; 1189 caddr_t sg; 1190 struct stat32 *p32, s32; 1191 struct stat *p = NULL, s; 1192 1193 p32 = uap->ub; 1194 if (p32) { 1195 sg = stackgap_init(); 1196 p = stackgap_alloc(&sg, sizeof(struct stat)); 1197 uap->ub = (struct stat32 *)p; 1198 } 1199 error = fstat(td, (struct fstat_args *) uap); 1200 if (error) 1201 return (error); 1202 if (p32) { 1203 error = copyin(p, &s, sizeof(s)); 1204 if (error) 1205 return (error); 1206 copy_stat(&s, &s32); 1207 error = copyout(&s32, p32, sizeof(s32)); 1208 } 1209 return (error); 1210} 1211 1212int 1213ia32_lstat(struct thread *td, struct ia32_lstat_args *uap) 1214{ 1215 int error; 1216 caddr_t sg; 1217 struct stat32 *p32, s32; 1218 struct stat *p = NULL, s; 1219 1220 p32 = uap->ub; 1221 if (p32) { 1222 sg = stackgap_init(); 1223 p = stackgap_alloc(&sg, sizeof(struct stat)); 1224 uap->ub = (struct stat32 *)p; 1225 } 1226 error = lstat(td, (struct lstat_args *) uap); 1227 if (error) 1228 return (error); 1229 if (p32) { 1230 error = copyin(p, &s, sizeof(s)); 1231 if (error) 1232 return (error); 1233 copy_stat(&s, &s32); 1234 error = copyout(&s32, p32, sizeof(s32)); 1235 } 1236 return (error); 1237} 1238 1239/* 1240 * MPSAFE 1241 */ 1242int 1243ia32_sysctl(struct thread *td, struct ia32_sysctl_args *uap) 1244{ 1245 int error, name[CTL_MAXNAME]; 1246 size_t j, oldlen; 1247 1248 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2) 1249 return (EINVAL); 1250 1251 error = copyin(uap->name, &name, uap->namelen * sizeof(int)); 1252 if (error) 1253 return (error); 1254 1255 mtx_lock(&Giant); 1256 1257 if (uap->oldlenp) 1258 oldlen = fuword32(uap->oldlenp); 1259 else 1260 oldlen = 0; 1261 error = userland_sysctl(td, name, uap->namelen, 1262 uap->old, &oldlen, 1, 1263 uap->new, uap->newlen, &j); 1264 if (error && error != ENOMEM) 1265 goto done2; 1266 if (uap->oldlenp) { 1267 suword32(uap->oldlenp, j); 1268 } 1269done2: 1270 mtx_unlock(&Giant); 1271 return (error); 1272} 1273 1274struct sigaction32 { 1275 u_int32_t sa_u; 1276 int sa_flags; 1277 sigset_t sa_mask; 1278}; 1279 1280int 1281ia32_sigaction(struct thread *td, struct ia32_sigaction_args *uap) 1282{ 1283 int error; 1284 caddr_t sg; 1285 struct sigaction32 *p32, *op32, s32; 1286 struct sigaction *p = NULL, *op = NULL, s; 1287 1288 p32 = uap->act; 1289 if (p32) { 1290 sg = stackgap_init(); 1291 p = stackgap_alloc(&sg, sizeof(struct sigaction)); 1292 uap->act = (struct sigaction32 *)p; 1293 error = copyin(p32, &s32, sizeof(s32)); 1294 if (error) 1295 return (error); 1296 s.sa_handler = PTRIN(s32.sa_u); 1297 CP(s32, s, sa_flags); 1298 CP(s32, s, sa_mask); 1299 error = copyout(&s, p, sizeof(s)); 1300 if (error) 1301 return (error); 1302 } 1303 op32 = uap->oact; 1304 if (op32) { 1305 sg = stackgap_init(); 1306 op = stackgap_alloc(&sg, sizeof(struct sigaction)); 1307 uap->oact = (struct sigaction32 *)op; 1308 } 1309 error = sigaction(td, (struct sigaction_args *) uap); 1310 if (error) 1311 return (error); 1312 if (op32) { 1313 error = copyin(op, &s, sizeof(s)); 1314 if (error) 1315 return (error); 1316 s32.sa_u = PTROUT(s.sa_handler); 1317 CP(s, s32, sa_flags); 1318 CP(s, s32, sa_mask); 1319 error = copyout(&s32, op32, sizeof(s32)); 1320 } 1321 return (error); 1322} 1323 1324#if 0 1325 1326int 1327ia32_xxx(struct thread *td, struct ia32_xxx_args *uap) 1328{ 1329 int error; 1330 caddr_t sg; 1331 struct yyy32 *p32, s32; 1332 struct yyy *p = NULL, s; 1333 1334 p32 = uap->zzz; 1335 if (p32) { 1336 sg = stackgap_init(); 1337 p = stackgap_alloc(&sg, sizeof(struct yyy)); 1338 uap->zzz = (struct yyy32 *)p; 1339 error = copyin(p32, &s32, sizeof(s32)); 1340 if (error) 1341 return (error); 1342 /* translate in */ 1343 error = copyout(&s, p, sizeof(s)); 1344 if (error) 1345 return (error); 1346 } 1347 error = xxx(td, (struct xxx_args *) uap); 1348 if (error) 1349 return (error); 1350 if (p32) { 1351 error = copyin(p, &s, sizeof(s)); 1352 if (error) 1353 return (error); 1354 /* translate out */ 1355 error = copyout(&s32, p32, sizeof(s32)); 1356 } 1357 return (error); 1358} 1359 1360#endif 1361