Annotation of src/sys/compat/linux/common/linux_misc.c, Revision 1.151.2.4
1.151.2.4! yamt 1: /* $NetBSD: linux_misc.c,v 1.151.2.3 2006/06/26 12:46:18 yamt Exp $ */
1.47 erh 2:
3: /*-
1.56 thorpej 4: * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc.
1.47 erh 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
1.56 thorpej 8: * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe
9: * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center.
1.47 erh 10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
1.1 fvdl 38: */
39:
40: /*
41: * Linux compatibility module. Try to deal with various Linux system calls.
42: */
43:
1.47 erh 44: /*
45: * These functions have been moved to multiarch to allow
1.135 perry 46: * selection of which machines include them to be
1.47 erh 47: * determined by the individual files.linux_<arch> files.
48: *
49: * Function in multiarch:
50: * linux_sys_break : linux_break.c
51: * linux_sys_alarm : linux_misc_notalpha.c
1.57 thorpej 52: * linux_sys_getresgid : linux_misc_notalpha.c
1.47 erh 53: * linux_sys_nice : linux_misc_notalpha.c
54: * linux_sys_readdir : linux_misc_notalpha.c
1.57 thorpej 55: * linux_sys_setresgid : linux_misc_notalpha.c
1.47 erh 56: * linux_sys_time : linux_misc_notalpha.c
57: * linux_sys_utime : linux_misc_notalpha.c
58: * linux_sys_waitpid : linux_misc_notalpha.c
59: * linux_sys_old_mmap : linux_oldmmap.c
60: * linux_sys_oldolduname : linux_oldolduname.c
61: * linux_sys_oldselect : linux_oldselect.c
62: * linux_sys_olduname : linux_olduname.c
63: * linux_sys_pipe : linux_pipe.c
64: */
1.95 lukem 65:
66: #include <sys/cdefs.h>
1.151.2.4! yamt 67: __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.151.2.3 2006/06/26 12:46:18 yamt Exp $");
1.47 erh 68:
1.1 fvdl 69: #include <sys/param.h>
70: #include <sys/systm.h>
71: #include <sys/namei.h>
72: #include <sys/proc.h>
1.29 mycroft 73: #include <sys/dirent.h>
1.1 fvdl 74: #include <sys/file.h>
75: #include <sys/stat.h>
76: #include <sys/filedesc.h>
77: #include <sys/ioctl.h>
78: #include <sys/kernel.h>
79: #include <sys/malloc.h>
80: #include <sys/mbuf.h>
81: #include <sys/mman.h>
82: #include <sys/mount.h>
1.67 erh 83: #include <sys/reboot.h>
1.1 fvdl 84: #include <sys/resource.h>
85: #include <sys/resourcevar.h>
86: #include <sys/signal.h>
87: #include <sys/signalvar.h>
88: #include <sys/socket.h>
89: #include <sys/time.h>
90: #include <sys/times.h>
91: #include <sys/vnode.h>
92: #include <sys/uio.h>
93: #include <sys/wait.h>
94: #include <sys/utsname.h>
95: #include <sys/unistd.h>
1.75 jdolecek 96: #include <sys/swap.h> /* for SWAP_ON */
97: #include <sys/sysctl.h> /* for KERN_DOMAINNAME */
1.151.2.2 yamt 98: #include <sys/kauth.h>
1.1 fvdl 99:
1.73 jdolecek 100: #include <sys/ptrace.h>
101: #include <machine/ptrace.h>
102:
1.116 thorpej 103: #include <sys/sa.h>
1.1 fvdl 104: #include <sys/syscallargs.h>
105:
1.143 manu 106: #include <compat/linux/common/linux_machdep.h>
1.49 christos 107: #include <compat/linux/common/linux_types.h>
108: #include <compat/linux/common/linux_signal.h>
109:
1.1 fvdl 110: #include <compat/linux/linux_syscallargs.h>
1.49 christos 111:
112: #include <compat/linux/common/linux_fcntl.h>
113: #include <compat/linux/common/linux_mmap.h>
114: #include <compat/linux/common/linux_dirent.h>
115: #include <compat/linux/common/linux_util.h>
116: #include <compat/linux/common/linux_misc.h>
1.150 manu 117: #ifndef COMPAT_LINUX32
118: #include <compat/linux/common/linux_limit.h>
119: #endif
1.62 tron 120: #include <compat/linux/common/linux_ptrace.h>
1.67 erh 121: #include <compat/linux/common/linux_reboot.h>
1.84 manu 122: #include <compat/linux/common/linux_emuldata.h>
1.49 christos 123:
1.150 manu 124: #ifndef COMPAT_LINUX32
1.73 jdolecek 125: const int linux_ptrace_request_map[] = {
1.62 tron 126: LINUX_PTRACE_TRACEME, PT_TRACE_ME,
127: LINUX_PTRACE_PEEKTEXT, PT_READ_I,
128: LINUX_PTRACE_PEEKDATA, PT_READ_D,
129: LINUX_PTRACE_POKETEXT, PT_WRITE_I,
130: LINUX_PTRACE_POKEDATA, PT_WRITE_D,
131: LINUX_PTRACE_CONT, PT_CONTINUE,
132: LINUX_PTRACE_KILL, PT_KILL,
133: LINUX_PTRACE_ATTACH, PT_ATTACH,
134: LINUX_PTRACE_DETACH, PT_DETACH,
1.150 manu 135: # ifdef PT_STEP
1.73 jdolecek 136: LINUX_PTRACE_SINGLESTEP, PT_STEP,
1.150 manu 137: # endif
1.62 tron 138: -1
139: };
1.1 fvdl 140:
1.132 jdolecek 141: const struct linux_mnttypes linux_fstypes[] = {
1.101 christos 142: { MOUNT_FFS, LINUX_DEFAULT_SUPER_MAGIC },
143: { MOUNT_NFS, LINUX_NFS_SUPER_MAGIC },
144: { MOUNT_MFS, LINUX_DEFAULT_SUPER_MAGIC },
145: { MOUNT_MSDOS, LINUX_MSDOS_SUPER_MAGIC },
146: { MOUNT_LFS, LINUX_DEFAULT_SUPER_MAGIC },
147: { MOUNT_FDESC, LINUX_DEFAULT_SUPER_MAGIC },
148: { MOUNT_PORTAL, LINUX_DEFAULT_SUPER_MAGIC },
149: { MOUNT_NULL, LINUX_DEFAULT_SUPER_MAGIC },
1.135 perry 150: { MOUNT_OVERLAY, LINUX_DEFAULT_SUPER_MAGIC },
1.101 christos 151: { MOUNT_UMAP, LINUX_DEFAULT_SUPER_MAGIC },
152: { MOUNT_KERNFS, LINUX_DEFAULT_SUPER_MAGIC },
153: { MOUNT_PROCFS, LINUX_PROC_SUPER_MAGIC },
154: { MOUNT_AFS, LINUX_DEFAULT_SUPER_MAGIC },
155: { MOUNT_CD9660, LINUX_ISOFS_SUPER_MAGIC },
156: { MOUNT_UNION, LINUX_DEFAULT_SUPER_MAGIC },
157: { MOUNT_ADOSFS, LINUX_ADFS_SUPER_MAGIC },
158: { MOUNT_EXT2FS, LINUX_EXT2_SUPER_MAGIC },
159: { MOUNT_CFS, LINUX_DEFAULT_SUPER_MAGIC },
160: { MOUNT_CODA, LINUX_CODA_SUPER_MAGIC },
161: { MOUNT_FILECORE, LINUX_DEFAULT_SUPER_MAGIC },
162: { MOUNT_NTFS, LINUX_DEFAULT_SUPER_MAGIC },
1.134 christos 163: { MOUNT_SMBFS, LINUX_SMB_SUPER_MAGIC },
1.140 jmmv 164: { MOUNT_PTYFS, LINUX_DEVPTS_SUPER_MAGIC },
165: { MOUNT_TMPFS, LINUX_DEFAULT_SUPER_MAGIC }
1.101 christos 166: };
1.132 jdolecek 167: const int linux_fstypes_cnt = sizeof(linux_fstypes) / sizeof(linux_fstypes[0]);
1.101 christos 168:
1.150 manu 169: # ifdef DEBUG_LINUX
1.104 christos 170: #define DPRINTF(a) uprintf a
1.150 manu 171: # else
1.104 christos 172: #define DPRINTF(a)
1.150 manu 173: # endif
1.104 christos 174:
1.47 erh 175: /* Local linux_misc.c functions: */
1.150 manu 176: # ifndef __amd64__
1.123 christos 177: static void bsd_to_linux_statfs __P((const struct statvfs *,
178: struct linux_statfs *));
1.150 manu 179: # endif
1.118 christos 180: static void linux_to_bsd_mmap_args __P((struct sys_mmap_args *,
181: const struct linux_sys_mmap_args *));
1.128 jdolecek 182: static int linux_mmap __P((struct lwp *, struct linux_sys_mmap_args *,
183: register_t *, off_t));
184:
1.26 christos 185:
1.1 fvdl 186: /*
187: * The information on a terminated (or stopped) process needs
188: * to be converted in order for Linux binaries to get a valid signal
189: * number out of it.
190: */
1.47 erh 191: void
1.52 christos 192: bsd_to_linux_wstat(st)
193: int *st;
1.1 fvdl 194: {
1.21 mycroft 195:
1.52 christos 196: int sig;
197:
198: if (WIFSIGNALED(*st)) {
199: sig = WTERMSIG(*st);
200: if (sig >= 0 && sig < NSIG)
1.105 christos 201: *st= (*st& ~0177) | native_to_linux_signo[sig];
1.52 christos 202: } else if (WIFSTOPPED(*st)) {
203: sig = WSTOPSIG(*st);
204: if (sig >= 0 && sig < NSIG)
1.105 christos 205: *st = (*st & ~0xff00) |
206: (native_to_linux_signo[sig] << 8);
1.52 christos 207: }
1.1 fvdl 208: }
209:
210: /*
1.133 erh 211: * wait4(2). Passed on to the NetBSD call, surrounded by code to
212: * reserve some space for a NetBSD-style wait status, and converting
213: * it to what Linux wants.
1.1 fvdl 214: */
215: int
1.116 thorpej 216: linux_sys_wait4(l, v, retval)
217: struct lwp *l;
1.20 thorpej 218: void *v;
219: register_t *retval;
220: {
1.21 mycroft 221: struct linux_sys_wait4_args /* {
1.1 fvdl 222: syscallarg(int) pid;
223: syscallarg(int *) status;
224: syscallarg(int) options;
225: syscallarg(struct rusage *) rusage;
1.20 thorpej 226: } */ *uap = v;
1.116 thorpej 227: struct proc *p = l->l_proc;
1.21 mycroft 228: struct sys_wait4_args w4a;
1.55 thorpej 229: int error, *status, tstat, options, linux_options;
1.1 fvdl 230: caddr_t sg;
231:
1.16 fvdl 232: if (SCARG(uap, status) != NULL) {
1.102 christos 233: sg = stackgap_init(p, 0);
234: status = (int *) stackgap_alloc(p, &sg, sizeof *status);
1.16 fvdl 235: } else
236: status = NULL;
1.1 fvdl 237:
1.55 thorpej 238: linux_options = SCARG(uap, options);
239: options = 0;
1.133 erh 240: if (linux_options & ~(LINUX_WAIT4_KNOWNFLAGS))
1.55 thorpej 241: return (EINVAL);
242:
243: if (linux_options & LINUX_WAIT4_WNOHANG)
244: options |= WNOHANG;
245: if (linux_options & LINUX_WAIT4_WUNTRACED)
246: options |= WUNTRACED;
1.93 thorpej 247: if (linux_options & LINUX_WAIT4_WALL)
248: options |= WALLSIG;
1.55 thorpej 249: if (linux_options & LINUX_WAIT4_WCLONE)
250: options |= WALTSIG;
1.150 manu 251: # ifdef DIAGNOSTIC
1.133 erh 252: if (linux_options & LINUX_WAIT4_WNOTHREAD)
253: printf("WARNING: %s: linux process %d.%d called "
254: "waitpid with __WNOTHREAD set!",
255: __FILE__, p->p_pid, l->l_lid);
256:
1.150 manu 257: # endif
1.55 thorpej 258:
1.1 fvdl 259: SCARG(&w4a, pid) = SCARG(uap, pid);
260: SCARG(&w4a, status) = status;
1.55 thorpej 261: SCARG(&w4a, options) = options;
1.1 fvdl 262: SCARG(&w4a, rusage) = SCARG(uap, rusage);
263:
1.116 thorpej 264: if ((error = sys_wait4(l, &w4a, retval)))
1.1 fvdl 265: return error;
266:
1.80 jdolecek 267: sigdelset(&p->p_sigctx.ps_siglist, SIGCHLD);
1.18 fvdl 268:
1.16 fvdl 269: if (status != NULL) {
270: if ((error = copyin(status, &tstat, sizeof tstat)))
271: return error;
272:
273: bsd_to_linux_wstat(&tstat);
274: return copyout(&tstat, SCARG(uap, status), sizeof tstat);
275: }
1.1 fvdl 276:
1.16 fvdl 277: return 0;
1.1 fvdl 278: }
279:
280: /*
281: * Linux brk(2). The check if the new address is >= the old one is
282: * done in the kernel in Linux. NetBSD does it in the library.
283: */
284: int
1.116 thorpej 285: linux_sys_brk(l, v, retval)
286: struct lwp *l;
1.20 thorpej 287: void *v;
288: register_t *retval;
289: {
1.21 mycroft 290: struct linux_sys_brk_args /* {
1.1 fvdl 291: syscallarg(char *) nsize;
1.20 thorpej 292: } */ *uap = v;
1.116 thorpej 293: struct proc *p = l->l_proc;
1.1 fvdl 294: char *nbrk = SCARG(uap, nsize);
1.21 mycroft 295: struct sys_obreak_args oba;
1.1 fvdl 296: struct vmspace *vm = p->p_vmspace;
1.85 manu 297: struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata;
1.84 manu 298:
1.1 fvdl 299: SCARG(&oba, nsize) = nbrk;
300:
1.116 thorpej 301: if ((caddr_t) nbrk > vm->vm_daddr && sys_obreak(l, &oba, retval) == 0)
1.127 jdolecek 302: ed->s->p_break = (char*)nbrk;
1.135 perry 303: else
1.127 jdolecek 304: nbrk = ed->s->p_break;
1.85 manu 305:
306: retval[0] = (register_t)nbrk;
1.1 fvdl 307:
308: return 0;
309: }
310:
1.150 manu 311: # ifndef __amd64__
1.1 fvdl 312: /*
1.131 jdolecek 313: * Convert NetBSD statvfs structure to Linux statfs structure.
314: * Linux doesn't have f_flag, and we can't set f_frsize due
315: * to glibc statvfs() bug (see below).
1.2 fvdl 316: */
317: static void
318: bsd_to_linux_statfs(bsp, lsp)
1.123 christos 319: const struct statvfs *bsp;
1.2 fvdl 320: struct linux_statfs *lsp;
321: {
1.101 christos 322: int i;
323:
1.132 jdolecek 324: for (i = 0; i < linux_fstypes_cnt; i++) {
325: if (strcmp(bsp->f_fstypename, linux_fstypes[i].bsd) == 0) {
326: lsp->l_ftype = linux_fstypes[i].linux;
1.101 christos 327: break;
1.132 jdolecek 328: }
329: }
1.101 christos 330:
1.132 jdolecek 331: if (i == linux_fstypes_cnt) {
1.104 christos 332: DPRINTF(("unhandled fstype in linux emulation: %s\n",
333: bsp->f_fstypename));
1.101 christos 334: lsp->l_ftype = LINUX_DEFAULT_SUPER_MAGIC;
335: }
1.21 mycroft 336:
1.131 jdolecek 337: /*
338: * The sizes are expressed in number of blocks. The block
339: * size used for the size is f_frsize for POSIX-compliant
340: * statvfs. Linux statfs uses f_bsize as the block size
341: * (f_frsize used to not be available in Linux struct statfs).
342: * However, glibc 2.3.3 statvfs() wrapper fails to adjust the block
343: * counts for different f_frsize if f_frsize is provided by the kernel.
344: * POSIX conforming apps thus get wrong size if f_frsize
345: * is different to f_bsize. Thus, we just pretend we don't
346: * support f_frsize.
347: */
348:
1.129 jdolecek 349: lsp->l_fbsize = bsp->f_frsize;
1.131 jdolecek 350: lsp->l_ffrsize = 0; /* compat */
1.2 fvdl 351: lsp->l_fblocks = bsp->f_blocks;
352: lsp->l_fbfree = bsp->f_bfree;
353: lsp->l_fbavail = bsp->f_bavail;
354: lsp->l_ffiles = bsp->f_files;
355: lsp->l_fffree = bsp->f_ffree;
1.101 christos 356: /* Linux sets the fsid to 0..., we don't */
1.123 christos 357: lsp->l_ffsid.val[0] = bsp->f_fsidx.__fsid_val[0];
358: lsp->l_ffsid.val[1] = bsp->f_fsidx.__fsid_val[1];
1.129 jdolecek 359: lsp->l_fnamelen = bsp->f_namemax;
1.101 christos 360: (void)memset(lsp->l_fspare, 0, sizeof(lsp->l_fspare));
1.2 fvdl 361: }
362:
363: /*
364: * Implement the fs stat functions. Straightforward.
1.1 fvdl 365: */
366: int
1.116 thorpej 367: linux_sys_statfs(l, v, retval)
368: struct lwp *l;
1.20 thorpej 369: void *v;
370: register_t *retval;
371: {
1.21 mycroft 372: struct linux_sys_statfs_args /* {
1.53 christos 373: syscallarg(const char *) path;
1.1 fvdl 374: syscallarg(struct linux_statfs *) sp;
1.20 thorpej 375: } */ *uap = v;
1.116 thorpej 376: struct proc *p = l->l_proc;
1.151.2.2 yamt 377: struct statvfs *btmp, *bsp;
1.2 fvdl 378: struct linux_statfs ltmp;
1.124 christos 379: struct sys_statvfs1_args bsa;
1.2 fvdl 380: caddr_t sg;
381: int error;
382:
1.102 christos 383: sg = stackgap_init(p, 0);
1.151.2.2 yamt 384: bsp = stackgap_alloc(p, &sg, sizeof (struct statvfs));
1.2 fvdl 385:
1.147 christos 386: CHECK_ALT_EXIST(l, &sg, SCARG(uap, path));
1.2 fvdl 387:
388: SCARG(&bsa, path) = SCARG(uap, path);
389: SCARG(&bsa, buf) = bsp;
1.125 christos 390: SCARG(&bsa, flags) = ST_WAIT;
1.2 fvdl 391:
1.125 christos 392: if ((error = sys_statvfs1(l, &bsa, retval)))
1.2 fvdl 393: return error;
394:
1.151.2.2 yamt 395: btmp = STATVFSBUF_GET();
396: error = copyin(bsp, btmp, sizeof(*btmp));
397: if (error) {
398: goto out;
399: }
400: bsd_to_linux_statfs(btmp, <mp);
401: error = copyout(<mp, SCARG(uap, sp), sizeof ltmp);
402: out:
403: STATVFSBUF_PUT(btmp);
404: return error;
1.1 fvdl 405: }
406:
407: int
1.116 thorpej 408: linux_sys_fstatfs(l, v, retval)
409: struct lwp *l;
1.20 thorpej 410: void *v;
411: register_t *retval;
412: {
1.21 mycroft 413: struct linux_sys_fstatfs_args /* {
1.2 fvdl 414: syscallarg(int) fd;
1.1 fvdl 415: syscallarg(struct linux_statfs *) sp;
1.20 thorpej 416: } */ *uap = v;
1.116 thorpej 417: struct proc *p = l->l_proc;
1.151.2.2 yamt 418: struct statvfs *btmp, *bsp;
1.2 fvdl 419: struct linux_statfs ltmp;
1.125 christos 420: struct sys_fstatvfs1_args bsa;
1.2 fvdl 421: caddr_t sg;
422: int error;
423:
1.102 christos 424: sg = stackgap_init(p, 0);
1.151.2.2 yamt 425: bsp = stackgap_alloc(p, &sg, sizeof (struct statvfs));
1.2 fvdl 426:
427: SCARG(&bsa, fd) = SCARG(uap, fd);
428: SCARG(&bsa, buf) = bsp;
1.125 christos 429: SCARG(&bsa, flags) = ST_WAIT;
1.2 fvdl 430:
1.125 christos 431: if ((error = sys_fstatvfs1(l, &bsa, retval)))
1.2 fvdl 432: return error;
433:
1.151.2.2 yamt 434: btmp = STATVFSBUF_GET();
435: error = copyin(bsp, btmp, sizeof(*btmp));
436: if (error) {
437: goto out;
438: }
439: bsd_to_linux_statfs(btmp, <mp);
440: error = copyout(<mp, SCARG(uap, sp), sizeof ltmp);
441: out:
442: STATVFSBUF_PUT(btmp);
443: return error;
1.1 fvdl 444: }
1.150 manu 445: # endif /* !__amd64__ */
1.82 fvdl 446:
1.1 fvdl 447: /*
448: * uname(). Just copy the info from the various strings stored in the
449: * kernel, and put it in the Linux utsname structure. That structure
450: * is almost the same as the NetBSD one, only it has fields 65 characters
451: * long, and an extra domainname field.
452: */
453: int
1.116 thorpej 454: linux_sys_uname(l, v, retval)
455: struct lwp *l;
1.20 thorpej 456: void *v;
457: register_t *retval;
458: {
1.21 mycroft 459: struct linux_sys_uname_args /* {
1.1 fvdl 460: syscallarg(struct linux_utsname *) up;
1.20 thorpej 461: } */ *uap = v;
1.15 mycroft 462: struct linux_utsname luts;
1.1 fvdl 463:
1.82 fvdl 464: strncpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname));
1.15 mycroft 465: strncpy(luts.l_nodename, hostname, sizeof(luts.l_nodename));
1.82 fvdl 466: strncpy(luts.l_release, linux_release, sizeof(luts.l_release));
467: strncpy(luts.l_version, linux_version, sizeof(luts.l_version));
1.150 manu 468: # ifdef LINUX_UNAME_ARCH
1.142 manu 469: strncpy(luts.l_machine, LINUX_UNAME_ARCH, sizeof(luts.l_machine));
1.150 manu 470: # else
1.15 mycroft 471: strncpy(luts.l_machine, machine, sizeof(luts.l_machine));
1.150 manu 472: # endif
1.15 mycroft 473: strncpy(luts.l_domainname, domainname, sizeof(luts.l_domainname));
474:
475: return copyout(&luts, SCARG(uap, up), sizeof(luts));
476: }
477:
1.47 erh 478: /* Used directly on: alpha, mips, ppc, sparc, sparc64 */
479: /* Used indirectly on: arm, i386, m68k */
1.1 fvdl 480:
481: /*
1.47 erh 482: * New type Linux mmap call.
483: * Only called directly on machines with >= 6 free regs.
1.1 fvdl 484: */
485: int
1.116 thorpej 486: linux_sys_mmap(l, v, retval)
487: struct lwp *l;
1.20 thorpej 488: void *v;
489: register_t *retval;
490: {
1.21 mycroft 491: struct linux_sys_mmap_args /* {
1.47 erh 492: syscallarg(unsigned long) addr;
493: syscallarg(size_t) len;
494: syscallarg(int) prot;
495: syscallarg(int) flags;
496: syscallarg(int) fd;
1.94 manu 497: syscallarg(linux_off_t) offset;
1.20 thorpej 498: } */ *uap = v;
1.118 christos 499:
1.115 christos 500: if (SCARG(uap, offset) & PAGE_MASK)
501: return EINVAL;
502:
1.128 jdolecek 503: return linux_mmap(l, uap, retval, SCARG(uap, offset));
1.118 christos 504: }
505:
506: /*
507: * Guts of most architectures' mmap64() implementations. This shares
508: * its list of arguments with linux_sys_mmap().
509: *
510: * The difference in linux_sys_mmap2() is that "offset" is actually
511: * (offset / pagesize), not an absolute byte count. This translation
512: * to pagesize offsets is done inside glibc between the mmap64() call
513: * point, and the actual syscall.
514: */
515: int
516: linux_sys_mmap2(l, v, retval)
517: struct lwp *l;
518: void *v;
519: register_t *retval;
520: {
521: struct linux_sys_mmap2_args /* {
522: syscallarg(unsigned long) addr;
523: syscallarg(size_t) len;
524: syscallarg(int) prot;
525: syscallarg(int) flags;
526: syscallarg(int) fd;
527: syscallarg(linux_off_t) offset;
528: } */ *uap = v;
1.128 jdolecek 529:
530: return linux_mmap(l, uap, retval,
531: ((off_t)SCARG(uap, offset)) << PAGE_SHIFT);
532: }
533:
534: /*
535: * Massage arguments and call system mmap(2).
536: */
537: static int
538: linux_mmap(l, uap, retval, offset)
539: struct lwp *l;
540: struct linux_sys_mmap_args *uap;
541: register_t *retval;
542: off_t offset;
543: {
1.118 christos 544: struct sys_mmap_args cma;
1.128 jdolecek 545: int error;
546: size_t mmoff=0;
547:
548: if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN) {
549: /*
550: * Request for stack-like memory segment. On linux, this
551: * works by mmap()ping (small) segment, which is automatically
552: * extended when page fault happens below the currently
553: * allocated area. We emulate this by allocating (typically
554: * bigger) segment sized at current stack size limit, and
555: * offsetting the requested and returned address accordingly.
556: * Since physical pages are only allocated on-demand, this
557: * is effectively identical.
558: */
559: rlim_t ssl = l->l_proc->p_rlimit[RLIMIT_STACK].rlim_cur;
560:
561: if (SCARG(uap, len) < ssl) {
562: /* Compute the address offset */
563: mmoff = round_page(ssl) - SCARG(uap, len);
564:
565: if (SCARG(uap, addr))
566: SCARG(uap, addr) -= mmoff;
567:
568: SCARG(uap, len) = (size_t) ssl;
569: }
570: }
1.118 christos 571:
572: linux_to_bsd_mmap_args(&cma, uap);
1.128 jdolecek 573: SCARG(&cma, pos) = offset;
574:
575: error = sys_mmap(l, &cma, retval);
576: if (error)
577: return (error);
578:
579: /* Shift the returned address for stack-like segment if necessary */
580: if (SCARG(uap, flags) & LINUX_MAP_GROWSDOWN && mmoff)
581: retval[0] += mmoff;
1.118 christos 582:
1.128 jdolecek 583: return (0);
1.118 christos 584: }
585:
586: static void
587: linux_to_bsd_mmap_args(cma, uap)
588: struct sys_mmap_args *cma;
589: const struct linux_sys_mmap_args *uap;
590: {
1.119 christos 591: int flags = MAP_TRYFIXED, fl = SCARG(uap, flags);
1.135 perry 592:
1.103 christos 593: flags |= cvtto_bsd_mask(fl, LINUX_MAP_SHARED, MAP_SHARED);
594: flags |= cvtto_bsd_mask(fl, LINUX_MAP_PRIVATE, MAP_PRIVATE);
595: flags |= cvtto_bsd_mask(fl, LINUX_MAP_FIXED, MAP_FIXED);
596: flags |= cvtto_bsd_mask(fl, LINUX_MAP_ANON, MAP_ANON);
1.47 erh 597: /* XXX XAX ERH: Any other flags here? There are more defined... */
598:
1.118 christos 599: SCARG(cma, addr) = (void *)SCARG(uap, addr);
600: SCARG(cma, len) = SCARG(uap, len);
601: SCARG(cma, prot) = SCARG(uap, prot);
602: if (SCARG(cma, prot) & VM_PROT_WRITE) /* XXX */
603: SCARG(cma, prot) |= VM_PROT_READ;
604: SCARG(cma, flags) = flags;
605: SCARG(cma, fd) = flags & MAP_ANON ? -1 : SCARG(uap, fd);
606: SCARG(cma, pad) = 0;
1.97 christos 607: }
608:
1.148 yamt 609: #define LINUX_MREMAP_MAYMOVE 1
610: #define LINUX_MREMAP_FIXED 2
611:
1.34 mycroft 612: int
1.116 thorpej 613: linux_sys_mremap(l, v, retval)
614: struct lwp *l;
1.34 mycroft 615: void *v;
616: register_t *retval;
617: {
618: struct linux_sys_mremap_args /* {
619: syscallarg(void *) old_address;
620: syscallarg(size_t) old_size;
621: syscallarg(size_t) new_size;
622: syscallarg(u_long) flags;
623: } */ *uap = v;
1.148 yamt 624:
625: struct proc *p;
626: struct vm_map *map;
627: vaddr_t oldva;
628: vaddr_t newva;
629: size_t oldsize;
630: size_t newsize;
631: int flags;
632: int uvmflags;
1.42 thorpej 633: int error;
634:
1.148 yamt 635: flags = SCARG(uap, flags);
636: oldva = (vaddr_t)SCARG(uap, old_address);
637: oldsize = round_page(SCARG(uap, old_size));
638: newsize = round_page(SCARG(uap, new_size));
1.149 yamt 639: if ((flags & ~(LINUX_MREMAP_FIXED|LINUX_MREMAP_MAYMOVE)) != 0) {
640: error = EINVAL;
641: goto done;
642: }
1.148 yamt 643: if ((flags & LINUX_MREMAP_FIXED) != 0) {
1.149 yamt 644: if ((flags & LINUX_MREMAP_MAYMOVE) == 0) {
645: error = EINVAL;
646: goto done;
647: }
1.148 yamt 648: #if 0 /* notyet */
649: newva = SCARG(uap, new_address);
650: uvmflags = UVM_MREMAP_FIXED;
651: #else /* notyet */
652: error = EOPNOTSUPP;
653: goto done;
654: #endif /* notyet */
655: } else if ((flags & LINUX_MREMAP_MAYMOVE) != 0) {
656: uvmflags = 0;
657: } else {
658: newva = oldva;
659: uvmflags = UVM_MREMAP_FIXED;
1.42 thorpej 660: }
1.148 yamt 661: p = l->l_proc;
662: map = &p->p_vmspace->vm_map;
663: error = uvm_mremap(map, oldva, oldsize, map, &newva, newsize, p,
664: uvmflags);
1.42 thorpej 665:
1.148 yamt 666: done:
667: *retval = (error != 0) ? 0 : (register_t)newva;
668: return error;
1.24 fvdl 669: }
670:
671: int
1.116 thorpej 672: linux_sys_msync(l, v, retval)
673: struct lwp *l;
1.24 fvdl 674: void *v;
675: register_t *retval;
676: {
677: struct linux_sys_msync_args /* {
678: syscallarg(caddr_t) addr;
679: syscallarg(int) len;
680: syscallarg(int) fl;
681: } */ *uap = v;
682:
1.36 fvdl 683: struct sys___msync13_args bma;
1.24 fvdl 684:
685: /* flags are ignored */
686: SCARG(&bma, addr) = SCARG(uap, addr);
687: SCARG(&bma, len) = SCARG(uap, len);
1.36 fvdl 688: SCARG(&bma, flags) = SCARG(uap, fl);
1.24 fvdl 689:
1.116 thorpej 690: return sys___msync13(l, &bma, retval);
1.103 christos 691: }
692:
693: int
1.116 thorpej 694: linux_sys_mprotect(l, v, retval)
695: struct lwp *l;
1.103 christos 696: void *v;
697: register_t *retval;
698: {
699: struct linux_sys_mprotect_args /* {
700: syscallarg(const void *) start;
701: syscallarg(unsigned long) len;
702: syscallarg(int) prot;
703: } */ *uap = v;
704: struct vm_map_entry *entry;
1.141 chs 705: struct vm_map *map;
706: struct proc *p;
707: vaddr_t end, start, len, stacklim;
708: int prot, grows;
1.103 christos 709:
1.141 chs 710: start = (vaddr_t)SCARG(uap, start);
1.103 christos 711: len = round_page(SCARG(uap, len));
1.141 chs 712: prot = SCARG(uap, prot);
713: grows = prot & (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP);
714: prot &= ~grows;
1.103 christos 715: end = start + len;
716:
1.141 chs 717: if (start & PAGE_MASK)
718: return EINVAL;
1.103 christos 719: if (end < start)
720: return EINVAL;
1.141 chs 721: if (end == start)
1.103 christos 722: return 0;
723:
1.141 chs 724: if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
725: return EINVAL;
726: if (grows == (LINUX_PROT_GROWSDOWN | LINUX_PROT_GROWSUP))
1.103 christos 727: return EINVAL;
728:
1.141 chs 729: p = l->l_proc;
730: map = &p->p_vmspace->vm_map;
1.103 christos 731: vm_map_lock(map);
1.150 manu 732: # ifdef notdef
1.103 christos 733: VM_MAP_RANGE_CHECK(map, start, end);
1.150 manu 734: # endif
1.103 christos 735: if (!uvm_map_lookup_entry(map, start, &entry) || entry->start > start) {
736: vm_map_unlock(map);
1.126 jdolecek 737: return ENOMEM;
1.103 christos 738: }
1.141 chs 739:
740: /*
741: * Approximate the behaviour of PROT_GROWS{DOWN,UP}.
742: */
743:
744: stacklim = (vaddr_t)p->p_limit->pl_rlimit[RLIMIT_STACK].rlim_cur;
745: if (grows & LINUX_PROT_GROWSDOWN) {
746: if (USRSTACK - stacklim <= start && start < USRSTACK) {
747: start = USRSTACK - stacklim;
748: } else {
749: start = entry->start;
750: }
751: } else if (grows & LINUX_PROT_GROWSUP) {
752: if (USRSTACK <= end && end < USRSTACK + stacklim) {
753: end = USRSTACK + stacklim;
754: } else {
755: end = entry->end;
756: }
757: }
1.103 christos 758: vm_map_unlock(map);
759: return uvm_map_protect(map, start, end, prot, FALSE);
1.1 fvdl 760: }
761:
762: /*
763: * This code is partly stolen from src/lib/libc/compat-43/times.c
764: */
765:
1.113 jdolecek 766: #define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
1.1 fvdl 767:
768: int
1.116 thorpej 769: linux_sys_times(l, v, retval)
770: struct lwp *l;
1.20 thorpej 771: void *v;
772: register_t *retval;
773: {
1.21 mycroft 774: struct linux_sys_times_args /* {
1.1 fvdl 775: syscallarg(struct times *) tms;
1.20 thorpej 776: } */ *uap = v;
1.116 thorpej 777: struct proc *p = l->l_proc;
1.1 fvdl 778: struct timeval t;
1.151.2.3 yamt 779: int error;
1.1 fvdl 780:
1.112 jdolecek 781: if (SCARG(uap, tms)) {
782: struct linux_tms ltms;
783: struct rusage ru;
784:
785: calcru(p, &ru.ru_utime, &ru.ru_stime, NULL);
786: ltms.ltms_utime = CONVTCK(ru.ru_utime);
787: ltms.ltms_stime = CONVTCK(ru.ru_stime);
1.1 fvdl 788:
1.112 jdolecek 789: ltms.ltms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime);
790: ltms.ltms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime);
1.1 fvdl 791:
1.112 jdolecek 792: if ((error = copyout(<ms, SCARG(uap, tms), sizeof ltms)))
793: return error;
794: }
1.1 fvdl 795:
1.151.2.3 yamt 796: getmicrouptime(&t);
1.1 fvdl 797:
798: retval[0] = ((linux_clock_t)(CONVTCK(t)));
799: return 0;
800: }
1.113 jdolecek 801:
802: #undef CONVTCK
1.1 fvdl 803:
804: /*
805: * Linux 'readdir' call. This code is mostly taken from the
806: * SunOS getdents call (see compat/sunos/sunos_misc.c), though
807: * an attempt has been made to keep it a little cleaner (failing
808: * miserably, because of the cruft needed if count 1 is passed).
809: *
1.17 fvdl 810: * The d_off field should contain the offset of the next valid entry,
811: * but in Linux it has the offset of the entry itself. We emulate
812: * that bug here.
813: *
1.1 fvdl 814: * Read in BSD-style entries, convert them, and copy them out.
815: *
816: * Note that this doesn't handle union-mounted filesystems.
817: */
818: int
1.116 thorpej 819: linux_sys_getdents(l, v, retval)
820: struct lwp *l;
1.20 thorpej 821: void *v;
822: register_t *retval;
823: {
1.47 erh 824: struct linux_sys_getdents_args /* {
1.1 fvdl 825: syscallarg(int) fd;
1.47 erh 826: syscallarg(struct linux_dirent *) dent;
1.1 fvdl 827: syscallarg(unsigned int) count;
1.20 thorpej 828: } */ *uap = v;
1.69 augustss 829: struct dirent *bdp;
1.1 fvdl 830: struct vnode *vp;
1.138 christos 831: caddr_t inp, tbuf; /* BSD-format */
1.26 christos 832: int len, reclen; /* BSD-format */
1.51 fvdl 833: caddr_t outp; /* Linux-format */
1.26 christos 834: int resid, linux_reclen = 0; /* Linux-format */
1.1 fvdl 835: struct file *fp;
836: struct uio auio;
837: struct iovec aiov;
838: struct linux_dirent idb;
839: off_t off; /* true file offset */
1.17 fvdl 840: int buflen, error, eofflag, nbytes, oldcall;
1.1 fvdl 841: struct vattr va;
1.40 fvdl 842: off_t *cookiebuf = NULL, *cookie;
1.22 mycroft 843: int ncookies;
1.1 fvdl 844:
1.54 thorpej 845: /* getvnode() will use the descriptor for us */
1.151.2.4! yamt 846: if ((error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp)) != 0)
1.1 fvdl 847: return (error);
848:
1.54 thorpej 849: if ((fp->f_flag & FREAD) == 0) {
850: error = EBADF;
851: goto out1;
852: }
1.1 fvdl 853:
1.5 mycroft 854: vp = (struct vnode *)fp->f_data;
1.54 thorpej 855: if (vp->v_type != VDIR) {
856: error = EINVAL;
857: goto out1;
858: }
1.1 fvdl 859:
1.151.2.4! yamt 860: if ((error = VOP_GETATTR(vp, &va, l->l_cred, l)))
1.54 thorpej 861: goto out1;
1.1 fvdl 862:
863: nbytes = SCARG(uap, count);
1.17 fvdl 864: if (nbytes == 1) { /* emulating old, broken behaviour */
1.107 christos 865: nbytes = sizeof (idb);
1.5 mycroft 866: buflen = max(va.va_blocksize, nbytes);
1.17 fvdl 867: oldcall = 1;
1.5 mycroft 868: } else {
869: buflen = min(MAXBSIZE, nbytes);
1.33 fvdl 870: if (buflen < va.va_blocksize)
871: buflen = va.va_blocksize;
1.17 fvdl 872: oldcall = 0;
1.1 fvdl 873: }
1.138 christos 874: tbuf = malloc(buflen, M_TEMP, M_WAITOK);
1.33 fvdl 875:
1.39 fvdl 876: vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.1 fvdl 877: off = fp->f_offset;
878: again:
1.138 christos 879: aiov.iov_base = tbuf;
1.1 fvdl 880: aiov.iov_len = buflen;
881: auio.uio_iov = &aiov;
882: auio.uio_iovcnt = 1;
883: auio.uio_rw = UIO_READ;
884: auio.uio_resid = buflen;
885: auio.uio_offset = off;
1.151 yamt 886: UIO_SETUP_SYSSPACE(&auio);
1.1 fvdl 887: /*
888: * First we read into the malloc'ed buffer, then
889: * we massage it into user space, one record at a time.
890: */
1.39 fvdl 891: error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
892: &ncookies);
1.1 fvdl 893: if (error)
894: goto out;
895:
1.138 christos 896: inp = tbuf;
1.51 fvdl 897: outp = (caddr_t)SCARG(uap, dent);
1.1 fvdl 898: resid = nbytes;
1.35 fvdl 899: if ((len = buflen - auio.uio_resid) == 0)
1.1 fvdl 900: goto eof;
901:
1.22 mycroft 902: for (cookie = cookiebuf; len > 0; len -= reclen) {
1.5 mycroft 903: bdp = (struct dirent *)inp;
904: reclen = bdp->d_reclen;
1.1 fvdl 905: if (reclen & 3)
906: panic("linux_readdir");
907: if (bdp->d_fileno == 0) {
908: inp += reclen; /* it is a hole; squish it out */
1.136 christos 909: if (cookie)
910: off = *cookie++;
911: else
912: off += reclen;
1.1 fvdl 913: continue;
914: }
1.21 mycroft 915: linux_reclen = LINUX_RECLEN(&idb, bdp->d_namlen);
916: if (reclen > len || resid < linux_reclen) {
1.1 fvdl 917: /* entry too big for buffer, so just stop */
918: outp++;
919: break;
920: }
921: /*
922: * Massage in place to make a Linux-shaped dirent (otherwise
923: * we have to worry about touching user memory outside of
924: * the copyout() call).
925: */
1.107 christos 926: idb.d_ino = bdp->d_fileno;
1.17 fvdl 927: /*
1.21 mycroft 928: * The old readdir() call misuses the offset and reclen fields.
1.17 fvdl 929: */
1.22 mycroft 930: if (oldcall) {
931: idb.d_off = (linux_off_t)linux_reclen;
932: idb.d_reclen = (u_short)bdp->d_namlen;
933: } else {
1.109 tron 934: if (sizeof (idb.d_off) <= 4 && (off >> 32) != 0) {
1.33 fvdl 935: compat_offseterr(vp, "linux_getdents");
936: error = EINVAL;
937: goto out;
938: }
1.22 mycroft 939: idb.d_off = (linux_off_t)off;
1.107 christos 940: idb.d_reclen = (u_short)linux_reclen;
941: }
942: strcpy(idb.d_name, bdp->d_name);
943: if ((error = copyout((caddr_t)&idb, outp, linux_reclen)))
944: goto out;
945: /* advance past this real entry */
946: inp += reclen;
1.136 christos 947: if (cookie)
948: off = *cookie++; /* each entry points to itself */
949: else
950: off += reclen;
1.107 christos 951: /* advance output past Linux-shaped entry */
952: outp += linux_reclen;
953: resid -= linux_reclen;
954: if (oldcall)
955: break;
956: }
957:
958: /* if we squished out the whole block, try again */
959: if (outp == (caddr_t)SCARG(uap, dent))
960: goto again;
961: fp->f_offset = off; /* update the vnode offset */
962:
963: if (oldcall)
964: nbytes = resid + linux_reclen;
965:
966: eof:
967: *retval = nbytes - resid;
968: out:
969: VOP_UNLOCK(vp, 0);
970: if (cookiebuf)
971: free(cookiebuf, M_TEMP);
1.138 christos 972: free(tbuf, M_TEMP);
1.107 christos 973: out1:
1.147 christos 974: FILE_UNUSE(fp, l);
1.1 fvdl 975: return error;
976: }
977:
978: /*
1.17 fvdl 979: * Even when just using registers to pass arguments to syscalls you can
980: * have 5 of them on the i386. So this newer version of select() does
981: * this.
1.1 fvdl 982: */
983: int
1.116 thorpej 984: linux_sys_select(l, v, retval)
985: struct lwp *l;
1.20 thorpej 986: void *v;
987: register_t *retval;
988: {
1.21 mycroft 989: struct linux_sys_select_args /* {
1.17 fvdl 990: syscallarg(int) nfds;
991: syscallarg(fd_set *) readfds;
992: syscallarg(fd_set *) writefds;
993: syscallarg(fd_set *) exceptfds;
994: syscallarg(struct timeval *) timeout;
1.20 thorpej 995: } */ *uap = v;
996:
1.116 thorpej 997: return linux_select1(l, retval, SCARG(uap, nfds), SCARG(uap, readfds),
1.17 fvdl 998: SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
999: }
1000:
1001: /*
1002: * Common code for the old and new versions of select(). A couple of
1003: * things are important:
1004: * 1) return the amount of time left in the 'timeout' parameter
1005: * 2) select never returns ERESTART on Linux, always return EINTR
1006: */
1007: int
1.116 thorpej 1008: linux_select1(l, retval, nfds, readfds, writefds, exceptfds, timeout)
1009: struct lwp *l;
1.17 fvdl 1010: register_t *retval;
1011: int nfds;
1012: fd_set *readfds, *writefds, *exceptfds;
1013: struct timeval *timeout;
1014: {
1.21 mycroft 1015: struct sys_select_args bsa;
1.116 thorpej 1016: struct proc *p = l->l_proc;
1.13 mycroft 1017: struct timeval tv0, tv1, utv, *tvp;
1018: caddr_t sg;
1.1 fvdl 1019: int error;
1020:
1.17 fvdl 1021: SCARG(&bsa, nd) = nfds;
1022: SCARG(&bsa, in) = readfds;
1023: SCARG(&bsa, ou) = writefds;
1024: SCARG(&bsa, ex) = exceptfds;
1025: SCARG(&bsa, tv) = timeout;
1.1 fvdl 1026:
1.7 fvdl 1027: /*
1028: * Store current time for computation of the amount of
1029: * time left.
1030: */
1.17 fvdl 1031: if (timeout) {
1032: if ((error = copyin(timeout, &utv, sizeof(utv))))
1.13 mycroft 1033: return error;
1034: if (itimerfix(&utv)) {
1035: /*
1036: * The timeval was invalid. Convert it to something
1037: * valid that will act as it does under Linux.
1038: */
1.102 christos 1039: sg = stackgap_init(p, 0);
1040: tvp = stackgap_alloc(p, &sg, sizeof(utv));
1.13 mycroft 1041: utv.tv_sec += utv.tv_usec / 1000000;
1042: utv.tv_usec %= 1000000;
1043: if (utv.tv_usec < 0) {
1044: utv.tv_sec -= 1;
1045: utv.tv_usec += 1000000;
1046: }
1047: if (utv.tv_sec < 0)
1048: timerclear(&utv);
1049: if ((error = copyout(&utv, tvp, sizeof(utv))))
1050: return error;
1051: SCARG(&bsa, tv) = tvp;
1052: }
1.7 fvdl 1053: microtime(&tv0);
1.13 mycroft 1054: }
1.7 fvdl 1055:
1.116 thorpej 1056: error = sys_select(l, &bsa, retval);
1.10 mycroft 1057: if (error) {
1058: /*
1059: * See fs/select.c in the Linux kernel. Without this,
1060: * Maelstrom doesn't work.
1061: */
1062: if (error == ERESTART)
1063: error = EINTR;
1.7 fvdl 1064: return error;
1.10 mycroft 1065: }
1.7 fvdl 1066:
1.17 fvdl 1067: if (timeout) {
1.14 mycroft 1068: if (*retval) {
1.7 fvdl 1069: /*
1.13 mycroft 1070: * Compute how much time was left of the timeout,
1.7 fvdl 1071: * by subtracting the current time and the time
1072: * before we started the call, and subtracting
1073: * that result from the user-supplied value.
1074: */
1075: microtime(&tv1);
1076: timersub(&tv1, &tv0, &tv1);
1077: timersub(&utv, &tv1, &utv);
1.14 mycroft 1078: if (utv.tv_sec < 0)
1079: timerclear(&utv);
1080: } else
1081: timerclear(&utv);
1.17 fvdl 1082: if ((error = copyout(&utv, timeout, sizeof(utv))))
1.7 fvdl 1083: return error;
1084: }
1.13 mycroft 1085:
1.7 fvdl 1086: return 0;
1.1 fvdl 1087: }
1088:
1089: /*
1090: * Get the process group of a certain process. Look it up
1091: * and return the value.
1092: */
1093: int
1.116 thorpej 1094: linux_sys_getpgid(l, v, retval)
1095: struct lwp *l;
1.20 thorpej 1096: void *v;
1097: register_t *retval;
1098: {
1.21 mycroft 1099: struct linux_sys_getpgid_args /* {
1.1 fvdl 1100: syscallarg(int) pid;
1.20 thorpej 1101: } */ *uap = v;
1.116 thorpej 1102: struct proc *p = l->l_proc;
1.1 fvdl 1103: struct proc *targp;
1104:
1.26 christos 1105: if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != p->p_pid) {
1.1 fvdl 1106: if ((targp = pfind(SCARG(uap, pid))) == 0)
1107: return ESRCH;
1.26 christos 1108: }
1.1 fvdl 1109: else
1110: targp = p;
1111:
1112: retval[0] = targp->p_pgid;
1.6 fvdl 1113: return 0;
1114: }
1115:
1116: /*
1117: * Set the 'personality' (emulation mode) for the current process. Only
1118: * accept the Linux personality here (0). This call is needed because
1119: * the Linux ELF crt0 issues it in an ugly kludge to make sure that
1120: * ELF binaries run in Linux mode, not SVR4 mode.
1121: */
1122: int
1.116 thorpej 1123: linux_sys_personality(l, v, retval)
1124: struct lwp *l;
1.20 thorpej 1125: void *v;
1126: register_t *retval;
1127: {
1.21 mycroft 1128: struct linux_sys_personality_args /* {
1.6 fvdl 1129: syscallarg(int) per;
1.20 thorpej 1130: } */ *uap = v;
1131:
1.6 fvdl 1132: if (SCARG(uap, per) != 0)
1133: return EINVAL;
1134: retval[0] = 0;
1.1 fvdl 1135: return 0;
1.18 fvdl 1136: }
1.150 manu 1137: #endif /* !COMPAT_LINUX32 */
1.18 fvdl 1138:
1.150 manu 1139: #if defined(__i386__) || defined(__m68k__) || defined(COMPAT_LINUX32)
1.18 fvdl 1140: /*
1141: * The calls are here because of type conversions.
1142: */
1143: int
1.116 thorpej 1144: linux_sys_setreuid16(l, v, retval)
1145: struct lwp *l;
1.20 thorpej 1146: void *v;
1147: register_t *retval;
1148: {
1.78 fvdl 1149: struct linux_sys_setreuid16_args /* {
1.18 fvdl 1150: syscallarg(int) ruid;
1151: syscallarg(int) euid;
1.20 thorpej 1152: } */ *uap = v;
1.28 mycroft 1153: struct sys_setreuid_args bsa;
1.135 perry 1154:
1.18 fvdl 1155: SCARG(&bsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
1156: (uid_t)-1 : SCARG(uap, ruid);
1157: SCARG(&bsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
1158: (uid_t)-1 : SCARG(uap, euid);
1159:
1.116 thorpej 1160: return sys_setreuid(l, &bsa, retval);
1.18 fvdl 1161: }
1162:
1163: int
1.116 thorpej 1164: linux_sys_setregid16(l, v, retval)
1165: struct lwp *l;
1.20 thorpej 1166: void *v;
1167: register_t *retval;
1168: {
1.78 fvdl 1169: struct linux_sys_setregid16_args /* {
1.18 fvdl 1170: syscallarg(int) rgid;
1171: syscallarg(int) egid;
1.20 thorpej 1172: } */ *uap = v;
1.28 mycroft 1173: struct sys_setregid_args bsa;
1.135 perry 1174:
1.18 fvdl 1175: SCARG(&bsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
1176: (uid_t)-1 : SCARG(uap, rgid);
1177: SCARG(&bsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
1178: (uid_t)-1 : SCARG(uap, egid);
1179:
1.116 thorpej 1180: return sys_setregid(l, &bsa, retval);
1.63 abs 1181: }
1.81 fvdl 1182:
1183: int
1.116 thorpej 1184: linux_sys_setresuid16(l, v, retval)
1185: struct lwp *l;
1.81 fvdl 1186: void *v;
1187: register_t *retval;
1188: {
1189: struct linux_sys_setresuid16_args /* {
1190: syscallarg(uid_t) ruid;
1191: syscallarg(uid_t) euid;
1192: syscallarg(uid_t) suid;
1193: } */ *uap = v;
1194: struct linux_sys_setresuid16_args lsa;
1195:
1196: SCARG(&lsa, ruid) = ((linux_uid_t)SCARG(uap, ruid) == (linux_uid_t)-1) ?
1197: (uid_t)-1 : SCARG(uap, ruid);
1198: SCARG(&lsa, euid) = ((linux_uid_t)SCARG(uap, euid) == (linux_uid_t)-1) ?
1199: (uid_t)-1 : SCARG(uap, euid);
1200: SCARG(&lsa, suid) = ((linux_uid_t)SCARG(uap, suid) == (linux_uid_t)-1) ?
1201: (uid_t)-1 : SCARG(uap, suid);
1202:
1.116 thorpej 1203: return linux_sys_setresuid(l, &lsa, retval);
1.81 fvdl 1204: }
1205:
1206: int
1.116 thorpej 1207: linux_sys_setresgid16(l, v, retval)
1208: struct lwp *l;
1.81 fvdl 1209: void *v;
1210: register_t *retval;
1211: {
1212: struct linux_sys_setresgid16_args /* {
1213: syscallarg(gid_t) rgid;
1214: syscallarg(gid_t) egid;
1215: syscallarg(gid_t) sgid;
1216: } */ *uap = v;
1217: struct linux_sys_setresgid16_args lsa;
1218:
1219: SCARG(&lsa, rgid) = ((linux_gid_t)SCARG(uap, rgid) == (linux_gid_t)-1) ?
1220: (gid_t)-1 : SCARG(uap, rgid);
1221: SCARG(&lsa, egid) = ((linux_gid_t)SCARG(uap, egid) == (linux_gid_t)-1) ?
1222: (gid_t)-1 : SCARG(uap, egid);
1223: SCARG(&lsa, sgid) = ((linux_gid_t)SCARG(uap, sgid) == (linux_gid_t)-1) ?
1224: (gid_t)-1 : SCARG(uap, sgid);
1225:
1.116 thorpej 1226: return linux_sys_setresgid(l, &lsa, retval);
1.81 fvdl 1227: }
1228:
1229: int
1.116 thorpej 1230: linux_sys_getgroups16(l, v, retval)
1231: struct lwp *l;
1.81 fvdl 1232: void *v;
1233: register_t *retval;
1234: {
1235: struct linux_sys_getgroups16_args /* {
1236: syscallarg(int) gidsetsize;
1237: syscallarg(linux_gid_t *) gidset;
1238: } */ *uap = v;
1.116 thorpej 1239: struct proc *p = l->l_proc;
1.135 perry 1240: caddr_t sg;
1.81 fvdl 1241: int n, error, i;
1242: struct sys_getgroups_args bsa;
1243: gid_t *bset, *kbset;
1244: linux_gid_t *lset;
1.151.2.4! yamt 1245: kauth_cred_t pc = l->l_cred;
1.81 fvdl 1246:
1247: n = SCARG(uap, gidsetsize);
1248: if (n < 0)
1249: return EINVAL;
1250: error = 0;
1251: bset = kbset = NULL;
1252: lset = NULL;
1253: if (n > 0) {
1.151.2.2 yamt 1254: n = min(kauth_cred_ngroups(pc), n);
1.102 christos 1255: sg = stackgap_init(p, 0);
1256: bset = stackgap_alloc(p, &sg, n * sizeof (gid_t));
1.81 fvdl 1257: kbset = malloc(n * sizeof (gid_t), M_TEMP, M_WAITOK);
1258: lset = malloc(n * sizeof (linux_gid_t), M_TEMP, M_WAITOK);
1259: if (bset == NULL || kbset == NULL || lset == NULL)
1.151.2.1 yamt 1260: {
1261: error = ENOMEM;
1262: goto out;
1263: }
1.81 fvdl 1264: SCARG(&bsa, gidsetsize) = n;
1265: SCARG(&bsa, gidset) = bset;
1.116 thorpej 1266: error = sys_getgroups(l, &bsa, retval);
1.81 fvdl 1267: if (error != 0)
1268: goto out;
1269: error = copyin(bset, kbset, n * sizeof (gid_t));
1270: if (error != 0)
1271: goto out;
1272: for (i = 0; i < n; i++)
1273: lset[i] = (linux_gid_t)kbset[i];
1274: error = copyout(lset, SCARG(uap, gidset),
1275: n * sizeof (linux_gid_t));
1276: } else
1.151.2.2 yamt 1277: *retval = kauth_cred_ngroups(pc);
1.81 fvdl 1278: out:
1279: if (kbset != NULL)
1280: free(kbset, M_TEMP);
1281: if (lset != NULL)
1282: free(lset, M_TEMP);
1283: return error;
1284: }
1285:
1286: int
1.116 thorpej 1287: linux_sys_setgroups16(l, v, retval)
1288: struct lwp *l;
1.81 fvdl 1289: void *v;
1290: register_t *retval;
1291: {
1292: struct linux_sys_setgroups16_args /* {
1293: syscallarg(int) gidsetsize;
1294: syscallarg(linux_gid_t *) gidset;
1295: } */ *uap = v;
1.116 thorpej 1296: struct proc *p = l->l_proc;
1.81 fvdl 1297: caddr_t sg;
1298: int n;
1299: int error, i;
1300: struct sys_setgroups_args bsa;
1301: gid_t *bset, *kbset;
1302: linux_gid_t *lset;
1303:
1304: n = SCARG(uap, gidsetsize);
1305: if (n < 0 || n > NGROUPS)
1306: return EINVAL;
1.102 christos 1307: sg = stackgap_init(p, 0);
1308: bset = stackgap_alloc(p, &sg, n * sizeof (gid_t));
1.81 fvdl 1309: lset = malloc(n * sizeof (linux_gid_t), M_TEMP, M_WAITOK);
1.106 fvdl 1310: kbset = malloc(n * sizeof (gid_t), M_TEMP, M_WAITOK);
1.151.2.1 yamt 1311: if (bset == NULL || kbset == NULL || lset == NULL)
1312: {
1313: error = ENOMEM;
1314: goto out;
1315: }
1.81 fvdl 1316: error = copyin(SCARG(uap, gidset), lset, n * sizeof (linux_gid_t));
1317: if (error != 0)
1318: goto out;
1319: for (i = 0; i < n; i++)
1320: kbset[i] = (gid_t)lset[i];
1321: error = copyout(kbset, bset, n * sizeof (gid_t));
1322: if (error != 0)
1323: goto out;
1324: SCARG(&bsa, gidsetsize) = n;
1325: SCARG(&bsa, gidset) = bset;
1.116 thorpej 1326: error = sys_setgroups(l, &bsa, retval);
1.135 perry 1327:
1.81 fvdl 1328: out:
1329: if (lset != NULL)
1330: free(lset, M_TEMP);
1331: if (kbset != NULL)
1332: free(kbset, M_TEMP);
1333:
1334: return error;
1335: }
1336:
1.150 manu 1337: #endif /* __i386__ || __m68k__ || COMPAT_LINUX32 */
1.63 abs 1338:
1.150 manu 1339: #ifndef COMPAT_LINUX32
1.63 abs 1340: /*
1.64 abs 1341: * We have nonexistent fsuid equal to uid.
1342: * If modification is requested, refuse.
1.63 abs 1343: */
1344: int
1.116 thorpej 1345: linux_sys_setfsuid(l, v, retval)
1346: struct lwp *l;
1.63 abs 1347: void *v;
1348: register_t *retval;
1349: {
1350: struct linux_sys_setfsuid_args /* {
1351: syscallarg(uid_t) uid;
1352: } */ *uap = v;
1353: uid_t uid;
1354:
1355: uid = SCARG(uap, uid);
1.151.2.4! yamt 1356: if (kauth_cred_getuid(l->l_cred) != uid)
1.116 thorpej 1357: return sys_nosys(l, v, retval);
1.63 abs 1358: else
1359: return (0);
1360: }
1361:
1.66 erh 1362: /* XXX XXX XXX */
1.150 manu 1363: # ifndef alpha
1.63 abs 1364: int
1.116 thorpej 1365: linux_sys_getfsuid(l, v, retval)
1366: struct lwp *l;
1.66 erh 1367: void *v;
1368: register_t *retval;
1.63 abs 1369: {
1.116 thorpej 1370: return sys_getuid(l, v, retval);
1.27 fvdl 1371: }
1.150 manu 1372: # endif
1.27 fvdl 1373:
1374: int
1.116 thorpej 1375: linux_sys_setresuid(l, v, retval)
1376: struct lwp *l;
1.57 thorpej 1377: void *v;
1378: register_t *retval;
1379: {
1380: struct linux_sys_setresuid_args /* {
1381: syscallarg(uid_t) ruid;
1382: syscallarg(uid_t) euid;
1383: syscallarg(uid_t) suid;
1384: } */ *uap = v;
1385:
1386: /*
1387: * Note: These checks are a little different than the NetBSD
1388: * setreuid(2) call performs. This precisely follows the
1389: * behavior of the Linux kernel.
1390: */
1391:
1.117 dsl 1392: return do_setresuid(l, SCARG(uap, ruid), SCARG(uap, euid),
1393: SCARG(uap, suid),
1394: ID_R_EQ_R | ID_R_EQ_E | ID_R_EQ_S |
1395: ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
1396: ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S );
1.57 thorpej 1397: }
1398:
1399: int
1.116 thorpej 1400: linux_sys_getresuid(l, v, retval)
1401: struct lwp *l;
1.57 thorpej 1402: void *v;
1403: register_t *retval;
1404: {
1405: struct linux_sys_getresuid_args /* {
1406: syscallarg(uid_t *) ruid;
1407: syscallarg(uid_t *) euid;
1408: syscallarg(uid_t *) suid;
1409: } */ *uap = v;
1.151.2.4! yamt 1410: kauth_cred_t pc = l->l_cred;
1.57 thorpej 1411: int error;
1.151.2.2 yamt 1412: uid_t uid;
1.57 thorpej 1413:
1414: /*
1415: * Linux copies these values out to userspace like so:
1416: *
1417: * 1. Copy out ruid.
1418: * 2. If that succeeds, copy out euid.
1419: * 3. If both of those succeed, copy out suid.
1420: */
1.151.2.2 yamt 1421: uid = kauth_cred_getuid(pc);
1422: if ((error = copyout(&uid, SCARG(uap, ruid), sizeof(uid_t))) != 0)
1.57 thorpej 1423: return (error);
1424:
1.151.2.2 yamt 1425: uid = kauth_cred_geteuid(pc);
1426: if ((error = copyout(&uid, SCARG(uap, euid), sizeof(uid_t))) != 0)
1.57 thorpej 1427: return (error);
1428:
1.151.2.2 yamt 1429: uid = kauth_cred_getsvuid(pc);
1430:
1431: return (copyout(&uid, SCARG(uap, suid), sizeof(uid_t)));
1.78 fvdl 1432: }
1.62 tron 1433:
1434: int
1.116 thorpej 1435: linux_sys_ptrace(l, v, retval)
1436: struct lwp *l;
1.62 tron 1437: void *v;
1438: register_t *retval;
1439: {
1440: struct linux_sys_ptrace_args /* {
1.88 manu 1441: i386, m68k, powerpc: T=int
1.137 manu 1442: alpha, amd64: T=long
1.66 erh 1443: syscallarg(T) request;
1444: syscallarg(T) pid;
1445: syscallarg(T) addr;
1446: syscallarg(T) data;
1.62 tron 1447: } */ *uap = v;
1.73 jdolecek 1448: const int *ptr;
1449: int request;
1.89 manu 1450: int error;
1.62 tron 1451:
1452: ptr = linux_ptrace_request_map;
1453: request = SCARG(uap, request);
1454: while (*ptr != -1)
1455: if (*ptr++ == request) {
1456: struct sys_ptrace_args pta;
1457:
1458: SCARG(&pta, req) = *ptr;
1459: SCARG(&pta, pid) = SCARG(uap, pid);
1460: SCARG(&pta, addr) = (caddr_t)SCARG(uap, addr);
1461: SCARG(&pta, data) = SCARG(uap, data);
1462:
1.73 jdolecek 1463: /*
1464: * Linux ptrace(PTRACE_CONT, pid, 0, 0) means actually
1.90 jdolecek 1465: * to continue where the process left off previously.
1466: * The same thing is achieved by addr == (caddr_t) 1
1467: * on NetBSD, so rewrite 'addr' appropriately.
1.73 jdolecek 1468: */
1469: if (request == LINUX_PTRACE_CONT && SCARG(uap, addr)==0)
1470: SCARG(&pta, addr) = (caddr_t) 1;
1.135 perry 1471:
1.116 thorpej 1472: error = sys_ptrace(l, &pta, retval);
1.135 perry 1473: if (error)
1.92 manu 1474: return error;
1475: switch (request) {
1476: case LINUX_PTRACE_PEEKTEXT:
1477: case LINUX_PTRACE_PEEKDATA:
1.135 perry 1478: error = copyout (retval,
1.137 manu 1479: (caddr_t)SCARG(uap, data),
1480: sizeof *retval);
1.92 manu 1481: *retval = SCARG(uap, data);
1482: break;
1.135 perry 1483: default:
1.92 manu 1484: break;
1485: }
1.89 manu 1486: return error;
1.62 tron 1487: }
1488: else
1489: ptr++;
1490:
1.116 thorpej 1491: return LINUX_SYS_PTRACE_ARCH(l, uap, retval);
1.1 fvdl 1492: }
1.67 erh 1493:
1494: int
1.116 thorpej 1495: linux_sys_reboot(struct lwp *l, void *v, register_t *retval)
1.67 erh 1496: {
1497: struct linux_sys_reboot_args /* {
1498: syscallarg(int) magic1;
1499: syscallarg(int) magic2;
1500: syscallarg(int) cmd;
1501: syscallarg(void *) arg;
1502: } */ *uap = v;
1503: struct sys_reboot_args /* {
1504: syscallarg(int) opt;
1505: syscallarg(char *) bootstr;
1506: } */ sra;
1507: int error;
1508:
1.151.2.4! yamt 1509: if ((error = kauth_authorize_generic(l->l_cred,
! 1510: KAUTH_GENERIC_ISSUSER, &l->l_acflag)) != 0)
1.67 erh 1511: return(error);
1512:
1513: if (SCARG(uap, magic1) != LINUX_REBOOT_MAGIC1)
1514: return(EINVAL);
1515: if (SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2 &&
1516: SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2A &&
1517: SCARG(uap, magic2) != LINUX_REBOOT_MAGIC2B)
1518: return(EINVAL);
1519:
1520: switch (SCARG(uap, cmd)) {
1521: case LINUX_REBOOT_CMD_RESTART:
1522: SCARG(&sra, opt) = RB_AUTOBOOT;
1523: break;
1524: case LINUX_REBOOT_CMD_HALT:
1525: SCARG(&sra, opt) = RB_HALT;
1526: break;
1527: case LINUX_REBOOT_CMD_POWER_OFF:
1528: SCARG(&sra, opt) = RB_HALT|RB_POWERDOWN;
1529: break;
1530: case LINUX_REBOOT_CMD_RESTART2:
1531: /* Reboot with an argument. */
1532: SCARG(&sra, opt) = RB_AUTOBOOT|RB_STRING;
1533: SCARG(&sra, bootstr) = SCARG(uap, arg);
1534: break;
1535: case LINUX_REBOOT_CMD_CAD_ON:
1536: return(EINVAL); /* We don't implement ctrl-alt-delete */
1537: case LINUX_REBOOT_CMD_CAD_OFF:
1538: return(0);
1539: default:
1540: return(EINVAL);
1541: }
1542:
1.116 thorpej 1543: return(sys_reboot(l, &sra, retval));
1.75 jdolecek 1544: }
1545:
1546: /*
1547: * Copy of compat_12_sys_swapon().
1548: */
1549: int
1.116 thorpej 1550: linux_sys_swapon(l, v, retval)
1551: struct lwp *l;
1.75 jdolecek 1552: void *v;
1553: register_t *retval;
1554: {
1555: struct sys_swapctl_args ua;
1556: struct linux_sys_swapon_args /* {
1557: syscallarg(const char *) name;
1558: } */ *uap = v;
1559:
1560: SCARG(&ua, cmd) = SWAP_ON;
1.139 drochner 1561: SCARG(&ua, arg) = (void *)__UNCONST(SCARG(uap, name));
1.75 jdolecek 1562: SCARG(&ua, misc) = 0; /* priority */
1.116 thorpej 1563: return (sys_swapctl(l, &ua, retval));
1.76 jdolecek 1564: }
1565:
1566: /*
1567: * Stop swapping to the file or block device specified by path.
1568: */
1569: int
1.116 thorpej 1570: linux_sys_swapoff(l, v, retval)
1571: struct lwp *l;
1.76 jdolecek 1572: void *v;
1573: register_t *retval;
1574: {
1575: struct sys_swapctl_args ua;
1576: struct linux_sys_swapoff_args /* {
1577: syscallarg(const char *) path;
1578: } */ *uap = v;
1579:
1580: SCARG(&ua, cmd) = SWAP_OFF;
1.138 christos 1581: SCARG(&ua, arg) = __UNCONST(SCARG(uap, path)); /*XXXUNCONST*/
1.116 thorpej 1582: return (sys_swapctl(l, &ua, retval));
1.75 jdolecek 1583: }
1584:
1585: /*
1586: * Copy of compat_09_sys_setdomainname()
1587: */
1588: /* ARGSUSED */
1589: int
1.116 thorpej 1590: linux_sys_setdomainname(l, v, retval)
1591: struct lwp *l;
1.75 jdolecek 1592: void *v;
1593: register_t *retval;
1594: {
1595: struct linux_sys_setdomainname_args /* {
1596: syscallarg(char *) domainname;
1597: syscallarg(int) len;
1598: } */ *uap = v;
1.122 atatat 1599: int name[2];
1.75 jdolecek 1600:
1.122 atatat 1601: name[0] = CTL_KERN;
1602: name[1] = KERN_DOMAINNAME;
1603: return (old_sysctl(&name[0], 2, 0, 0, SCARG(uap, domainname),
1604: SCARG(uap, len), l));
1.77 augustss 1605: }
1606:
1607: /*
1608: * sysinfo()
1609: */
1610: /* ARGSUSED */
1611: int
1.116 thorpej 1612: linux_sys_sysinfo(l, v, retval)
1613: struct lwp *l;
1.77 augustss 1614: void *v;
1615: register_t *retval;
1616: {
1617: struct linux_sys_sysinfo_args /* {
1618: syscallarg(struct linux_sysinfo *) arg;
1619: } */ *uap = v;
1620: struct linux_sysinfo si;
1621: struct loadavg *la;
1622:
1.151.2.3 yamt 1623: si.uptime = time_uptime;
1.77 augustss 1624: la = &averunnable;
1625: si.loads[0] = la->ldavg[0] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1626: si.loads[1] = la->ldavg[1] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1627: si.loads[2] = la->ldavg[2] * LINUX_SYSINFO_LOADS_SCALE / la->fscale;
1628: si.totalram = ctob(physmem);
1629: si.freeram = uvmexp.free * uvmexp.pagesize;
1630: si.sharedram = 0; /* XXX */
1.96 chs 1631: si.bufferram = uvmexp.filepages * uvmexp.pagesize;
1.77 augustss 1632: si.totalswap = uvmexp.swpages * uvmexp.pagesize;
1633: si.freeswap = (uvmexp.swpages - uvmexp.swpginuse) * uvmexp.pagesize;
1634: si.procs = nprocs;
1635:
1636: /* The following are only present in newer Linux kernels. */
1637: si.totalbig = 0;
1638: si.freebig = 0;
1639: si.mem_unit = 1;
1640:
1641: return (copyout(&si, SCARG(uap, arg), sizeof si));
1.97 christos 1642: }
1643:
1644: int
1.116 thorpej 1645: linux_sys_getrlimit(l, v, retval)
1646: struct lwp *l;
1.97 christos 1647: void *v;
1648: register_t *retval;
1649: {
1650: struct linux_sys_getrlimit_args /* {
1651: syscallarg(int) which;
1.150 manu 1652: # ifdef LINUX_LARGEFILE64
1.144 manu 1653: syscallarg(struct rlimit *) rlp;
1.150 manu 1654: # else
1.97 christos 1655: syscallarg(struct orlimit *) rlp;
1.150 manu 1656: # endif
1.97 christos 1657: } */ *uap = v;
1.116 thorpej 1658: struct proc *p = l->l_proc;
1.102 christos 1659: caddr_t sg = stackgap_init(p, 0);
1.97 christos 1660: struct sys_getrlimit_args ap;
1661: struct rlimit rl;
1.150 manu 1662: # ifdef LINUX_LARGEFILE64
1.144 manu 1663: struct rlimit orl;
1.150 manu 1664: # else
1.97 christos 1665: struct orlimit orl;
1.150 manu 1666: # endif
1.97 christos 1667: int error;
1668:
1669: SCARG(&ap, which) = linux_to_bsd_limit(SCARG(uap, which));
1670: if ((error = SCARG(&ap, which)) < 0)
1671: return -error;
1.102 christos 1672: SCARG(&ap, rlp) = stackgap_alloc(p, &sg, sizeof rl);
1.116 thorpej 1673: if ((error = sys_getrlimit(l, &ap, retval)) != 0)
1.97 christos 1674: return error;
1675: if ((error = copyin(SCARG(&ap, rlp), &rl, sizeof(rl))) != 0)
1676: return error;
1677: bsd_to_linux_rlimit(&orl, &rl);
1.146 rpaulo 1678:
1.97 christos 1679: return copyout(&orl, SCARG(uap, rlp), sizeof(orl));
1680: }
1681:
1682: int
1.116 thorpej 1683: linux_sys_setrlimit(l, v, retval)
1684: struct lwp *l;
1.97 christos 1685: void *v;
1686: register_t *retval;
1687: {
1688: struct linux_sys_setrlimit_args /* {
1689: syscallarg(int) which;
1.150 manu 1690: # ifdef LINUX_LARGEFILE64
1.144 manu 1691: syscallarg(struct rlimit *) rlp;
1.150 manu 1692: # else
1.97 christos 1693: syscallarg(struct orlimit *) rlp;
1.150 manu 1694: # endif
1.97 christos 1695: } */ *uap = v;
1.116 thorpej 1696: struct proc *p = l->l_proc;
1.102 christos 1697: caddr_t sg = stackgap_init(p, 0);
1.138 christos 1698: struct sys_getrlimit_args ap;
1.97 christos 1699: struct rlimit rl;
1.150 manu 1700: # ifdef LINUX_LARGEFILE64
1.144 manu 1701: struct rlimit orl;
1.150 manu 1702: # else
1.97 christos 1703: struct orlimit orl;
1.150 manu 1704: # endif
1.97 christos 1705: int error;
1706:
1707: SCARG(&ap, which) = linux_to_bsd_limit(SCARG(uap, which));
1.102 christos 1708: SCARG(&ap, rlp) = stackgap_alloc(p, &sg, sizeof rl);
1.97 christos 1709: if ((error = SCARG(&ap, which)) < 0)
1710: return -error;
1711: if ((error = copyin(SCARG(uap, rlp), &orl, sizeof(orl))) != 0)
1712: return error;
1713: linux_to_bsd_rlimit(&rl, &orl);
1.138 christos 1714: if ((error = copyout(&rl, SCARG(&ap, rlp), sizeof(rl))) != 0)
1.97 christos 1715: return error;
1.116 thorpej 1716: return sys_setrlimit(l, &ap, retval);
1.97 christos 1717: }
1718:
1.150 manu 1719: # if !defined(__mips__) && !defined(__amd64__)
1.98 rafal 1720: /* XXX: this doesn't look 100% common, at least mips doesn't have it */
1.97 christos 1721: int
1.116 thorpej 1722: linux_sys_ugetrlimit(l, v, retval)
1723: struct lwp *l;
1.97 christos 1724: void *v;
1725: register_t *retval;
1726: {
1.116 thorpej 1727: return linux_sys_getrlimit(l, v, retval);
1.87 jdolecek 1728: }
1.150 manu 1729: # endif
1.87 jdolecek 1730:
1731: /*
1732: * This gets called for unsupported syscalls. The difference to sys_nosys()
1733: * is that process does not get SIGSYS, the call just returns with ENOSYS.
1734: * This is the way Linux does it and glibc depends on this behaviour.
1735: */
1736: int
1.116 thorpej 1737: linux_sys_nosys(l, v, retval)
1738: struct lwp *l;
1.87 jdolecek 1739: void *v;
1740: register_t *retval;
1741: {
1742: return (ENOSYS);
1.67 erh 1743: }
1.150 manu 1744:
1.151.2.3 yamt 1745: int
1746: linux_sys_getpriority(l, v, retval)
1747: struct lwp *l;
1748: void *v;
1749: register_t *retval;
1750: {
1751: struct linux_sys_getpriority_args /* {
1752: syscallarg(int) which;
1753: syscallarg(int) who;
1754: } */ *uap = v;
1755: struct sys_getpriority_args bsa;
1756: int error;
1757:
1758: SCARG(&bsa, which) = SCARG(uap, which);
1759: SCARG(&bsa, who) = SCARG(uap, who);
1760:
1761: if ((error = sys_getpriority(l, &bsa, retval)))
1762: return error;
1763:
1764: *retval = NZERO - *retval;
1765:
1766: return 0;
1767: }
1768:
1.150 manu 1769: #endif /* !COMPAT_LINUX32 */
CVSweb <webmaster@jp.NetBSD.org>