1 /* $NetBSD: svr4_misc.c,v 1.144.6.1 2010/03/17 02:59:52 snj Exp $ */
2
3 /*-
4 * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas.
9 *
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.
18 *
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.
30 */
31
32 /*
33 * SVR4 compatibility module.
34 *
35 * SVR4 system calls that are implemented differently in BSD are
36 * handled here.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: svr4_misc.c,v 1.144.6.1 2010/03/17 02:59:52 snj Exp $");
41
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>
72
73 #include <netinet/in.h>
74 #include <sys/syscallargs.h>
75
76 #include <miscfs/specfs/specdev.h>
77
78 #include <compat/svr4/svr4_types.h>
79 #include <compat/svr4/svr4_signal.h>
80 #include <compat/svr4/svr4_lwp.h>
81 #include <compat/svr4/svr4_ucontext.h>
82 #include <compat/svr4/svr4_syscallargs.h>
83 #include <compat/svr4/svr4_util.h>
84 #include <compat/svr4/svr4_time.h>
85 #include <compat/svr4/svr4_dirent.h>
86 #include <compat/svr4/svr4_ulimit.h>
87 #include <compat/svr4/svr4_hrt.h>
88 #include <compat/svr4/svr4_wait.h>
89 #include <compat/svr4/svr4_statvfs.h>
90 #include <compat/svr4/svr4_sysconfig.h>
91 #include <compat/svr4/svr4_acl.h>
92 #include <compat/svr4/svr4_mman.h>
93
94 #include <sys/cpu.h>
95
96 #include <uvm/uvm_extern.h>
97
98 static int svr4_to_bsd_mmap_flags(int);
99
100 static inline clock_t timeval_to_clock_t(struct timeval *);
101 static void svr4_setinfo(int, struct rusage *, int, svr4_siginfo_t *);
102
103 struct svr4_hrtcntl_args;
104 static int svr4_hrtcntl(struct lwp *, const struct svr4_hrtcntl_args *,
105 register_t *);
106 #define svr4_pfind(pid) p_find((pid), PFIND_UNLOCK | PFIND_ZOMBIE)
107
108 static int svr4_mknod(struct lwp *, register_t *, const char *,
109 svr4_mode_t, svr4_dev_t);
110
111 int
112 svr4_sys_wait(struct lwp *l, const struct svr4_sys_wait_args *uap, register_t *retval)
113 {
114 int error, was_zombie;
115 int st, sig;
116 int pid = WAIT_ANY;
117
118 error = do_sys_wait(l, &pid, &st, 0, NULL, &was_zombie);
119
120 retval[0] = pid;
121 if (pid == 0)
122 return error;
123
124 if (WIFSIGNALED(st)) {
125 sig = WTERMSIG(st);
126 if (sig >= 0 && sig < NSIG)
127 st = (st & ~0177) | native_to_svr4_signo[sig];
128 } else if (WIFSTOPPED(st)) {
129 sig = WSTOPSIG(st);
130 if (sig >= 0 && sig < NSIG)
131 st = (st & ~0xff00) | (native_to_svr4_signo[sig] << 8);
132 }
133
134 /*
135 * It looks like wait(2) on svr4/solaris/2.4 returns
136 * the status in retval[1], and the pid on retval[0].
137 */
138 retval[1] = st;
139
140 if (SCARG(uap, status))
141 error = copyout(&st, SCARG(uap, status), sizeof(st));
142
143 return error;
144 }
145
146
147 int
148 svr4_sys_execv(struct lwp *l, const struct svr4_sys_execv_args *uap, register_t *retval)
149 {
150 /* {
151 syscallarg(char *) path;
152 syscallarg(char **) argv;
153 } */
154 struct sys_execve_args ap;
155
156 SCARG(&ap, path) = SCARG(uap, path);
157 SCARG(&ap, argp) = SCARG(uap, argp);
158 SCARG(&ap, envp) = NULL;
159
160 return sys_execve(l, &ap, retval);
161 }
162
163
164 int
165 svr4_sys_execve(struct lwp *l, const struct svr4_sys_execve_args *uap, register_t *retval)
166 {
167 /* {
168 syscallarg(const char *) path;
169 syscallarg(char **) argv;
170 syscallarg(char **) envp;
171 } */
172 struct sys_execve_args ap;
173
174 SCARG(&ap, path) = SCARG(uap, path);
175 SCARG(&ap, argp) = SCARG(uap, argp);
176 SCARG(&ap, envp) = SCARG(uap, envp);
177
178 return sys_execve(l, &ap, retval);
179 }
180
181
182 int
183 svr4_sys_time(struct lwp *l, const struct svr4_sys_time_args *uap, register_t *retval)
184 {
185 int error = 0;
186 struct timeval tv;
187
188 microtime(&tv);
189 if (SCARG(uap, t))
190 error = copyout(&tv.tv_sec, SCARG(uap, t),
191 sizeof(*(SCARG(uap, t))));
192 *retval = (int) tv.tv_sec;
193
194 return error;
195 }
196
197
198 /*
199 * Read SVR4-style directory entries. We suck them into kernel space so
200 * that they can be massaged before being copied out to user code. Like
201 * SunOS, we squish out `empty' entries.
202 *
203 * This is quite ugly, but what do you expect from compatibility code?
204 */
205 int
206 svr4_sys_getdents64(struct lwp *l, const struct svr4_sys_getdents64_args *uap, register_t *retval)
207 {
208 struct dirent *bdp;
209 struct vnode *vp;
210 char *inp, *tbuf; /* BSD-format */
211 int len, reclen; /* BSD-format */
212 char *outp; /* SVR4-format */
213 int resid, svr4_reclen; /* SVR4-format */
214 struct file *fp;
215 struct uio auio;
216 struct iovec aiov;
217 struct svr4_dirent64 idb;
218 off_t off; /* true file offset */
219 int buflen, error, eofflag;
220 off_t *cookiebuf = NULL, *cookie;
221 int ncookies;
222
223 /* fd_getvnode() will use the descriptor for us */
224 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
225 return (error);
226
227 if ((fp->f_flag & FREAD) == 0) {
228 error = EBADF;
229 goto out1;
230 }
231
232 vp = (struct vnode *)fp->f_data;
233 if (vp->v_type != VDIR) {
234 error = EINVAL;
235 goto out1;
236 }
237
238 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
239 tbuf = malloc(buflen, M_TEMP, M_WAITOK);
240 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
241 off = fp->f_offset;
242 again:
243 aiov.iov_base = tbuf;
244 aiov.iov_len = buflen;
245 auio.uio_iov = &aiov;
246 auio.uio_iovcnt = 1;
247 auio.uio_rw = UIO_READ;
248 auio.uio_resid = buflen;
249 auio.uio_offset = off;
250 UIO_SETUP_SYSSPACE(&auio);
251 /*
252 * First we read into the malloc'ed buffer, then
253 * we massage it into user space, one record at a time.
254 */
255 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
256 &ncookies);
257 if (error)
258 goto out;
259
260 inp = tbuf;
261 outp = (char *) SCARG(uap, dp);
262 resid = SCARG(uap, nbytes);
263 if ((len = buflen - auio.uio_resid) == 0)
264 goto eof;
265
266 for (cookie = cookiebuf; len > 0; len -= reclen) {
267 bdp = (struct dirent *)inp;
268 reclen = bdp->d_reclen;
269 if (reclen & 3)
270 panic("svr4_getdents64: bad reclen");
271 if (bdp->d_fileno == 0) {
272 inp += reclen; /* it is a hole; squish it out */
273 if (cookie)
274 off = *cookie++;
275 else
276 off += reclen;
277 continue;
278 }
279 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
280 if (reclen > len || resid < svr4_reclen) {
281 /* entry too big for buffer, so just stop */
282 outp++;
283 break;
284 }
285 if (cookie)
286 off = *cookie++; /* each entry points to the next */
287 else
288 off += reclen;
289 /*
290 * Massage in place to make a SVR4-shaped dirent (otherwise
291 * we have to worry about touching user memory outside of
292 * the copyout() call).
293 */
294 idb.d_ino = (svr4_ino64_t)bdp->d_fileno;
295 idb.d_off = (svr4_off64_t)off;
296 idb.d_reclen = (u_short)svr4_reclen;
297 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
298 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
299 goto out;
300 /* advance past this real entry */
301 inp += reclen;
302 /* advance output past SVR4-shaped entry */
303 outp += svr4_reclen;
304 resid -= svr4_reclen;
305 }
306
307 /* if we squished out the whole block, try again */
308 if (outp == (char *) SCARG(uap, dp)) {
309 if (cookiebuf)
310 free(cookiebuf, M_TEMP);
311 cookiebuf = NULL;
312 goto again;
313 }
314 fp->f_offset = off; /* update the vnode offset */
315
316 eof:
317 *retval = SCARG(uap, nbytes) - resid;
318 out:
319 VOP_UNLOCK(vp, 0);
320 if (cookiebuf)
321 free(cookiebuf, M_TEMP);
322 free(tbuf, M_TEMP);
323 out1:
324 fd_putfile(SCARG(uap, fd));
325 return error;
326 }
327
328
329 int
330 svr4_sys_getdents(struct lwp *l, const struct svr4_sys_getdents_args *uap, register_t *retval)
331 {
332 struct dirent *bdp;
333 struct vnode *vp;
334 char *inp, *tbuf; /* BSD-format */
335 int len, reclen; /* BSD-format */
336 char *outp; /* SVR4-format */
337 int resid, svr4_reclen; /* SVR4-format */
338 struct file *fp;
339 struct uio auio;
340 struct iovec aiov;
341 struct svr4_dirent idb;
342 off_t off; /* true file offset */
343 int buflen, error, eofflag;
344 off_t *cookiebuf = NULL, *cookie;
345 int ncookies;
346
347 /* fd_getvnode() will use the descriptor for us */
348 if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
349 return (error);
350
351 if ((fp->f_flag & FREAD) == 0) {
352 error = EBADF;
353 goto out1;
354 }
355
356 vp = (struct vnode *)fp->f_data;
357 if (vp->v_type != VDIR) {
358 error = EINVAL;
359 goto out1;
360 }
361
362 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
363 tbuf = malloc(buflen, M_TEMP, M_WAITOK);
364 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
365 off = fp->f_offset;
366 again:
367 aiov.iov_base = tbuf;
368 aiov.iov_len = buflen;
369 auio.uio_iov = &aiov;
370 auio.uio_iovcnt = 1;
371 auio.uio_rw = UIO_READ;
372 auio.uio_resid = buflen;
373 auio.uio_offset = off;
374 UIO_SETUP_SYSSPACE(&auio);
375 /*
376 * First we read into the malloc'ed buffer, then
377 * we massage it into user space, one record at a time.
378 */
379 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
380 &ncookies);
381 if (error)
382 goto out;
383
384 inp = tbuf;
385 outp = SCARG(uap, buf);
386 resid = SCARG(uap, nbytes);
387 if ((len = buflen - auio.uio_resid) == 0)
388 goto eof;
389
390 for (cookie = cookiebuf; len > 0; len -= reclen) {
391 bdp = (struct dirent *)inp;
392 reclen = bdp->d_reclen;
393 if (reclen & 3)
394 panic("svr4_getdents: bad reclen");
395 if (cookie)
396 off = *cookie++; /* each entry points to the next */
397 else
398 off += reclen;
399 if ((off >> 32) != 0) {
400 compat_offseterr(vp, "svr4_getdents");
401 error = EINVAL;
402 goto out;
403 }
404 if (bdp->d_fileno == 0) {
405 inp += reclen; /* it is a hole; squish it out */
406 continue;
407 }
408 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
409 if (reclen > len || resid < svr4_reclen) {
410 /* entry too big for buffer, so just stop */
411 outp++;
412 break;
413 }
414 /*
415 * Massage in place to make a SVR4-shaped dirent (otherwise
416 * we have to worry about touching user memory outside of
417 * the copyout() call).
418 */
419 idb.d_ino = (svr4_ino_t)bdp->d_fileno;
420 idb.d_off = (svr4_off_t)off;
421 idb.d_reclen = (u_short)svr4_reclen;
422 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
423 if ((error = copyout((void *)&idb, outp, svr4_reclen)))
424 goto out;
425 /* advance past this real entry */
426 inp += reclen;
427 /* advance output past SVR4-shaped entry */
428 outp += svr4_reclen;
429 resid -= svr4_reclen;
430 }
431
432 /* if we squished out the whole block, try again */
433 if (outp == SCARG(uap, buf)) {
434 if (cookiebuf)
435 free(cookiebuf, M_TEMP);
436 cookiebuf = NULL;
437 goto again;
438 }
439 fp->f_offset = off; /* update the vnode offset */
440
441 eof:
442 *retval = SCARG(uap, nbytes) - resid;
443 out:
444 VOP_UNLOCK(vp, 0);
445 if (cookiebuf)
446 free(cookiebuf, M_TEMP);
447 free(tbuf, M_TEMP);
448 out1:
449 fd_putfile(SCARG(uap, fd));
450 return error;
451 }
452
453
454 static int
455 svr4_to_bsd_mmap_flags(int f)
456 {
457 int type = f & SVR4_MAP_TYPE;
458 int nf;
459
460 if (type != MAP_PRIVATE && type != MAP_SHARED)
461 return -1;
462
463 nf = f & SVR4_MAP_COPYFLAGS;
464 if (f & SVR4_MAP_ANON)
465 nf |= MAP_ANON;
466
467 return nf;
468 }
469
470
471 int
472 svr4_sys_mmap(struct lwp *l, const struct svr4_sys_mmap_args *uap, register_t *retval)
473 {
474 struct sys_mmap_args mm;
475 /*
476 * Verify the arguments.
477 */
478 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
479 return EINVAL; /* XXX still needed? */
480
481 if (SCARG(uap, len) == 0)
482 return EINVAL;
483
484 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
485 return EINVAL;
486
487 SCARG(&mm, prot) = SCARG(uap, prot);
488 SCARG(&mm, len) = SCARG(uap, len);
489 SCARG(&mm, fd) = SCARG(uap, fd);
490 SCARG(&mm, addr) = SCARG(uap, addr);
491 SCARG(&mm, pos) = SCARG(uap, pos);
492
493 return sys_mmap(l, &mm, retval);
494 }
495
496
497 int
498 svr4_sys_mmap64(struct lwp *l, const struct svr4_sys_mmap64_args *uap, register_t *retval)
499 {
500 struct sys_mmap_args mm;
501 /*
502 * Verify the arguments.
503 */
504 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
505 return EINVAL; /* XXX still needed? */
506
507 if (SCARG(uap, len) == 0)
508 return EINVAL;
509
510 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
511 return EINVAL;
512
513 SCARG(&mm, prot) = SCARG(uap, prot);
514 SCARG(&mm, len) = SCARG(uap, len);
515 SCARG(&mm, fd) = SCARG(uap, fd);
516 SCARG(&mm, addr) = SCARG(uap, addr);
517 SCARG(&mm, pos) = SCARG(uap, pos);
518
519 return sys_mmap(l, &mm, retval);
520 }
521
522
523 static int
524 svr4_mknod(struct lwp *l, register_t *retval, const char *path, svr4_mode_t mode, svr4_dev_t dev)
525 {
526 if (S_ISFIFO(mode)) {
527 struct sys_mkfifo_args ap;
528 SCARG(&ap, path) = path;
529 SCARG(&ap, mode) = mode;
530 return sys_mkfifo(l, &ap, retval);
531 } else {
532 struct sys_mknod_args ap;
533 SCARG(&ap, path) = path;
534 SCARG(&ap, mode) = mode;
535 SCARG(&ap, dev) = dev;
536 return sys_mknod(l, &ap, retval);
537 }
538 }
539
540
541 int
542 svr4_sys_mknod(struct lwp *l, const struct svr4_sys_mknod_args *uap, register_t *retval)
543 {
544 return svr4_mknod(l, retval,
545 SCARG(uap, path), SCARG(uap, mode),
546 svr4_to_bsd_odev_t(SCARG(uap, dev)));
547 }
548
549
550 int
551 svr4_sys_xmknod(struct lwp *l, const struct svr4_sys_xmknod_args *uap, register_t *retval)
552 {
553 return svr4_mknod(l, retval,
554 SCARG(uap, path), SCARG(uap, mode),
555 svr4_to_bsd_dev_t(SCARG(uap, dev)));
556 }
557
558
559 int
560 svr4_sys_vhangup(struct lwp *l, const void *v, register_t *retval)
561 {
562 return 0;
563 }
564
565
566 int
567 svr4_sys_sysconfig(struct lwp *l, const struct svr4_sys_sysconfig_args *uap, register_t *retval)
568 {
569 int active;
570
571 switch (SCARG(uap, name)) {
572 case SVR4_CONFIG_NGROUPS:
573 *retval = NGROUPS_MAX;
574 break;
575 case SVR4_CONFIG_CHILD_MAX:
576 *retval = maxproc;
577 break;
578 case SVR4_CONFIG_OPEN_FILES:
579 *retval = maxfiles;
580 break;
581 case SVR4_CONFIG_POSIX_VER:
582 *retval = 198808;
583 break;
584 case SVR4_CONFIG_PAGESIZE:
585 *retval = PAGE_SIZE;
586 break;
587 case SVR4_CONFIG_CLK_TCK:
588 *retval = 60; /* should this be `hz', ie. 100? */
589 break;
590 case SVR4_CONFIG_XOPEN_VER:
591 *retval = 2; /* XXX: What should that be? */
592 break;
593 case SVR4_CONFIG_PROF_TCK:
594 *retval = 60; /* XXX: What should that be? */
595 break;
596 case SVR4_CONFIG_NPROC_CONF:
597 *retval = 1; /* Only one processor for now */
598 break;
599 case SVR4_CONFIG_NPROC_ONLN:
600 *retval = 1; /* And it better be online */
601 break;
602 case SVR4_CONFIG_AIO_LISTIO_MAX:
603 case SVR4_CONFIG_AIO_MAX:
604 case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
605 *retval = 0; /* No aio support */
606 break;
607 case SVR4_CONFIG_DELAYTIMER_MAX:
608 *retval = 0; /* No delaytimer support */
609 break;
610 case SVR4_CONFIG_MQ_OPEN_MAX:
611 #ifdef SYSVMSG
612 *retval = msginfo.msgmni;
613 #else
614 *retval = 0;
615 #endif
616 break;
617 case SVR4_CONFIG_MQ_PRIO_MAX:
618 *retval = 0; /* XXX: Don't know */
619 break;
620 case SVR4_CONFIG_RTSIG_MAX:
621 *retval = 0;
622 break;
623 case SVR4_CONFIG_SEM_NSEMS_MAX:
624 #ifdef SYSVSEM
625 *retval = seminfo.semmni;
626 #else
627 *retval = 0;
628 #endif
629 break;
630 case SVR4_CONFIG_SEM_VALUE_MAX:
631 #ifdef SYSVSEM
632 *retval = seminfo.semvmx;
633 #else
634 *retval = 0;
635 #endif
636 break;
637 case SVR4_CONFIG_SIGQUEUE_MAX:
638 *retval = 0; /* XXX: Don't know */
639 break;
640 case SVR4_CONFIG_SIGRT_MIN:
641 case SVR4_CONFIG_SIGRT_MAX:
642 *retval = 0; /* No real time signals */
643 break;
644 case SVR4_CONFIG_TIMER_MAX:
645 *retval = 3; /* XXX: real, virtual, profiling */
646 break;
647 case SVR4_CONFIG_PHYS_PAGES:
648 *retval = uvmexp.free; /* XXX: free instead of total */
649 break;
650 case SVR4_CONFIG_AVPHYS_PAGES:
651 uvm_estimatepageable(&active, NULL);
652 *retval = active; /* XXX: active instead of avg */
653 break;
654 case SVR4_CONFIG_COHERENCY:
655 *retval = 0; /* XXX */
656 break;
657 case SVR4_CONFIG_SPLIT_CACHE:
658 *retval = 0; /* XXX */
659 break;
660 case SVR4_CONFIG_ICACHESZ:
661 *retval = 256; /* XXX */
662 break;
663 case SVR4_CONFIG_DCACHESZ:
664 *retval = 256; /* XXX */
665 break;
666 case SVR4_CONFIG_ICACHELINESZ:
667 *retval = 64; /* XXX */
668 break;
669 case SVR4_CONFIG_DCACHELINESZ:
670 *retval = 64; /* XXX */
671 break;
672 case SVR4_CONFIG_ICACHEBLKSZ:
673 *retval = 64; /* XXX */
674 break;
675 case SVR4_CONFIG_DCACHEBLKSZ:
676 *retval = 64; /* XXX */
677 break;
678 case SVR4_CONFIG_DCACHETBLKSZ:
679 *retval = 64; /* XXX */
680 break;
681 case SVR4_CONFIG_ICACHE_ASSOC:
682 *retval = 1; /* XXX */
683 break;
684 case SVR4_CONFIG_DCACHE_ASSOC:
685 *retval = 1; /* XXX */
686 break;
687 case SVR4_CONFIG_MAXPID:
688 *retval = PID_MAX;
689 break;
690 case SVR4_CONFIG_STACK_PROT:
691 *retval = PROT_READ|PROT_WRITE|PROT_EXEC;
692 break;
693 default:
694 return EINVAL;
695 }
696 return 0;
697 }
698
699 /* ARGSUSED */
700 int
701 svr4_sys_break(struct lwp *l, const struct svr4_sys_break_args *uap, register_t *retval)
702 {
703 struct proc *p = l->l_proc;
704 struct vmspace *vm = p->p_vmspace;
705 vaddr_t new, old;
706 int error;
707
708 old = (vaddr_t) vm->vm_daddr;
709 new = round_page((vaddr_t)SCARG(uap, nsize));
710
711 if (new - old > p->p_rlimit[RLIMIT_DATA].rlim_cur && new > old)
712 return ENOMEM;
713
714 old = round_page(old + ctob(vm->vm_dsize));
715 DPRINTF(("break(2): dsize = %x ctob %x\n",
716 vm->vm_dsize, ctob(vm->vm_dsize)));
717
718 if (new > old) {
719 error = uvm_map(&vm->vm_map, &old, new - old, NULL,
720 UVM_UNKNOWN_OFFSET, 0,
721 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
722 UVM_ADV_NORMAL,
723 UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
724 UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
725 if (error) {
726 uprintf("sbrk: grow failed, error = %d\n", error);
727 return error;
728 }
729 vm->vm_dsize += btoc(new - old);
730 } else if (new < old) {
731 uvm_deallocate(&vm->vm_map, new, old - new);
732 vm->vm_dsize -= btoc(old - new);
733 }
734 return 0;
735 }
736
737
738 static inline clock_t
739 timeval_to_clock_t(struct timeval *tv)
740 {
741 return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
742 }
743
744
745 int
746 svr4_sys_times(struct lwp *l, const struct svr4_sys_times_args *uap, register_t *retval)
747 {
748 struct tms tms;
749 struct timeval t;
750 struct rusage ru, *rup;
751 struct proc *p = l->l_proc;
752
753 ru = p->p_stats->p_ru;
754 mutex_enter(p->p_lock);
755 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
756 rulwps(p, &ru);
757 mutex_exit(p->p_lock);
758
759 tms.tms_utime = timeval_to_clock_t(&ru.ru_utime);
760 tms.tms_stime = timeval_to_clock_t(&ru.ru_stime);
761
762 rup = &p->p_stats->p_cru;
763 tms.tms_cutime = timeval_to_clock_t(&rup->ru_utime);
764 tms.tms_cstime = timeval_to_clock_t(&rup->ru_stime);
765
766 microtime(&t);
767 *retval = timeval_to_clock_t(&t);
768
769 return copyout(&tms, SCARG(uap, tp), sizeof(tms));
770 }
771
772
773 int
774 svr4_sys_ulimit(struct lwp *l, const struct svr4_sys_ulimit_args *uap, register_t *retval)
775 {
776 struct proc *p = l->l_proc;
777 int error;
778 struct rlimit krl;
779 register_t r;
780
781 switch (SCARG(uap, cmd)) {
782 case SVR4_GFILLIM:
783 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;
784 break;
785
786 case SVR4_SFILLIM:
787 krl.rlim_cur = SCARG(uap, newlimit) * 512;
788 krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max;
789
790 error = dosetrlimit(l, l->l_proc, RLIMIT_FSIZE, &krl);
791 if (error)
792 return error;
793
794 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
795 break;
796
797 case SVR4_GMEMLIM:
798 r = p->p_rlimit[RLIMIT_DATA].rlim_cur;
799 if (r > 0x7fffffff)
800 r = 0x7fffffff;
801 r += (long)p->p_vmspace->vm_daddr;
802 break;
803
804 case SVR4_GDESLIM:
805 r = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
806 break;
807
808 default:
809 return EINVAL;
810 }
811
812 *retval = r > 0x7fffffff ? 0x7fffffff : r;
813 return 0;
814 }
815
816
817 int
818 svr4_sys_pgrpsys(struct lwp *l, const struct svr4_sys_pgrpsys_args *uap, register_t *retval)
819 {
820 struct proc *p = l->l_proc;
821
822 switch (SCARG(uap, cmd)) {
823 case 1: /* setpgrp() */
824 /*
825 * SVR4 setpgrp() (which takes no arguments) has the
826 * semantics that the session ID is also created anew, so
827 * in almost every sense, setpgrp() is identical to
828 * setsid() for SVR4. (Under BSD, the difference is that
829 * a setpgid(0,0) will not create a new session.)
830 */
831 sys_setsid(l, NULL, retval);
832 /*FALLTHROUGH*/
833
834 case 0: /* getpgrp() */
835 mutex_enter(proc_lock);
836 *retval = p->p_pgrp->pg_id;
837 mutex_exit(proc_lock);
838 return 0;
839
840 case 2: /* getsid(pid) */
841 mutex_enter(proc_lock);
842 if (SCARG(uap, pid) != 0 &&
843 (p = p_find(SCARG(uap, pid), PFIND_LOCKED | PFIND_ZOMBIE)) == NULL) {
844 mutex_exit(proc_lock);
845 return ESRCH;
846 }
847 /*
848 * This has already been initialized to the pid of
849 * the session leader.
850 */
851 *retval = (register_t) p->p_session->s_sid;
852 mutex_exit(proc_lock);
853 return 0;
854
855 case 3: /* setsid() */
856 return sys_setsid(l, NULL, retval);
857
858 case 4: /* getpgid(pid) */
859 mutex_enter(proc_lock);
860 if (SCARG(uap, pid) != 0 &&
861 (p = p_find(SCARG(uap, pid), PFIND_LOCKED | PFIND_ZOMBIE)) == NULL) {
862 mutex_exit(proc_lock);
863 return ESRCH;
864 }
865
866 *retval = (int) p->p_pgrp->pg_id;
867 mutex_exit(proc_lock);
868 return 0;
869
870 case 5: /* setpgid(pid, pgid); */
871 {
872 struct sys_setpgid_args sa;
873
874 SCARG(&sa, pid) = SCARG(uap, pid);
875 SCARG(&sa, pgid) = SCARG(uap, pgid);
876 return sys_setpgid(l, &sa, retval);
877 }
878
879 default:
880 return EINVAL;
881 }
882 }
883
884 struct svr4_hrtcntl_args {
885 syscallarg(int) cmd;
886 syscallarg(int) fun;
887 syscallarg(int) clk;
888 syscallarg(svr4_hrt_interval_t *) iv;
889 syscallarg(svr4_hrt_time_t *) ti;
890 };
891
892
893 static int
894 svr4_hrtcntl(struct lwp *l, const struct svr4_hrtcntl_args *uap,
895 register_t *retval)
896 {
897 switch (SCARG(uap, fun)) {
898 case SVR4_HRT_CNTL_RES:
899 DPRINTF(("htrcntl(RES)\n"));
900 *retval = SVR4_HRT_USEC;
901 return 0;
902
903 case SVR4_HRT_CNTL_TOFD:
904 DPRINTF(("htrcntl(TOFD)\n"));
905 {
906 struct timeval tv;
907 svr4_hrt_time_t t;
908 if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) {
909 DPRINTF(("clk == %d\n", SCARG(uap, clk)));
910 return EINVAL;
911 }
912 if (SCARG(uap, ti) == NULL) {
913 DPRINTF(("ti NULL\n"));
914 return EINVAL;
915 }
916 microtime(&tv);
917 t.h_sec = tv.tv_sec;
918 t.h_rem = tv.tv_usec;
919 t.h_res = SVR4_HRT_USEC;
920 return copyout(&t, SCARG(uap, ti), sizeof(t));
921 }
922
923 case SVR4_HRT_CNTL_START:
924 DPRINTF(("htrcntl(START)\n"));
925 return ENOSYS;
926
927 case SVR4_HRT_CNTL_GET:
928 DPRINTF(("htrcntl(GET)\n"));
929 return ENOSYS;
930 default:
931 DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun)));
932 return ENOSYS;
933 }
934 }
935
936
937 int
938 svr4_sys_hrtsys(struct lwp *l, const struct svr4_sys_hrtsys_args *uap, register_t *retval)
939 {
940
941 switch (SCARG(uap, cmd)) {
942 case SVR4_HRT_CNTL:
943 return svr4_hrtcntl(l, (const struct svr4_hrtcntl_args *) uap,
944 retval);
945
946 case SVR4_HRT_ALRM:
947 DPRINTF(("hrtalarm\n"));
948 return ENOSYS;
949
950 case SVR4_HRT_SLP:
951 DPRINTF(("hrtsleep\n"));
952 return ENOSYS;
953
954 case SVR4_HRT_CAN:
955 DPRINTF(("hrtcancel\n"));
956 return ENOSYS;
957
958 default:
959 DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd)));
960 return EINVAL;
961 }
962 }
963
964
965 static void
966 svr4_setinfo(int pid, struct rusage *ru, int st, svr4_siginfo_t *s)
967 {
968 int sig;
969
970 memset(s, 0, sizeof(*s));
971
972 s->si_signo = SVR4_SIGCHLD;
973 s->si_errno = 0; /* XXX? */
974
975 if (pid != 0) {
976 s->si_pid = pid;
977 s->si_stime = ru->ru_stime.tv_sec;
978 s->si_utime = ru->ru_utime.tv_sec;
979 }
980
981 if (WIFEXITED(st)) {
982 s->si_status = WEXITSTATUS(st);
983 s->si_code = SVR4_CLD_EXITED;
984 } else if (WIFSTOPPED(st)) {
985 sig = WSTOPSIG(st);
986 if (sig >= 0 && sig < NSIG)
987 s->si_status = native_to_svr4_signo[sig];
988
989 if (s->si_status == SVR4_SIGCONT)
990 s->si_code = SVR4_CLD_CONTINUED;
991 else
992 s->si_code = SVR4_CLD_STOPPED;
993 } else {
994 sig = WTERMSIG(st);
995 if (sig >= 0 && sig < NSIG)
996 s->si_status = native_to_svr4_signo[sig];
997
998 if (WCOREDUMP(st))
999 s->si_code = SVR4_CLD_DUMPED;
1000 else
1001 s->si_code = SVR4_CLD_KILLED;
1002 }
1003
1004 DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1005 (long) s->si_pid,
1006 s->si_signo, s->si_code, s->si_errno, s->si_status));
1007 }
1008
1009
1010 int
1011 svr4_sys_waitsys(struct lwp *l, const struct svr4_sys_waitsys_args *uap, register_t *retval)
1012 {
1013 int options, status;
1014 int error;
1015 int was_zombie;
1016 struct rusage ru;
1017 svr4_siginfo_t i;
1018 int id = SCARG(uap, id);
1019
1020 switch (SCARG(uap, grp)) {
1021 case SVR4_P_PID:
1022 break;
1023
1024 case SVR4_P_PGID:
1025 mutex_enter(proc_lock);
1026 id = -l->l_proc->p_pgid;
1027 mutex_exit(proc_lock);
1028 break;
1029
1030 case SVR4_P_ALL:
1031 id = WAIT_ANY;
1032 break;
1033
1034 default:
1035 return EINVAL;
1036 }
1037
1038 /* Translate options */
1039 options = WOPTSCHECKED;
1040 if (SCARG(uap, options) & SVR4_WNOWAIT)
1041 options |= WNOWAIT;
1042 if (SCARG(uap, options) & SVR4_WNOHANG)
1043 options |= WNOHANG;
1044 if ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)) == 0)
1045 options |= WNOZOMBIE;
1046 if (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED))
1047 options |= WUNTRACED;
1048
1049 DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1050 SCARG(uap, grp), id,
1051 SCARG(uap, info), SCARG(uap, options)));
1052
1053 error = do_sys_wait(l, &id, &status, options, &ru,
1054 &was_zombie);
1055
1056 retval[0] = id;
1057 if (error != 0)
1058 return error;
1059
1060 svr4_setinfo(id, &ru, status, &i);
1061 return copyout(&i, SCARG(uap, info), sizeof(i));
1062 }
1063
1064
1065 static int
1066 svr4_copyout_statvfs(const struct statvfs *bfs, struct svr4_statvfs *sufs)
1067 {
1068 struct svr4_statvfs *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1069 int error;
1070
1071 sfs->f_bsize = bfs->f_bsize;
1072 sfs->f_frsize = bfs->f_frsize;
1073 sfs->f_blocks = bfs->f_blocks;
1074 sfs->f_bfree = bfs->f_bfree;
1075 sfs->f_bavail = bfs->f_bavail;
1076 sfs->f_files = bfs->f_files;
1077 sfs->f_ffree = bfs->f_ffree;
1078 sfs->f_favail = bfs->f_favail;
1079 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1080 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1081 sfs->f_flag = 0;
1082 if (bfs->f_flag & MNT_RDONLY)
1083 sfs->f_flag |= SVR4_ST_RDONLY;
1084 if (bfs->f_flag & MNT_NOSUID)
1085 sfs->f_flag |= SVR4_ST_NOSUID;
1086 sfs->f_namemax = MAXNAMLEN;
1087 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1088 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1089
1090 error = copyout(sfs, sufs, sizeof(*sfs));
1091
1092 free(sfs, M_TEMP);
1093 return error;
1094 }
1095
1096
1097 static int
1098 svr4_copyout_statvfs64(const struct statvfs *bfs, struct svr4_statvfs64 *sufs)
1099 {
1100 struct svr4_statvfs64 *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1101 int error;
1102
1103 sfs->f_bsize = bfs->f_bsize;
1104 sfs->f_frsize = bfs->f_frsize;
1105 sfs->f_blocks = bfs->f_blocks;
1106 sfs->f_bfree = bfs->f_bfree;
1107 sfs->f_bavail = bfs->f_bavail;
1108 sfs->f_files = bfs->f_files;
1109 sfs->f_ffree = bfs->f_ffree;
1110 sfs->f_favail = bfs->f_ffree;
1111 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1112 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1113 sfs->f_flag = 0;
1114 if (bfs->f_flag & MNT_RDONLY)
1115 sfs->f_flag |= SVR4_ST_RDONLY;
1116 if (bfs->f_flag & MNT_NOSUID)
1117 sfs->f_flag |= SVR4_ST_NOSUID;
1118 sfs->f_namemax = MAXNAMLEN;
1119 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1120 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1121
1122 error = copyout(sfs, sufs, sizeof(*sfs));
1123
1124 free(sfs, M_TEMP);
1125 return error;
1126 }
1127
1128
1129 int
1130 svr4_sys_statvfs(struct lwp *l, const struct svr4_sys_statvfs_args *uap, register_t *retval)
1131 {
1132 struct statvfs *sb;
1133 int error;
1134
1135 sb = STATVFSBUF_GET();
1136 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
1137 if (error == 0)
1138 error = svr4_copyout_statvfs(sb, SCARG(uap, fs));
1139 STATVFSBUF_PUT(sb);
1140 return error;
1141 }
1142
1143
1144 int
1145 svr4_sys_fstatvfs(struct lwp *l, const struct svr4_sys_fstatvfs_args *uap, register_t *retval)
1146 {
1147 struct statvfs *sb;
1148 int error;
1149
1150 sb = STATVFSBUF_GET();
1151 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1152 if (error == 0)
1153 error = svr4_copyout_statvfs(sb, SCARG(uap, fs));
1154 STATVFSBUF_PUT(sb);
1155 return error;
1156 }
1157
1158
1159 int
1160 svr4_sys_statvfs64(struct lwp *l, const struct svr4_sys_statvfs64_args *uap, register_t *retval)
1161 {
1162 struct statvfs *sb;
1163 int error;
1164
1165 sb = STATVFSBUF_GET();
1166 error = do_sys_pstatvfs(l, SCARG(uap, path), ST_WAIT, sb);
1167 if (error == 0)
1168 error = svr4_copyout_statvfs64(sb, SCARG(uap, fs));
1169 STATVFSBUF_PUT(sb);
1170 return error;
1171 }
1172
1173
1174 int
1175 svr4_sys_fstatvfs64(struct lwp *l, const struct svr4_sys_fstatvfs64_args *uap, register_t *retval)
1176 {
1177 struct statvfs *sb;
1178 int error;
1179
1180 sb = STATVFSBUF_GET();
1181 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1182 if (error == 0)
1183 error = svr4_copyout_statvfs64(sb, SCARG(uap, fs));
1184 STATVFSBUF_PUT(sb);
1185 return error;
1186 }
1187
1188 int
1189 svr4_sys_alarm(struct lwp *l, const struct svr4_sys_alarm_args *uap, register_t *retval)
1190 {
1191 struct itimerval tp;
1192
1193 dogetitimer(l->l_proc, ITIMER_REAL, &tp);
1194 if (tp.it_value.tv_usec)
1195 tp.it_value.tv_sec++;
1196 *retval = (register_t)tp.it_value.tv_sec;
1197
1198 timerclear(&tp.it_interval);
1199 tp.it_value.tv_sec = SCARG(uap, sec);
1200 tp.it_value.tv_usec = 0;
1201
1202 return dosetitimer(l->l_proc, ITIMER_REAL, &tp);
1203 }
1204
1205
1206 int
1207 svr4_sys_gettimeofday(struct lwp *l, const struct svr4_sys_gettimeofday_args *uap, register_t *retval)
1208 {
1209
1210 if (SCARG(uap, tp)) {
1211 struct timeval atv;
1212
1213 microtime(&atv);
1214 return copyout(&atv, SCARG(uap, tp), sizeof (atv));
1215 }
1216
1217 return 0;
1218 }
1219
1220
1221 int
1222 svr4_sys_facl(struct lwp *l, const struct svr4_sys_facl_args *uap, register_t *retval)
1223 {
1224
1225 *retval = 0;
1226
1227 switch (SCARG(uap, cmd)) {
1228 case SVR4_SYS_SETACL:
1229 /* We don't support acls on any filesystem */
1230 return ENOSYS;
1231
1232 case SVR4_SYS_GETACL:
1233 #if 1
1234 return ENOSYS;
1235 #else
1236 /*
1237 * XXX This code is completly borked, no idea what it was
1238 * trying to do.
1239 */
1240 return copyout(retval, &SCARG(uap, num),
1241 sizeof(SCARG(uap, num)));
1242 #endif
1243
1244 case SVR4_SYS_GETACLCNT:
1245 return 0;
1246
1247 default:
1248 return EINVAL;
1249 }
1250 }
1251
1252
1253 int
1254 svr4_sys_acl(struct lwp *l, const struct svr4_sys_acl_args *uap, register_t *retval)
1255 {
1256 return svr4_sys_facl(l, (const void *)uap, retval); /* XXX: for now the same */
1257 }
1258
1259
1260 int
1261 svr4_sys_auditsys(struct lwp *l, const struct svr4_sys_auditsys_args *uap, register_t *retval)
1262 {
1263 /*
1264 * XXX: Big brother is *not* watching.
1265 */
1266 return 0;
1267 }
1268
1269
1270 int
1271 svr4_sys_memcntl(struct lwp *l, const struct svr4_sys_memcntl_args *uap, register_t *retval)
1272 {
1273 switch (SCARG(uap, cmd)) {
1274 case SVR4_MC_SYNC:
1275 {
1276 struct sys___msync13_args msa;
1277
1278 SCARG(&msa, addr) = SCARG(uap, addr);
1279 SCARG(&msa, len) = SCARG(uap, len);
1280 SCARG(&msa, flags) = (int)(u_long)SCARG(uap, arg);
1281
1282 return sys___msync13(l, &msa, retval);
1283 }
1284 case SVR4_MC_ADVISE:
1285 {
1286 struct sys_madvise_args maa;
1287
1288 SCARG(&maa, addr) = SCARG(uap, addr);
1289 SCARG(&maa, len) = SCARG(uap, len);
1290 SCARG(&maa, behav) = (int)(u_long)SCARG(uap, arg);
1291
1292 return sys_madvise(l, &maa, retval);
1293 }
1294 case SVR4_MC_LOCK:
1295 case SVR4_MC_UNLOCK:
1296 case SVR4_MC_LOCKAS:
1297 case SVR4_MC_UNLOCKAS:
1298 return EOPNOTSUPP;
1299 default:
1300 return ENOSYS;
1301 }
1302 }
1303
1304
1305 int
1306 svr4_sys_nice(struct lwp *l, const struct svr4_sys_nice_args *uap, register_t *retval)
1307 {
1308 struct sys_setpriority_args ap;
1309 int error;
1310
1311 SCARG(&ap, which) = PRIO_PROCESS;
1312 SCARG(&ap, who) = 0;
1313 SCARG(&ap, prio) = SCARG(uap, prio);
1314
1315 if ((error = sys_setpriority(l, &ap, retval)) != 0)
1316 return error;
1317
1318 if ((error = sys_getpriority(l, (const void *)&ap, retval)) != 0)
1319 return error;
1320
1321 return 0;
1322 }
1323
1324
1325 int
1326 svr4_sys_resolvepath(struct lwp *l, const struct svr4_sys_resolvepath_args *uap, register_t *retval)
1327 {
1328 struct nameidata nd;
1329 int error;
1330 size_t len;
1331
1332 NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | TRYEMULROOT, UIO_USERSPACE,
1333 SCARG(uap, path));
1334
1335 if ((error = namei(&nd)) != 0)
1336 return error;
1337
1338 if ((error = copyoutstr(nd.ni_cnd.cn_pnbuf, SCARG(uap, buf),
1339 SCARG(uap, bufsiz), &len)) != 0)
1340 goto bad;
1341
1342 *retval = len;
1343 bad:
1344 vrele(nd.ni_vp);
1345 PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
1346 return error;
1347 }
Cache object: b3374b187b002ef8606959df4761f801
|