Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / compat / svr4_32 / svr4_32_misc.c
blob9992f30fc7f471bbc1f2b4dfec9a01325f3bd246
1 /* $NetBSD: svr4_32_misc.c,v 1.66 2009/11/04 21:23:03 rmind Exp $ */
3 /*-
4 * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * SVR4 compatibility module.
35 * SVR4 system calls that are implemented differently in BSD are
36 * handled here.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: svr4_32_misc.c,v 1.66 2009/11/04 21:23:03 rmind Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/namei.h>
45 #include <sys/dirent.h>
46 #include <sys/proc.h>
47 #include <sys/file.h>
48 #include <sys/stat.h>
49 #include <sys/time.h>
50 #include <sys/filedesc.h>
51 #include <sys/ioctl.h>
52 #include <sys/kernel.h>
53 #include <sys/malloc.h>
54 #include <sys/pool.h>
55 #include <sys/mbuf.h>
56 #include <sys/mman.h>
57 #include <sys/mount.h>
58 #include <sys/resource.h>
59 #include <sys/resourcevar.h>
60 #include <sys/socket.h>
61 #include <sys/vnode.h>
62 #include <sys/uio.h>
63 #include <sys/wait.h>
64 #include <sys/utsname.h>
65 #include <sys/unistd.h>
66 #include <sys/vfs_syscalls.h>
67 #include <sys/times.h>
68 #include <sys/sem.h>
69 #include <sys/msg.h>
70 #include <sys/ptrace.h>
71 #include <sys/signalvar.h>
73 #include <netinet/in.h>
74 #include <sys/syscallargs.h>
76 #include <miscfs/specfs/specdev.h>
78 #include <compat/svr4_32/svr4_32_types.h>
79 #include <compat/netbsd32/netbsd32_syscallargs.h>
80 #include <compat/svr4_32/svr4_32_signal.h>
81 #include <compat/svr4_32/svr4_32_lwp.h>
82 #include <compat/svr4_32/svr4_32_ucontext.h>
83 #include <compat/svr4_32/svr4_32_syscallargs.h>
84 #include <compat/svr4_32/svr4_32_util.h>
85 #include <compat/svr4_32/svr4_32_time.h>
86 #include <compat/svr4_32/svr4_32_dirent.h>
87 #include <compat/svr4/svr4_ulimit.h>
88 #include <compat/svr4_32/svr4_32_hrt.h>
89 #include <compat/svr4/svr4_wait.h>
90 #include <compat/svr4_32/svr4_32_statvfs.h>
91 #include <compat/svr4/svr4_sysconfig.h>
92 #include <compat/svr4_32/svr4_32_acl.h>
93 #include <compat/svr4/svr4_mman.h>
95 #include <sys/cpu.h>
97 #include <uvm/uvm_extern.h>
99 static int svr4_to_bsd_mmap_flags(int);
101 static inline clock_t timeval_to_clock_t(struct timeval *);
102 static int svr4_32_setinfo(int, struct rusage *, int, svr4_32_siginfo_tp);
104 #define svr4_32_pfind(pid) p_find((pid), PFIND_UNLOCK | PFIND_ZOMBIE)
106 static int svr4_32_mknod(struct lwp *, register_t *, const char *,
107 svr4_32_mode_t, svr4_32_dev_t);
110 svr4_32_sys_wait(struct lwp *l, const struct svr4_32_sys_wait_args *uap,
111 register_t *retval)
113 int error, st, sig, pid = WAIT_ANY;
115 error = do_sys_wait(&pid, &st, 0, NULL);
117 retval[0] = pid;
118 if (pid == 0)
119 return error;
121 if (WIFSIGNALED(st)) {
122 sig = WTERMSIG(st);
123 if (sig >= 0 && sig < NSIG)
124 st = (st & ~0177) | native_to_svr4_signo[sig];
125 } else if (WIFSTOPPED(st)) {
126 sig = WSTOPSIG(st);
127 if (sig >= 0 && sig < NSIG)
128 st = (st & ~0xff00) | (native_to_svr4_signo[sig] << 8);
132 * It looks like wait(2) on svr4/solaris/2.4 returns
133 * the status in retval[1], and the pid on retval[0].
135 retval[1] = st;
137 if (SCARG_P32(uap, status))
138 error = copyout(&st, SCARG_P32(uap, status), sizeof(st));
139 return error;
144 svr4_32_sys_execv(struct lwp *l, const struct svr4_32_sys_execv_args *uap, register_t *retval)
146 /* {
147 syscallarg(char *) path;
148 syscallarg(char **) argv;
149 } */
150 struct netbsd32_execve_args ap;
152 SCARG(&ap, path) = SCARG(uap, path);
153 SCARG(&ap, argp) = SCARG(uap, argp);
154 NETBSD32PTR32(SCARG(&ap, envp), 0);
156 return netbsd32_execve(l, &ap, retval);
159 #if 0
161 svr4_32_sys_execve(struct proc *p, void *v, register_t *retval)
163 struct svr4_32_sys_execve_args /* {
164 syscallarg(const char *) path;
165 syscallarg(char **) argv;
166 syscallarg(char **) envp;
167 } */ *uap = v;
168 struct sys_execve_args ap;
170 SCARG(&ap, path) = SCARG_P32(uap, path);
171 SCARG(&ap, argp) = SCARG_P32(uap, argp);
172 SCARG(&ap, envp) = SCARG_P32(uap, envp);
174 return netbsd32_execve(p, &ap, retval);
176 #endif
179 svr4_32_sys_time(struct lwp *l, const struct svr4_32_sys_time_args *uap, register_t *retval)
181 int error = 0;
182 struct timeval tv;
183 struct netbsd32_timeval ntv;
185 microtime(&tv);
186 ntv.tv_sec = tv.tv_sec;
187 ntv.tv_usec = tv.tv_usec;
188 if (SCARG_P32(uap, t))
189 error = copyout(&ntv.tv_sec, SCARG_P32(uap, t),
190 sizeof(ntv.tv_sec));
191 *retval = (int) ntv.tv_sec;
193 return error;
198 * Read SVR4-style directory entries. We suck them into kernel space so
199 * that they can be massaged before being copied out to user code. Like
200 * SunOS, we squish out `empty' entries.
202 * This is quite ugly, but what do you expect from compatibility code?
205 svr4_32_sys_getdents64(struct lwp *l, const struct svr4_32_sys_getdents64_args *uap, register_t *retval)
207 struct dirent *bdp;
208 struct vnode *vp;
209 char *inp, *sbuf; /* BSD-format */
210 int len, reclen; /* BSD-format */
211 char *outp; /* SVR4-format */
212 int resid, svr4_32_reclen; /* SVR4-format */
213 file_t *fp;
214 struct uio auio;
215 struct iovec aiov;
216 struct svr4_32_dirent64 idb;
217 off_t off; /* true file offset */
218 int buflen, error, eofflag;
219 off_t *cookiebuf = NULL, *cookie;
220 int ncookies;
222 /* fd_getvnode() will use the descriptor for us */
223 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
224 return (error);
226 if ((fp->f_flag & FREAD) == 0) {
227 error = EBADF;
228 goto out1;
231 vp = fp->f_data;
232 if (vp->v_type != VDIR) {
233 error = EINVAL;
234 goto out1;
237 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
238 sbuf = malloc(buflen, M_TEMP, M_WAITOK);
239 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
240 off = fp->f_offset;
241 again:
242 aiov.iov_base = sbuf;
243 aiov.iov_len = buflen;
244 auio.uio_iov = &aiov;
245 auio.uio_iovcnt = 1;
246 auio.uio_rw = UIO_READ;
247 auio.uio_resid = buflen;
248 auio.uio_offset = off;
249 UIO_SETUP_SYSSPACE(&auio);
251 * First we read into the malloc'ed buffer, then
252 * we massage it into user space, one record at a time.
254 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
255 &ncookies);
256 if (error)
257 goto out;
259 inp = sbuf;
260 outp = SCARG_P32(uap, dp);
261 resid = SCARG(uap, nbytes);
262 if ((len = buflen - auio.uio_resid) == 0)
263 goto eof;
265 for (cookie = cookiebuf; len > 0; len -= reclen) {
266 bdp = (struct dirent *)inp;
267 reclen = bdp->d_reclen;
268 if (reclen & 3)
269 panic("svr4_32_getdents64: bad reclen");
270 if (bdp->d_fileno == 0) {
271 inp += reclen; /* it is a hole; squish it out */
272 if (cookie)
273 off = *cookie++;
274 else
275 off += reclen;
276 continue;
278 svr4_32_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
279 if (reclen > len || resid < svr4_32_reclen) {
280 /* entry too big for buffer, so just stop */
281 outp++;
282 break;
284 if (cookie)
285 off = *cookie++; /* each entry points to the next */
286 else
287 off += reclen;
289 * Massage in place to make a SVR4-shaped dirent (otherwise
290 * we have to worry about touching user memory outside of
291 * the copyout() call).
293 idb.d_ino = (svr4_32_ino64_t)bdp->d_fileno;
294 idb.d_off = (svr4_32_off64_t)off;
295 idb.d_reclen = (u_short)svr4_32_reclen;
296 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
297 if ((error = copyout((void *)&idb, outp, svr4_32_reclen)))
298 goto out;
299 /* advance past this real entry */
300 inp += reclen;
301 /* advance output past SVR4-shaped entry */
302 outp += svr4_32_reclen;
303 resid -= svr4_32_reclen;
306 /* if we squished out the whole block, try again */
307 if (outp == SCARG_P32(uap, dp))
308 goto again;
309 fp->f_offset = off; /* update the vnode offset */
311 eof:
312 *retval = SCARG(uap, nbytes) - resid;
313 out:
314 VOP_UNLOCK(vp, 0);
315 if (cookiebuf)
316 free(cookiebuf, M_TEMP);
317 free(sbuf, M_TEMP);
318 out1:
319 fd_putfile(SCARG(uap, fd));
320 return error;
325 svr4_32_sys_getdents(struct lwp *l, const struct svr4_32_sys_getdents_args *uap, register_t *retval)
327 struct dirent *bdp;
328 struct vnode *vp;
329 char *inp, *sbuf; /* BSD-format */
330 int len, reclen; /* BSD-format */
331 char *outp; /* SVR4-format */
332 int resid, svr4_reclen; /* SVR4-format */
333 file_t *fp;
334 struct uio auio;
335 struct iovec aiov;
336 struct svr4_32_dirent idb;
337 off_t off; /* true file offset */
338 int buflen, error, eofflag;
339 off_t *cookiebuf = NULL, *cookie;
340 int ncookies;
342 /* fd_getvnode() will use the descriptor for us */
343 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
344 return (error);
346 if ((fp->f_flag & FREAD) == 0) {
347 error = EBADF;
348 goto out1;
351 vp = fp->f_data;
352 if (vp->v_type != VDIR) {
353 error = EINVAL;
354 goto out1;
357 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
358 sbuf = malloc(buflen, M_TEMP, M_WAITOK);
359 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
360 off = fp->f_offset;
361 again:
362 aiov.iov_base = sbuf;
363 aiov.iov_len = buflen;
364 auio.uio_iov = &aiov;
365 auio.uio_iovcnt = 1;
366 auio.uio_rw = UIO_READ;
367 auio.uio_resid = buflen;
368 auio.uio_offset = off;
369 UIO_SETUP_SYSSPACE(&auio);
371 * First we read into the malloc'ed buffer, then
372 * we massage it into user space, one record at a time.
374 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
375 &ncookies);
376 if (error)
377 goto out;
379 inp = sbuf;
380 outp = SCARG_P32(uap, buf);
381 resid = SCARG(uap, nbytes);
382 if ((len = buflen - auio.uio_resid) == 0)
383 goto eof;
385 for (cookie = cookiebuf; len > 0; len -= reclen) {
386 bdp = (struct dirent *)inp;
387 reclen = bdp->d_reclen;
388 if (reclen & 3)
389 panic("svr4_32_getdents: bad reclen");
390 if (cookie)
391 off = *cookie++; /* each entry points to the next */
392 else
393 off += reclen;
394 if ((off >> 32) != 0) {
395 compat_offseterr(vp, "svr4_32_getdents");
396 error = EINVAL;
397 goto out;
399 if (bdp->d_fileno == 0) {
400 inp += reclen; /* it is a hole; squish it out */
401 continue;
403 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
404 if (reclen > len || resid < svr4_reclen) {
405 /* entry too big for buffer, so just stop */
406 outp++;
407 break;
410 * Massage in place to make a SVR4-shaped dirent (otherwise
411 * we have to worry about touching user memory outside of
412 * the copyout() call).
414 idb.d_ino = (svr4_32_ino_t)bdp->d_fileno;
415 idb.d_off = (svr4_32_off_t)off;
416 idb.d_reclen = (u_short)svr4_reclen;
417 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
418 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
419 goto out;
420 /* advance past this real entry */
421 inp += reclen;
422 /* advance output past SVR4-shaped entry */
423 outp += svr4_reclen;
424 resid -= svr4_reclen;
427 /* if we squished out the whole block, try again */
428 if (outp == SCARG_P32(uap, buf))
429 goto again;
430 fp->f_offset = off; /* update the vnode offset */
432 eof:
433 *retval = SCARG(uap, nbytes) - resid;
434 out:
435 VOP_UNLOCK(vp, 0);
436 if (cookiebuf)
437 free(cookiebuf, M_TEMP);
438 free(sbuf, M_TEMP);
439 out1:
440 fd_putfile(SCARG(uap, fd));
441 return error;
445 static int
446 svr4_to_bsd_mmap_flags(int f)
448 int type = f & SVR4_MAP_TYPE;
449 int nf;
451 if (type != MAP_PRIVATE && type != MAP_SHARED)
452 return -1;
454 nf = f & SVR4_MAP_COPYFLAGS;
455 if (f & SVR4_MAP_ANON)
456 nf |= MAP_ANON;
458 return nf;
463 svr4_32_sys_mmap(struct lwp *l, const struct svr4_32_sys_mmap_args *uap, register_t *retval)
465 struct sys_mmap_args mm;
466 int error;
468 * Verify the arguments.
470 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
471 return EINVAL; /* XXX still needed? */
473 if (SCARG(uap, len) == 0)
474 return EINVAL;
476 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
477 return EINVAL;
479 SCARG(&mm, prot) = SCARG(uap, prot);
480 SCARG(&mm, len) = SCARG(uap, len);
481 SCARG(&mm, fd) = SCARG(uap, fd);
482 SCARG(&mm, addr) = SCARG_P32(uap, addr);
483 SCARG(&mm, pos) = SCARG(uap, pos);
485 error = sys_mmap(l, &mm, retval);
486 if ((u_long)*retval > (u_long)UINT_MAX) {
487 printf("svr4_32_mmap: retval out of range: 0x%lx",
488 (u_long)*retval);
489 /* Should try to recover and return an error here. */
491 return (error);
496 svr4_32_sys_mmap64(struct lwp *l, const struct svr4_32_sys_mmap64_args *uap, register_t *retval)
498 struct sys_mmap_args mm;
499 int error;
501 * Verify the arguments.
503 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
504 return EINVAL; /* XXX still needed? */
506 if (SCARG(uap, len) == 0)
507 return EINVAL;
509 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
510 return EINVAL;
512 SCARG(&mm, prot) = SCARG(uap, prot);
513 SCARG(&mm, len) = SCARG(uap, len);
514 SCARG(&mm, fd) = SCARG(uap, fd);
515 SCARG(&mm, addr) = SCARG_P32(uap, addr);
516 SCARG(&mm, pos) = SCARG(uap, pos);
518 error = sys_mmap(l, &mm, retval);
519 if ((u_long)*retval > (u_long)UINT_MAX) {
520 printf("svr4_32_mmap64: retval out of range: 0x%lx",
521 (u_long)*retval);
522 /* Should try to recover and return an error here. */
524 return (error);
528 static int
529 svr4_32_mknod(struct lwp *l, register_t *retval, const char *path, svr4_32_mode_t mode, svr4_32_dev_t dev)
531 if (S_ISFIFO(mode)) {
532 struct sys_mkfifo_args ap;
533 SCARG(&ap, path) = path;
534 SCARG(&ap, mode) = mode;
535 return sys_mkfifo(l, &ap, retval);
536 } else {
537 return do_sys_mknod(l, path, mode, dev, retval, UIO_USERSPACE);
543 svr4_32_sys_mknod(struct lwp *l, const struct svr4_32_sys_mknod_args *uap, register_t *retval)
545 return svr4_32_mknod(l, retval,
546 SCARG_P32(uap, path), SCARG(uap, mode),
547 svr4_32_to_bsd_odev_t(SCARG(uap, dev)));
552 svr4_32_sys_xmknod(struct lwp *l, const struct svr4_32_sys_xmknod_args *uap, register_t *retval)
554 return svr4_32_mknod(l, retval,
555 SCARG_P32(uap, path), SCARG(uap, mode),
556 svr4_32_to_bsd_dev_t(SCARG(uap, dev)));
561 svr4_32_sys_vhangup(struct lwp *l, const void *v, register_t *retval)
563 return 0;
568 svr4_32_sys_sysconfig(struct lwp *l, const struct svr4_32_sys_sysconfig_args *uap, register_t *retval)
570 extern u_int maxfiles;
571 int active;
573 switch (SCARG(uap, name)) {
574 case SVR4_CONFIG_NGROUPS:
575 *retval = NGROUPS_MAX;
576 break;
577 case SVR4_CONFIG_CHILD_MAX:
578 *retval = maxproc;
579 break;
580 case SVR4_CONFIG_OPEN_FILES:
581 *retval = maxfiles;
582 break;
583 case SVR4_CONFIG_POSIX_VER:
584 *retval = 198808;
585 break;
586 case SVR4_CONFIG_PAGESIZE:
587 *retval = PAGE_SIZE;
588 break;
589 case SVR4_CONFIG_CLK_TCK:
590 *retval = 60; /* should this be `hz', ie. 100? */
591 break;
592 case SVR4_CONFIG_XOPEN_VER:
593 *retval = 2; /* XXX: What should that be? */
594 break;
595 case SVR4_CONFIG_PROF_TCK:
596 *retval = 60; /* XXX: What should that be? */
597 break;
598 case SVR4_CONFIG_NPROC_CONF:
599 *retval = 1; /* Only one processor for now */
600 break;
601 case SVR4_CONFIG_NPROC_ONLN:
602 *retval = 1; /* And it better be online */
603 break;
604 case SVR4_CONFIG_AIO_LISTIO_MAX:
605 case SVR4_CONFIG_AIO_MAX:
606 case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
607 *retval = 0; /* No aio support */
608 break;
609 case SVR4_CONFIG_DELAYTIMER_MAX:
610 *retval = 0; /* No delaytimer support */
611 break;
612 case SVR4_CONFIG_MQ_OPEN_MAX:
613 #ifdef SYSVMSG
614 *retval = msginfo.msgmni;
615 #else
616 *retval = 0;
617 #endif
618 break;
619 case SVR4_CONFIG_MQ_PRIO_MAX:
620 *retval = 0; /* XXX: Don't know */
621 break;
622 case SVR4_CONFIG_RTSIG_MAX:
623 *retval = 0;
624 break;
625 case SVR4_CONFIG_SEM_NSEMS_MAX:
626 #ifdef SYSVSEM
627 *retval = seminfo.semmni;
628 #else
629 *retval = 0;
630 #endif
631 break;
632 case SVR4_CONFIG_SEM_VALUE_MAX:
633 #ifdef SYSVSEM
634 *retval = seminfo.semvmx;
635 #else
636 *retval = 0;
637 #endif
638 break;
639 case SVR4_CONFIG_SIGQUEUE_MAX:
640 *retval = 0; /* XXX: Don't know */
641 break;
642 case SVR4_CONFIG_SIGRT_MIN:
643 case SVR4_CONFIG_SIGRT_MAX:
644 *retval = 0; /* No real time signals */
645 break;
646 case SVR4_CONFIG_TIMER_MAX:
647 *retval = 3; /* XXX: real, virtual, profiling */
648 break;
649 case SVR4_CONFIG_PHYS_PAGES:
650 *retval = uvmexp.free; /* XXX: free instead of total */
651 break;
652 case SVR4_CONFIG_AVPHYS_PAGES:
653 uvm_estimatepageable(&active, NULL);
654 *retval = active; /* XXX: active instead of avg */
655 break;
656 case SVR4_CONFIG_COHERENCY:
657 *retval = 0; /* XXX */
658 break;
659 case SVR4_CONFIG_SPLIT_CACHE:
660 *retval = 0; /* XXX */
661 break;
662 case SVR4_CONFIG_ICACHESZ:
663 *retval = 256; /* XXX */
664 break;
665 case SVR4_CONFIG_DCACHESZ:
666 *retval = 256; /* XXX */
667 break;
668 case SVR4_CONFIG_ICACHELINESZ:
669 *retval = 64; /* XXX */
670 break;
671 case SVR4_CONFIG_DCACHELINESZ:
672 *retval = 64; /* XXX */
673 break;
674 case SVR4_CONFIG_ICACHEBLKSZ:
675 *retval = 64; /* XXX */
676 break;
677 case SVR4_CONFIG_DCACHEBLKSZ:
678 *retval = 64; /* XXX */
679 break;
680 case SVR4_CONFIG_DCACHETBLKSZ:
681 *retval = 64; /* XXX */
682 break;
683 case SVR4_CONFIG_ICACHE_ASSOC:
684 *retval = 1; /* XXX */
685 break;
686 case SVR4_CONFIG_DCACHE_ASSOC:
687 *retval = 1; /* XXX */
688 break;
689 case SVR4_CONFIG_MAXPID:
690 *retval = PID_MAX;
691 break;
692 case SVR4_CONFIG_STACK_PROT:
693 *retval = PROT_READ|PROT_WRITE|PROT_EXEC;
694 break;
695 default:
696 return EINVAL;
698 return 0;
702 /* ARGSUSED */
704 svr4_32_sys_break(struct lwp *l, const struct svr4_32_sys_break_args *uap, register_t *retval)
706 struct proc *p = l->l_proc;
707 struct vmspace *vm = p->p_vmspace;
708 vaddr_t new, old;
709 int error;
711 old = (vaddr_t) vm->vm_daddr;
712 new = round_page((vaddr_t)SCARG_P32(uap, nsize));
714 if (new - old > p->p_rlimit[RLIMIT_DATA].rlim_cur && new > old)
715 return ENOMEM;
717 old = round_page(old + ctob(vm->vm_dsize));
718 DPRINTF(("break(2): dsize = %x ctob %x\n",
719 vm->vm_dsize, ctob(vm->vm_dsize)));
721 if (new > old) {
722 error = uvm_map(&vm->vm_map, &old, new - old, NULL,
723 UVM_UNKNOWN_OFFSET, 0,
724 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
725 UVM_ADV_NORMAL,
726 UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
727 UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
728 if (error) {
729 uprintf("sbrk: grow failed, return = %d\n", error);
730 return error;
732 vm->vm_dsize += btoc(new - old);
733 } else if (new < old) {
734 uvm_deallocate(&vm->vm_map, new, old - new);
735 vm->vm_dsize -= btoc(old - new);
737 return 0;
741 static inline clock_t
742 timeval_to_clock_t(struct timeval *tv)
744 return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
748 svr4_32_sys_times(struct lwp *l, const struct svr4_32_sys_times_args *uap, register_t *retval)
750 struct tms tms;
751 struct timeval t;
752 struct rusage ru, *rup;
753 struct proc *p = l->l_proc;
755 ru = l->l_proc->p_stats->p_ru;
756 mutex_enter(p->p_lock);
757 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
758 rulwps(p, &ru);
759 mutex_exit(p->p_lock);
761 tms.tms_utime = timeval_to_clock_t(&ru.ru_utime);
762 tms.tms_stime = timeval_to_clock_t(&ru.ru_stime);
764 rup = &l->l_proc->p_stats->p_cru;
765 tms.tms_cutime = timeval_to_clock_t(&rup->ru_utime);
766 tms.tms_cstime = timeval_to_clock_t(&rup->ru_stime);
768 microtime(&t);
769 *retval = timeval_to_clock_t(&t);
771 return copyout(&tms, SCARG_P32(uap, tp), sizeof(tms));
776 svr4_32_sys_ulimit(struct lwp *l, const struct svr4_32_sys_ulimit_args *uap, register_t *retval)
778 struct proc *p = l->l_proc;
779 int error;
780 struct rlimit krl;
781 register_t r;
783 switch (SCARG(uap, cmd)) {
784 case SVR4_GFILLIM:
785 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;
786 break;
788 case SVR4_SFILLIM:
789 krl.rlim_cur = SCARG(uap, newlimit) * 512;
790 krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max;
792 error = dosetrlimit(l, l->l_proc, RLIMIT_FSIZE, &krl);
793 if (error)
794 return error;
796 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
797 break;
799 case SVR4_GMEMLIM:
800 r = p->p_rlimit[RLIMIT_DATA].rlim_cur;
801 if (r > 0x7fffffff)
802 r = 0x7fffffff;
803 r += (long)p->p_vmspace->vm_daddr;
804 break;
806 case SVR4_GDESLIM:
807 r = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
808 break;
810 default:
811 return EINVAL;
814 *retval = r > 0x7fffffff ? 0x7fffffff : r;
815 return 0;
820 svr4_32_sys_pgrpsys(struct lwp *l, const struct svr4_32_sys_pgrpsys_args *uap, register_t *retval)
822 struct proc *p = l->l_proc;
824 switch (SCARG(uap, cmd)) {
825 case 1: /* setpgrp() */
827 * SVR4 setpgrp() (which takes no arguments) has the
828 * semantics that the session ID is also created anew, so
829 * in almost every sense, setpgrp() is identical to
830 * setsid() for SVR4. (Under BSD, the difference is that
831 * a setpgid(0,0) will not create a new session.)
833 sys_setsid(l, NULL, retval);
834 /*FALLTHROUGH*/
836 case 0: /* getpgrp() */
837 *retval = p->p_pgrp->pg_id;
838 return 0;
840 case 2: /* getsid(pid) */
841 if (SCARG(uap, pid) != 0 &&
842 (p = svr4_32_pfind(SCARG(uap, pid))) == NULL)
843 return ESRCH;
845 * This has already been initialized to the pid of
846 * the session leader.
848 *retval = (register_t) p->p_session->s_sid;
849 return 0;
851 case 3: /* setsid() */
852 return sys_setsid(l, NULL, retval);
854 case 4: /* getpgid(pid) */
856 if (SCARG(uap, pid) != 0 &&
857 (p = svr4_32_pfind(SCARG(uap, pid))) == NULL)
858 return ESRCH;
860 *retval = (int) p->p_pgrp->pg_id;
861 return 0;
863 case 5: /* setpgid(pid, pgid); */
865 struct sys_setpgid_args sa;
867 SCARG(&sa, pid) = SCARG(uap, pid);
868 SCARG(&sa, pgid) = SCARG(uap, pgid);
869 return sys_setpgid(l, &sa, retval);
872 default:
873 return EINVAL;
877 struct svr4_32_hrtcntl_args {
878 syscallarg(int) cmd;
879 syscallarg(int) fun;
880 syscallarg(int) clk;
881 syscallarg(svr4_32_hrt_interval_tp) iv;
882 syscallarg(svr4_32_hrt_time_tp) ti;
886 static int
887 svr4_32_hrtcntl(struct proc *p, const struct svr4_32_hrtcntl_args *uap, register_t *retval)
889 switch (SCARG(uap, fun)) {
890 case SVR4_HRT_CNTL_RES:
891 DPRINTF(("htrcntl(RES)\n"));
892 *retval = SVR4_HRT_USEC;
893 return 0;
895 case SVR4_HRT_CNTL_TOFD:
896 DPRINTF(("htrcntl(TOFD)\n"));
898 struct timeval tv;
899 svr4_hrt_time_t t;
900 if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) {
901 DPRINTF(("clk == %d\n", SCARG(uap, clk)));
902 return EINVAL;
904 if (SCARG_P32(uap, ti) == 0) {
905 DPRINTF(("ti NULL\n"));
906 return EINVAL;
908 microtime(&tv);
909 t.h_sec = tv.tv_sec;
910 t.h_rem = tv.tv_usec;
911 t.h_res = SVR4_HRT_USEC;
912 return copyout(&t, SCARG_P32(uap, ti),
913 sizeof(t));
916 case SVR4_HRT_CNTL_START:
917 DPRINTF(("htrcntl(START)\n"));
918 return ENOSYS;
920 case SVR4_HRT_CNTL_GET:
921 DPRINTF(("htrcntl(GET)\n"));
922 return ENOSYS;
923 default:
924 DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun)));
925 return ENOSYS;
931 svr4_32_sys_hrtsys(struct lwp *l, const struct svr4_32_sys_hrtsys_args *uap, register_t *retval)
934 switch (SCARG(uap, cmd)) {
935 case SVR4_HRT_CNTL:
936 return svr4_32_hrtcntl(l->l_proc, (const struct svr4_32_hrtcntl_args *) uap,
937 retval);
939 case SVR4_HRT_ALRM:
940 DPRINTF(("hrtalarm\n"));
941 return ENOSYS;
943 case SVR4_HRT_SLP:
944 DPRINTF(("hrtsleep\n"));
945 return ENOSYS;
947 case SVR4_HRT_CAN:
948 DPRINTF(("hrtcancel\n"));
949 return ENOSYS;
951 default:
952 DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd)));
953 return EINVAL;
958 static int
959 svr4_32_setinfo(int pid, struct rusage *ru, int st, svr4_32_siginfo_tp si)
961 svr4_32_siginfo_t *s = NETBSD32PTR64(si);
962 svr4_32_siginfo_t i;
963 int sig;
965 memset(&i, 0, sizeof(i));
967 i.si_signo = SVR4_SIGCHLD;
968 i.si_errno = 0; /* XXX? */
970 if (pid != 0) {
971 i.si_pid = pid;
972 i.si_stime = ru->ru_stime.tv_sec;
973 i.si_utime = ru->ru_utime.tv_sec;
976 if (WIFEXITED(st)) {
977 i.si_status = WEXITSTATUS(st);
978 i.si_code = SVR4_CLD_EXITED;
979 } else if (WIFSTOPPED(st)) {
980 sig = WSTOPSIG(st);
981 if (sig >= 0 && sig < NSIG)
982 i.si_status = native_to_svr4_signo[sig];
984 if (i.si_status == SVR4_SIGCONT)
985 i.si_code = SVR4_CLD_CONTINUED;
986 else
987 i.si_code = SVR4_CLD_STOPPED;
988 } else {
989 sig = WTERMSIG(st);
990 if (sig >= 0 && sig < NSIG)
991 i.si_status = native_to_svr4_signo[sig];
993 if (WCOREDUMP(st))
994 i.si_code = SVR4_CLD_DUMPED;
995 else
996 i.si_code = SVR4_CLD_KILLED;
999 DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1000 i.si_pid, i.si_signo, i.si_code, i.si_errno, i.si_status));
1002 return copyout(&i, s, sizeof(i));
1007 svr4_32_sys_waitsys(struct lwp *l, const struct svr4_32_sys_waitsys_args *uap, register_t *retval)
1009 int options, error, status;
1010 struct rusage ru;
1011 int id = SCARG(uap, id);
1013 switch (SCARG(uap, grp)) {
1014 case SVR4_P_PID:
1015 break;
1017 case SVR4_P_PGID:
1018 id = -l->l_proc->p_pgid;
1019 break;
1021 case SVR4_P_ALL:
1022 id = WAIT_ANY;
1023 break;
1025 default:
1026 return EINVAL;
1029 DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1030 SCARG(uap, grp), id,
1031 SCARG(uap, info), SCARG(uap, options)));
1033 /* Translate options */
1034 options = WOPTSCHECKED;
1035 if (SCARG(uap, options) & SVR4_WNOWAIT)
1036 options |= WNOWAIT;
1037 if (SCARG(uap, options) & SVR4_WNOHANG)
1038 options |= WNOHANG;
1039 if ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)) == 0)
1040 options |= WNOZOMBIE;
1041 if (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED))
1042 options |= WUNTRACED;
1044 error = do_sys_wait(&id, &status, options, &ru);
1046 retval[0] = id;
1047 if (error != 0)
1048 return error;
1050 return svr4_32_setinfo(id, &ru, status, SCARG(uap, info));
1053 static int
1054 svr4_32_copyout_statvfs(const struct statvfs *bfs, struct svr4_32_statvfs *sufs)
1056 struct svr4_32_statvfs *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1057 int error;
1059 sfs->f_bsize = bfs->f_iosize; /* XXX */
1060 sfs->f_frsize = bfs->f_bsize;
1061 sfs->f_blocks = bfs->f_blocks;
1062 sfs->f_bfree = bfs->f_bfree;
1063 sfs->f_bavail = bfs->f_bavail;
1064 sfs->f_files = bfs->f_files;
1065 sfs->f_ffree = bfs->f_ffree;
1066 sfs->f_favail = bfs->f_ffree;
1067 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1068 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1069 sfs->f_flag = 0;
1070 if (bfs->f_flag & MNT_RDONLY)
1071 sfs->f_flag |= SVR4_ST_RDONLY;
1072 if (bfs->f_flag & MNT_NOSUID)
1073 sfs->f_flag |= SVR4_ST_NOSUID;
1074 sfs->f_namemax = MAXNAMLEN;
1075 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1076 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1078 error = copyout(sfs, sufs, sizeof(*sfs));
1080 free(sfs, M_TEMP);
1081 return error;
1085 static int
1086 svr4_32_copyout_statvfs64(const struct statvfs *bfs, struct svr4_32_statvfs64 *sufs)
1088 struct svr4_32_statvfs64 *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1089 int error;
1091 sfs->f_bsize = bfs->f_iosize; /* XXX */
1092 sfs->f_frsize = bfs->f_bsize;
1093 sfs->f_blocks = bfs->f_blocks;
1094 sfs->f_bfree = bfs->f_bfree;
1095 sfs->f_bavail = bfs->f_bavail;
1096 sfs->f_files = bfs->f_files;
1097 sfs->f_ffree = bfs->f_ffree;
1098 sfs->f_favail = bfs->f_ffree;
1099 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1100 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1101 sfs->f_flag = 0;
1102 if (bfs->f_flag & MNT_RDONLY)
1103 sfs->f_flag |= SVR4_ST_RDONLY;
1104 if (bfs->f_flag & MNT_NOSUID)
1105 sfs->f_flag |= SVR4_ST_NOSUID;
1106 sfs->f_namemax = MAXNAMLEN;
1107 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1108 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1110 error = copyout(sfs, sufs, sizeof(*sfs));
1112 free(sfs, M_TEMP);
1113 return error;
1118 svr4_32_sys_statvfs(struct lwp *l, const struct svr4_32_sys_statvfs_args *uap, register_t *retval)
1120 struct statvfs *sb;
1121 int error;
1123 sb = STATVFSBUF_GET();
1124 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
1125 if (error == 0)
1126 error = svr4_32_copyout_statvfs(sb, SCARG_P32(uap, fs));
1127 STATVFSBUF_PUT(sb);
1128 return error;
1133 svr4_32_sys_fstatvfs(struct lwp *l, const struct svr4_32_sys_fstatvfs_args *uap, register_t *retval)
1135 struct statvfs *sb;
1136 int error;
1138 sb = STATVFSBUF_GET();
1139 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1140 if (error == 0)
1141 error = svr4_32_copyout_statvfs(sb, SCARG_P32(uap, fs));
1142 STATVFSBUF_PUT(sb);
1143 return error;
1148 svr4_32_sys_statvfs64(struct lwp *l, const struct svr4_32_sys_statvfs64_args *uap, register_t *retval)
1150 struct statvfs *sb;
1151 int error;
1153 sb = STATVFSBUF_GET();
1154 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
1155 if (error == 0)
1156 error = svr4_32_copyout_statvfs64(sb, SCARG_P32(uap, fs));
1157 STATVFSBUF_PUT(sb);
1158 return error;
1163 svr4_32_sys_fstatvfs64(struct lwp *l, const struct svr4_32_sys_fstatvfs64_args *uap, register_t *retval)
1165 struct statvfs *sb;
1166 int error;
1168 sb = STATVFSBUF_GET();
1169 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1170 if (error == 0)
1171 error = svr4_32_copyout_statvfs64(sb, SCARG_P32(uap, fs));
1172 STATVFSBUF_PUT(sb);
1173 return error;
1179 svr4_32_sys_alarm(struct lwp *l, const struct svr4_32_sys_alarm_args *uap, register_t *retval)
1181 struct itimerval tp;
1183 dogetitimer(l->l_proc, ITIMER_REAL, &tp);
1184 if (tp.it_value.tv_usec)
1185 tp.it_value.tv_sec++;
1186 *retval = (register_t)tp.it_value.tv_sec;
1188 timerclear(&tp.it_interval);
1189 tp.it_value.tv_sec = SCARG(uap, sec);
1190 tp.it_value.tv_usec = 0;
1192 return dosetitimer(l->l_proc, ITIMER_REAL, &tp);
1197 svr4_32_sys_gettimeofday(struct lwp *l, const struct svr4_32_sys_gettimeofday_args *uap, register_t *retval)
1200 if (SCARG_P32(uap, tp)) {
1201 struct timeval atv;
1203 microtime(&atv);
1204 return copyout(&atv, SCARG_P32(uap, tp), sizeof (atv));
1207 return 0;
1212 svr4_32_sys_facl(struct lwp *l, const struct svr4_32_sys_facl_args *uap, register_t *retval)
1215 *retval = 0;
1217 switch (SCARG(uap, cmd)) {
1218 case SVR4_SYS_SETACL:
1219 /* We don't support acls on any filesystem */
1220 return ENOSYS;
1222 case SVR4_SYS_GETACL:
1223 return 0;
1225 return copyout(retval, &SCARG(uap, num),
1226 sizeof(SCARG(uap, num)));
1229 case SVR4_SYS_GETACLCNT:
1230 return 0;
1232 default:
1233 return EINVAL;
1239 svr4_32_sys_acl(struct lwp *l, const struct svr4_32_sys_acl_args *uap, register_t *retval)
1241 return svr4_32_sys_facl(l, (const void *)uap, retval); /* XXX: for now the same */
1246 svr4_32_sys_auditsys(struct lwp *l, const struct svr4_32_sys_auditsys_args *uap, register_t *retval)
1249 * XXX: Big brother is *not* watching.
1251 return 0;
1256 svr4_32_sys_memcntl(struct lwp *l, const struct svr4_32_sys_memcntl_args *uap, register_t *retval)
1258 switch (SCARG(uap, cmd)) {
1259 case SVR4_MC_SYNC:
1261 struct sys___msync13_args msa;
1263 SCARG(&msa, addr) = SCARG_P32(uap, addr);
1264 SCARG(&msa, len) = SCARG(uap, len);
1265 SCARG(&msa, flags) = (uintptr_t)SCARG_P32(uap, arg);
1267 return sys___msync13(l, &msa, retval);
1269 case SVR4_MC_ADVISE:
1271 struct sys_madvise_args maa;
1273 SCARG(&maa, addr) = SCARG_P32(uap, addr);
1274 SCARG(&maa, len) = SCARG(uap, len);
1275 SCARG(&maa, behav) = (uintptr_t)SCARG_P32(uap, arg);
1277 return sys_madvise(l, &maa, retval);
1279 case SVR4_MC_LOCK:
1280 case SVR4_MC_UNLOCK:
1281 case SVR4_MC_LOCKAS:
1282 case SVR4_MC_UNLOCKAS:
1283 return EOPNOTSUPP;
1284 default:
1285 return ENOSYS;
1291 svr4_32_sys_nice(struct lwp *l, const struct svr4_32_sys_nice_args *uap, register_t *retval)
1293 struct sys_setpriority_args ap;
1294 int error;
1296 SCARG(&ap, which) = PRIO_PROCESS;
1297 SCARG(&ap, who) = 0;
1298 SCARG(&ap, prio) = SCARG(uap, prio);
1300 if ((error = sys_setpriority(l, &ap, retval)) != 0)
1301 return error;
1303 if ((error = sys_getpriority(l, (const void *)&ap, retval)) != 0)
1304 return error;
1306 return 0;
1311 svr4_32_sys_resolvepath(struct lwp *l, const struct svr4_32_sys_resolvepath_args *uap, register_t *retval)
1313 struct nameidata nd;
1314 int error;
1315 size_t len;
1317 NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | TRYEMULROOT, UIO_USERSPACE,
1318 SCARG_P32(uap, path));
1320 if ((error = namei(&nd)) != 0)
1321 return error;
1323 if ((error = copyoutstr(nd.ni_cnd.cn_pnbuf,
1324 SCARG_P32(uap, buf),
1325 SCARG(uap, bufsiz), &len)) != 0)
1326 goto bad;
1328 *retval = len;
1329 bad:
1330 vrele(nd.ni_vp);
1331 PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
1332 return error;