1 /*-
2 * Copyright (c) 1998 Mark Newton
3 * Copyright (c) 1994 Christos Zoulas
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 /*
29 * SVR4 compatibility module.
30 *
31 * SVR4 system calls that are implemented differently in BSD are
32 * handled here.
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: src/sys/compat/svr4/svr4_misc.c,v 1.71.2.6 2005/04/21 22:19:21 ps Exp $");
37
38 #include "opt_mac.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/dirent.h>
43 #include <sys/fcntl.h>
44 #include <sys/filedesc.h>
45 #include <sys/kernel.h>
46 #include <sys/lock.h>
47 #include <sys/mac.h>
48 #include <sys/malloc.h>
49 #include <sys/file.h> /* Must come after sys/malloc.h */
50 #include <sys/mman.h>
51 #include <sys/mount.h>
52 #include <sys/msg.h>
53 #include <sys/mutex.h>
54 #include <sys/namei.h>
55 #include <sys/proc.h>
56 #include <sys/ptrace.h>
57 #include <sys/resource.h>
58 #include <sys/resourcevar.h>
59 #include <sys/sem.h>
60 #include <sys/signalvar.h>
61 #include <sys/stat.h>
62 #include <sys/sx.h>
63 #include <sys/syscallsubr.h>
64 #include <sys/sysproto.h>
65 #include <sys/time.h>
66 #include <sys/times.h>
67 #include <sys/uio.h>
68 #include <sys/vnode.h>
69 #include <sys/wait.h>
70
71 #include <compat/svr4/svr4.h>
72 #include <compat/svr4/svr4_types.h>
73 #include <compat/svr4/svr4_signal.h>
74 #include <compat/svr4/svr4_proto.h>
75 #include <compat/svr4/svr4_util.h>
76 #include <compat/svr4/svr4_sysconfig.h>
77 #include <compat/svr4/svr4_dirent.h>
78 #include <compat/svr4/svr4_acl.h>
79 #include <compat/svr4/svr4_ulimit.h>
80 #include <compat/svr4/svr4_statvfs.h>
81 #include <compat/svr4/svr4_hrt.h>
82 #include <compat/svr4/svr4_mman.h>
83 #include <compat/svr4/svr4_wait.h>
84
85 #include <machine/vmparam.h>
86 #include <vm/vm.h>
87 #include <vm/vm_param.h>
88 #include <vm/vm_map.h>
89 #if defined(__FreeBSD__)
90 #include <vm/uma.h>
91 #include <vm/vm_extern.h>
92 #endif
93
94 #if defined(NetBSD)
95 # if defined(UVM)
96 # include <uvm/uvm_extern.h>
97 # endif
98 #endif
99
100 #define BSD_DIRENT(cp) ((struct dirent *)(cp))
101
102 static int svr4_mknod(struct thread *, register_t *, char *,
103 svr4_mode_t, svr4_dev_t);
104
105 static __inline clock_t timeval_to_clock_t(struct timeval *);
106 static int svr4_setinfo (struct proc *, int, svr4_siginfo_t *);
107
108 struct svr4_hrtcntl_args;
109 static int svr4_hrtcntl (struct thread *, struct svr4_hrtcntl_args *,
110 register_t *);
111 static void bsd_statfs_to_svr4_statvfs(const struct statfs *,
112 struct svr4_statvfs *);
113 static void bsd_statfs_to_svr4_statvfs64(const struct statfs *,
114 struct svr4_statvfs64 *);
115 static struct proc *svr4_pfind(pid_t pid);
116
117 /* BOGUS noop */
118 #if defined(BOGUS)
119 int
120 svr4_sys_setitimer(td, uap)
121 register struct thread *td;
122 struct svr4_sys_setitimer_args *uap;
123 {
124 td->td_retval[0] = 0;
125 return 0;
126 }
127 #endif
128
129 int
130 svr4_sys_wait(td, uap)
131 struct thread *td;
132 struct svr4_sys_wait_args *uap;
133 {
134 int error, st, sig;
135
136 error = kern_wait(td, WAIT_ANY, &st, 0, NULL);
137 if (error)
138 return (error);
139
140 if (WIFSIGNALED(st)) {
141 sig = WTERMSIG(st);
142 if (sig >= 0 && sig < NSIG)
143 st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig);
144 } else if (WIFSTOPPED(st)) {
145 sig = WSTOPSIG(st);
146 if (sig >= 0 && sig < NSIG)
147 st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8);
148 }
149
150 /*
151 * It looks like wait(2) on svr4/solaris/2.4 returns
152 * the status in retval[1], and the pid on retval[0].
153 */
154 td->td_retval[1] = st;
155
156 if (uap->status)
157 error = copyout(&st, uap->status, sizeof(st));
158
159 return (error);
160 }
161
162 int
163 svr4_sys_execv(td, uap)
164 struct thread *td;
165 struct svr4_sys_execv_args *uap;
166 {
167 struct execve_args ap;
168 caddr_t sg;
169
170 sg = stackgap_init();
171 CHECKALTEXIST(td, &sg, uap->path);
172
173 ap.fname = uap->path;
174 ap.argv = uap->argp;
175 ap.envv = NULL;
176
177 return execve(td, &ap);
178 }
179
180 int
181 svr4_sys_execve(td, uap)
182 struct thread *td;
183 struct svr4_sys_execve_args *uap;
184 {
185 struct execve_args ap;
186 caddr_t sg;
187
188 sg = stackgap_init();
189 CHECKALTEXIST(td, &sg, uap->path);
190
191 ap.fname = uap->path;
192 ap.argv = uap->argp;
193 ap.envv = uap->envp;
194
195 return execve(td, &ap);
196 }
197
198 int
199 svr4_sys_time(td, v)
200 struct thread *td;
201 struct svr4_sys_time_args *v;
202 {
203 struct svr4_sys_time_args *uap = v;
204 int error = 0;
205 struct timeval tv;
206
207 microtime(&tv);
208 if (uap->t)
209 error = copyout(&tv.tv_sec, uap->t,
210 sizeof(*(uap->t)));
211 td->td_retval[0] = (int) tv.tv_sec;
212
213 return error;
214 }
215
216
217 /*
218 * Read SVR4-style directory entries. We suck them into kernel space so
219 * that they can be massaged before being copied out to user code.
220 *
221 * This code is ported from the Linux emulator: Changes to the VFS interface
222 * between FreeBSD and NetBSD have made it simpler to port it from there than
223 * to adapt the NetBSD version.
224 */
225 int
226 svr4_sys_getdents64(td, uap)
227 struct thread *td;
228 struct svr4_sys_getdents64_args *uap;
229 {
230 register struct dirent *bdp;
231 struct vnode *vp;
232 caddr_t inp, buf; /* BSD-format */
233 int len, reclen; /* BSD-format */
234 caddr_t outp; /* SVR4-format */
235 int resid, svr4reclen=0; /* SVR4-format */
236 struct file *fp;
237 struct uio auio;
238 struct iovec aiov;
239 off_t off;
240 struct svr4_dirent64 svr4_dirent;
241 int buflen, error, eofflag, nbytes, justone;
242 u_long *cookies = NULL, *cookiep;
243 int ncookies;
244
245 DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
246 uap->fd, uap->nbytes));
247 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
248 return (error);
249 }
250
251 if ((fp->f_flag & FREAD) == 0) {
252 fdrop(fp, td);
253 return (EBADF);
254 }
255
256 vp = fp->f_vnode;
257
258 if (vp->v_type != VDIR) {
259 fdrop(fp, td);
260 return (EINVAL);
261 }
262
263 nbytes = uap->nbytes;
264 if (nbytes == 1) {
265 nbytes = sizeof (struct svr4_dirent64);
266 justone = 1;
267 }
268 else
269 justone = 0;
270
271 off = fp->f_offset;
272 #define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */
273 buflen = max(DIRBLKSIZ, nbytes);
274 buflen = min(buflen, MAXBSIZE);
275 buf = malloc(buflen, M_TEMP, M_WAITOK);
276 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
277 again:
278 aiov.iov_base = buf;
279 aiov.iov_len = buflen;
280 auio.uio_iov = &aiov;
281 auio.uio_iovcnt = 1;
282 auio.uio_rw = UIO_READ;
283 auio.uio_segflg = UIO_SYSSPACE;
284 auio.uio_td = td;
285 auio.uio_resid = buflen;
286 auio.uio_offset = off;
287
288 if (cookies) {
289 free(cookies, M_TEMP);
290 cookies = NULL;
291 }
292
293 #ifdef MAC
294 error = mac_check_vnode_readdir(td->td_ucred, vp);
295 if (error)
296 goto out;
297 #endif
298
299 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
300 &ncookies, &cookies);
301 if (error) {
302 goto out;
303 }
304
305 inp = buf;
306 outp = (caddr_t) uap->dp;
307 resid = nbytes;
308 if ((len = buflen - auio.uio_resid) <= 0) {
309 goto eof;
310 }
311
312 cookiep = cookies;
313
314 if (cookies) {
315 /*
316 * When using cookies, the vfs has the option of reading from
317 * a different offset than that supplied (UFS truncates the
318 * offset to a block boundary to make sure that it never reads
319 * partway through a directory entry, even if the directory
320 * has been compacted).
321 */
322 while (len > 0 && ncookies > 0 && *cookiep <= off) {
323 bdp = (struct dirent *) inp;
324 len -= bdp->d_reclen;
325 inp += bdp->d_reclen;
326 cookiep++;
327 ncookies--;
328 }
329 }
330
331 while (len > 0) {
332 if (cookiep && ncookies == 0)
333 break;
334 bdp = (struct dirent *) inp;
335 reclen = bdp->d_reclen;
336 if (reclen & 3) {
337 DPRINTF(("svr4_readdir: reclen=%d\n", reclen));
338 error = EFAULT;
339 goto out;
340 }
341
342 if (bdp->d_fileno == 0) {
343 inp += reclen;
344 if (cookiep) {
345 off = *cookiep++;
346 ncookies--;
347 } else
348 off += reclen;
349 len -= reclen;
350 continue;
351 }
352 svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen);
353 if (reclen > len || resid < svr4reclen) {
354 outp++;
355 break;
356 }
357 svr4_dirent.d_ino = (long) bdp->d_fileno;
358 if (justone) {
359 /*
360 * old svr4-style readdir usage.
361 */
362 svr4_dirent.d_off = (svr4_off_t) svr4reclen;
363 svr4_dirent.d_reclen = (u_short) bdp->d_namlen;
364 } else {
365 svr4_dirent.d_off = (svr4_off_t)(off + reclen);
366 svr4_dirent.d_reclen = (u_short) svr4reclen;
367 }
368 strcpy(svr4_dirent.d_name, bdp->d_name);
369 if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen)))
370 goto out;
371 inp += reclen;
372 if (cookiep) {
373 off = *cookiep++;
374 ncookies--;
375 } else
376 off += reclen;
377 outp += svr4reclen;
378 resid -= svr4reclen;
379 len -= reclen;
380 if (justone)
381 break;
382 }
383
384 if (outp == (caddr_t) uap->dp)
385 goto again;
386 fp->f_offset = off;
387
388 if (justone)
389 nbytes = resid + svr4reclen;
390
391 eof:
392 td->td_retval[0] = nbytes - resid;
393 out:
394 VOP_UNLOCK(vp, 0, td);
395 fdrop(fp, td);
396 if (cookies)
397 free(cookies, M_TEMP);
398 free(buf, M_TEMP);
399 return error;
400 }
401
402
403 int
404 svr4_sys_getdents(td, uap)
405 struct thread *td;
406 struct svr4_sys_getdents_args *uap;
407 {
408 struct dirent *bdp;
409 struct vnode *vp;
410 caddr_t inp, buf; /* BSD-format */
411 int len, reclen; /* BSD-format */
412 caddr_t outp; /* SVR4-format */
413 int resid, svr4_reclen; /* SVR4-format */
414 struct file *fp;
415 struct uio auio;
416 struct iovec aiov;
417 struct svr4_dirent idb;
418 off_t off; /* true file offset */
419 int buflen, error, eofflag;
420 u_long *cookiebuf = NULL, *cookie;
421 int ncookies = 0, *retval = td->td_retval;
422
423 if (uap->nbytes < 0)
424 return (EINVAL);
425
426 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
427 return (error);
428
429 if ((fp->f_flag & FREAD) == 0) {
430 fdrop(fp, td);
431 return (EBADF);
432 }
433
434 vp = fp->f_vnode;
435 if (vp->v_type != VDIR) {
436 fdrop(fp, td);
437 return (EINVAL);
438 }
439
440 buflen = min(MAXBSIZE, uap->nbytes);
441 buf = malloc(buflen, M_TEMP, M_WAITOK);
442 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
443 off = fp->f_offset;
444 again:
445 aiov.iov_base = buf;
446 aiov.iov_len = buflen;
447 auio.uio_iov = &aiov;
448 auio.uio_iovcnt = 1;
449 auio.uio_rw = UIO_READ;
450 auio.uio_segflg = UIO_SYSSPACE;
451 auio.uio_td = td;
452 auio.uio_resid = buflen;
453 auio.uio_offset = off;
454
455 #ifdef MAC
456 error = mac_check_vnode_readdir(td->td_ucred, vp);
457 if (error)
458 goto out;
459 #endif
460
461 /*
462 * First we read into the malloc'ed buffer, then
463 * we massage it into user space, one record at a time.
464 */
465 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
466 &cookiebuf);
467 if (error) {
468 goto out;
469 }
470
471 inp = buf;
472 outp = uap->buf;
473 resid = uap->nbytes;
474 if ((len = buflen - auio.uio_resid) == 0)
475 goto eof;
476
477 for (cookie = cookiebuf; len > 0; len -= reclen) {
478 bdp = (struct dirent *)inp;
479 reclen = bdp->d_reclen;
480 if (reclen & 3)
481 panic("svr4_sys_getdents64: bad reclen");
482 off = *cookie++; /* each entry points to the next */
483 if ((off >> 32) != 0) {
484 uprintf("svr4_sys_getdents64: dir offset too large for emulated program");
485 error = EINVAL;
486 goto out;
487 }
488 if (bdp->d_fileno == 0) {
489 inp += reclen; /* it is a hole; squish it out */
490 continue;
491 }
492 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
493 if (reclen > len || resid < svr4_reclen) {
494 /* entry too big for buffer, so just stop */
495 outp++;
496 break;
497 }
498 /*
499 * Massage in place to make a SVR4-shaped dirent (otherwise
500 * we have to worry about touching user memory outside of
501 * the copyout() call).
502 */
503 idb.d_ino = (svr4_ino_t)bdp->d_fileno;
504 idb.d_off = (svr4_off_t)off;
505 idb.d_reclen = (u_short)svr4_reclen;
506 strcpy(idb.d_name, bdp->d_name);
507 if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))
508 goto out;
509 /* advance past this real entry */
510 inp += reclen;
511 /* advance output past SVR4-shaped entry */
512 outp += svr4_reclen;
513 resid -= svr4_reclen;
514 }
515
516 /* if we squished out the whole block, try again */
517 if (outp == uap->buf)
518 goto again;
519 fp->f_offset = off; /* update the vnode offset */
520
521 eof:
522 *retval = uap->nbytes - resid;
523 out:
524 VOP_UNLOCK(vp, 0, td);
525 fdrop(fp, td);
526 if (cookiebuf)
527 free(cookiebuf, M_TEMP);
528 free(buf, M_TEMP);
529 return error;
530 }
531
532
533 int
534 svr4_sys_mmap(td, uap)
535 struct thread *td;
536 struct svr4_sys_mmap_args *uap;
537 {
538 struct mmap_args mm;
539 int *retval;
540
541 retval = td->td_retval;
542 #define _MAP_NEW 0x80000000
543 /*
544 * Verify the arguments.
545 */
546 if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
547 return EINVAL; /* XXX still needed? */
548
549 if (uap->len == 0)
550 return EINVAL;
551
552 mm.prot = uap->prot;
553 mm.len = uap->len;
554 mm.flags = uap->flags & ~_MAP_NEW;
555 mm.fd = uap->fd;
556 mm.addr = uap->addr;
557 mm.pos = uap->pos;
558
559 return mmap(td, &mm);
560 }
561
562 int
563 svr4_sys_mmap64(td, uap)
564 struct thread *td;
565 struct svr4_sys_mmap64_args *uap;
566 {
567 struct mmap_args mm;
568 void *rp;
569
570 #define _MAP_NEW 0x80000000
571 /*
572 * Verify the arguments.
573 */
574 if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
575 return EINVAL; /* XXX still needed? */
576
577 if (uap->len == 0)
578 return EINVAL;
579
580 mm.prot = uap->prot;
581 mm.len = uap->len;
582 mm.flags = uap->flags & ~_MAP_NEW;
583 mm.fd = uap->fd;
584 mm.addr = uap->addr;
585 mm.pos = uap->pos;
586
587 rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz));
588 if ((mm.flags & MAP_FIXED) == 0 &&
589 mm.addr != 0 && (void *)mm.addr < rp)
590 mm.addr = rp;
591
592 return mmap(td, &mm);
593 }
594
595
596 int
597 svr4_sys_fchroot(td, uap)
598 struct thread *td;
599 struct svr4_sys_fchroot_args *uap;
600 {
601 struct filedesc *fdp = td->td_proc->p_fd;
602 struct vnode *vp, *vpold;
603 struct file *fp;
604 int error;
605
606 if ((error = suser(td)) != 0)
607 return error;
608 if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
609 return error;
610 vp = fp->f_vnode;
611 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
612 if (vp->v_type != VDIR)
613 error = ENOTDIR;
614 else
615 error = VOP_ACCESS(vp, VEXEC, td->td_ucred, td);
616 VOP_UNLOCK(vp, 0, td);
617 if (error) {
618 fdrop(fp, td);
619 return error;
620 }
621 VREF(vp);
622 FILEDESC_LOCK_FAST(fdp);
623 vpold = fdp->fd_rdir;
624 fdp->fd_rdir = vp;
625 FILEDESC_UNLOCK_FAST(fdp);
626 if (vpold != NULL)
627 vrele(vpold);
628 fdrop(fp, td);
629 return 0;
630 }
631
632
633 static int
634 svr4_mknod(td, retval, path, mode, dev)
635 struct thread *td;
636 register_t *retval;
637 char *path;
638 svr4_mode_t mode;
639 svr4_dev_t dev;
640 {
641 caddr_t sg = stackgap_init();
642
643 CHECKALTEXIST(td, &sg, path);
644
645 if (S_ISFIFO(mode)) {
646 struct mkfifo_args ap;
647 ap.path = path;
648 ap.mode = mode;
649 return mkfifo(td, &ap);
650 } else {
651 struct mknod_args ap;
652 ap.path = path;
653 ap.mode = mode;
654 ap.dev = dev;
655 return mknod(td, &ap);
656 }
657 }
658
659
660 int
661 svr4_sys_mknod(td, uap)
662 register struct thread *td;
663 struct svr4_sys_mknod_args *uap;
664 {
665 int *retval = td->td_retval;
666 return svr4_mknod(td, retval,
667 uap->path, uap->mode,
668 (svr4_dev_t)svr4_to_bsd_odev_t(uap->dev));
669 }
670
671
672 int
673 svr4_sys_xmknod(td, uap)
674 struct thread *td;
675 struct svr4_sys_xmknod_args *uap;
676 {
677 int *retval = td->td_retval;
678 return svr4_mknod(td, retval,
679 uap->path, uap->mode,
680 (svr4_dev_t)svr4_to_bsd_dev_t(uap->dev));
681 }
682
683
684 int
685 svr4_sys_vhangup(td, uap)
686 struct thread *td;
687 struct svr4_sys_vhangup_args *uap;
688 {
689 return 0;
690 }
691
692
693 int
694 svr4_sys_sysconfig(td, uap)
695 struct thread *td;
696 struct svr4_sys_sysconfig_args *uap;
697 {
698 int *retval;
699
700 retval = &(td->td_retval[0]);
701
702 switch (uap->name) {
703 case SVR4_CONFIG_UNUSED:
704 *retval = 0;
705 break;
706 case SVR4_CONFIG_NGROUPS:
707 *retval = NGROUPS_MAX;
708 break;
709 case SVR4_CONFIG_CHILD_MAX:
710 *retval = maxproc;
711 break;
712 case SVR4_CONFIG_OPEN_FILES:
713 *retval = maxfiles;
714 break;
715 case SVR4_CONFIG_POSIX_VER:
716 *retval = 198808;
717 break;
718 case SVR4_CONFIG_PAGESIZE:
719 *retval = PAGE_SIZE;
720 break;
721 case SVR4_CONFIG_CLK_TCK:
722 *retval = 60; /* should this be `hz', ie. 100? */
723 break;
724 case SVR4_CONFIG_XOPEN_VER:
725 *retval = 2; /* XXX: What should that be? */
726 break;
727 case SVR4_CONFIG_PROF_TCK:
728 *retval = 60; /* XXX: What should that be? */
729 break;
730 case SVR4_CONFIG_NPROC_CONF:
731 *retval = 1; /* Only one processor for now */
732 break;
733 case SVR4_CONFIG_NPROC_ONLN:
734 *retval = 1; /* And it better be online */
735 break;
736 case SVR4_CONFIG_AIO_LISTIO_MAX:
737 case SVR4_CONFIG_AIO_MAX:
738 case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
739 *retval = 0; /* No aio support */
740 break;
741 case SVR4_CONFIG_DELAYTIMER_MAX:
742 *retval = 0; /* No delaytimer support */
743 break;
744 case SVR4_CONFIG_MQ_OPEN_MAX:
745 *retval = msginfo.msgmni;
746 break;
747 case SVR4_CONFIG_MQ_PRIO_MAX:
748 *retval = 0; /* XXX: Don't know */
749 break;
750 case SVR4_CONFIG_RTSIG_MAX:
751 *retval = 0;
752 break;
753 case SVR4_CONFIG_SEM_NSEMS_MAX:
754 *retval = seminfo.semmni;
755 break;
756 case SVR4_CONFIG_SEM_VALUE_MAX:
757 *retval = seminfo.semvmx;
758 break;
759 case SVR4_CONFIG_SIGQUEUE_MAX:
760 *retval = 0; /* XXX: Don't know */
761 break;
762 case SVR4_CONFIG_SIGRT_MIN:
763 case SVR4_CONFIG_SIGRT_MAX:
764 *retval = 0; /* No real time signals */
765 break;
766 case SVR4_CONFIG_TIMER_MAX:
767 *retval = 3; /* XXX: real, virtual, profiling */
768 break;
769 #if defined(NOTYET)
770 case SVR4_CONFIG_PHYS_PAGES:
771 #if defined(UVM)
772 *retval = uvmexp.free; /* XXX: free instead of total */
773 #else
774 *retval = cnt.v_free_count; /* XXX: free instead of total */
775 #endif
776 break;
777 case SVR4_CONFIG_AVPHYS_PAGES:
778 #if defined(UVM)
779 *retval = uvmexp.active; /* XXX: active instead of avg */
780 #else
781 *retval = cnt.v_active_count; /* XXX: active instead of avg */
782 #endif
783 break;
784 #endif /* NOTYET */
785
786 default:
787 return EINVAL;
788 }
789 return 0;
790 }
791
792 /* ARGSUSED */
793 int
794 svr4_sys_break(td, uap)
795 struct thread *td;
796 struct svr4_sys_break_args *uap;
797 {
798 struct proc *p = td->td_proc;
799 struct vmspace *vm = p->p_vmspace;
800 vm_offset_t new, old, base, ns;
801 int rv;
802
803 base = round_page((vm_offset_t) vm->vm_daddr);
804 ns = (vm_offset_t)uap->nsize;
805 new = round_page(ns);
806 if (new > base) {
807 PROC_LOCK(p);
808 if ((new - base) > (unsigned)lim_cur(p, RLIMIT_DATA)) {
809 PROC_UNLOCK(p);
810 return ENOMEM;
811 }
812 PROC_UNLOCK(p);
813 if (new >= VM_MAXUSER_ADDRESS)
814 return (ENOMEM);
815 } else if (new < base) {
816 /*
817 * This is simply an invalid value. If someone wants to
818 * do fancy address space manipulations, mmap and munmap
819 * can do most of what the user would want.
820 */
821 return EINVAL;
822 }
823
824 old = base + ctob(vm->vm_dsize);
825
826 if (new > old) {
827 vm_size_t diff;
828 diff = new - old;
829 PROC_LOCK(p);
830 if (vm->vm_map.size + diff > lim_cur(p, RLIMIT_VMEM)) {
831 PROC_UNLOCK(p);
832 return(ENOMEM);
833 }
834 PROC_UNLOCK(p);
835 rv = vm_map_find(&vm->vm_map, NULL, 0, &old, diff, FALSE,
836 VM_PROT_ALL, VM_PROT_ALL, 0);
837 if (rv != KERN_SUCCESS) {
838 return (ENOMEM);
839 }
840 vm->vm_dsize += btoc(diff);
841 } else if (new < old) {
842 rv = vm_map_remove(&vm->vm_map, new, old);
843 if (rv != KERN_SUCCESS) {
844 return (ENOMEM);
845 }
846 vm->vm_dsize -= btoc(old - new);
847 }
848
849 return (0);
850 }
851
852 static __inline clock_t
853 timeval_to_clock_t(tv)
854 struct timeval *tv;
855 {
856 return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
857 }
858
859
860 int
861 svr4_sys_times(td, uap)
862 struct thread *td;
863 struct svr4_sys_times_args *uap;
864 {
865 int error, *retval = td->td_retval;
866 struct tms tms;
867 struct timeval t;
868 struct rusage *ru;
869 struct rusage r;
870 struct getrusage_args ga;
871
872 caddr_t sg = stackgap_init();
873 ru = stackgap_alloc(&sg, sizeof(struct rusage));
874
875 ga.who = RUSAGE_SELF;
876 ga.rusage = ru;
877
878 error = getrusage(td, &ga);
879 if (error)
880 return error;
881
882 if ((error = copyin(ru, &r, sizeof r)) != 0)
883 return error;
884
885 tms.tms_utime = timeval_to_clock_t(&r.ru_utime);
886 tms.tms_stime = timeval_to_clock_t(&r.ru_stime);
887
888 ga.who = RUSAGE_CHILDREN;
889 error = getrusage(td, &ga);
890 if (error)
891 return error;
892
893 if ((error = copyin(ru, &r, sizeof r)) != 0)
894 return error;
895
896 tms.tms_cutime = timeval_to_clock_t(&r.ru_utime);
897 tms.tms_cstime = timeval_to_clock_t(&r.ru_stime);
898
899 microtime(&t);
900 *retval = timeval_to_clock_t(&t);
901
902 return copyout(&tms, uap->tp, sizeof(tms));
903 }
904
905
906 int
907 svr4_sys_ulimit(td, uap)
908 struct thread *td;
909 struct svr4_sys_ulimit_args *uap;
910 {
911 int *retval = td->td_retval;
912 int error;
913
914 switch (uap->cmd) {
915 case SVR4_GFILLIM:
916 PROC_LOCK(td->td_proc);
917 *retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512;
918 PROC_UNLOCK(td->td_proc);
919 if (*retval == -1)
920 *retval = 0x7fffffff;
921 return 0;
922
923 case SVR4_SFILLIM:
924 {
925 struct rlimit krl;
926
927 krl.rlim_cur = uap->newlimit * 512;
928 PROC_LOCK(td->td_proc);
929 krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE);
930 PROC_UNLOCK(td->td_proc);
931
932 error = kern_setrlimit(td, RLIMIT_FSIZE, &krl);
933 if (error)
934 return error;
935
936 PROC_LOCK(td->td_proc);
937 *retval = lim_cur(td->td_proc, RLIMIT_FSIZE);
938 PROC_UNLOCK(td->td_proc);
939 if (*retval == -1)
940 *retval = 0x7fffffff;
941 return 0;
942 }
943
944 case SVR4_GMEMLIM:
945 {
946 struct vmspace *vm = td->td_proc->p_vmspace;
947 register_t r;
948
949 PROC_LOCK(td->td_proc);
950 r = lim_cur(td->td_proc, RLIMIT_DATA);
951 PROC_UNLOCK(td->td_proc);
952
953 if (r == -1)
954 r = 0x7fffffff;
955 mtx_lock(&Giant); /* XXX */
956 r += (long) vm->vm_daddr;
957 mtx_unlock(&Giant);
958 if (r < 0)
959 r = 0x7fffffff;
960 *retval = r;
961 return 0;
962 }
963
964 case SVR4_GDESLIM:
965 PROC_LOCK(td->td_proc);
966 *retval = lim_cur(td->td_proc, RLIMIT_NOFILE);
967 PROC_UNLOCK(td->td_proc);
968 if (*retval == -1)
969 *retval = 0x7fffffff;
970 return 0;
971
972 default:
973 return EINVAL;
974 }
975 }
976
977 static struct proc *
978 svr4_pfind(pid)
979 pid_t pid;
980 {
981 struct proc *p;
982
983 /* look in the live processes */
984 if ((p = pfind(pid)) == NULL)
985 /* look in the zombies */
986 p = zpfind(pid);
987
988 return p;
989 }
990
991
992 int
993 svr4_sys_pgrpsys(td, uap)
994 struct thread *td;
995 struct svr4_sys_pgrpsys_args *uap;
996 {
997 int *retval = td->td_retval;
998 struct proc *p = td->td_proc;
999
1000 switch (uap->cmd) {
1001 case 1: /* setpgrp() */
1002 /*
1003 * SVR4 setpgrp() (which takes no arguments) has the
1004 * semantics that the session ID is also created anew, so
1005 * in almost every sense, setpgrp() is identical to
1006 * setsid() for SVR4. (Under BSD, the difference is that
1007 * a setpgid(0,0) will not create a new session.)
1008 */
1009 setsid(td, NULL);
1010 /*FALLTHROUGH*/
1011
1012 case 0: /* getpgrp() */
1013 PROC_LOCK(p);
1014 *retval = p->p_pgrp->pg_id;
1015 PROC_UNLOCK(p);
1016 return 0;
1017
1018 case 2: /* getsid(pid) */
1019 if (uap->pid == 0)
1020 PROC_LOCK(p);
1021 else if ((p = svr4_pfind(uap->pid)) == NULL)
1022 return ESRCH;
1023 /*
1024 * This has already been initialized to the pid of
1025 * the session leader.
1026 */
1027 *retval = (register_t) p->p_session->s_sid;
1028 PROC_UNLOCK(p);
1029 return 0;
1030
1031 case 3: /* setsid() */
1032 return setsid(td, NULL);
1033
1034 case 4: /* getpgid(pid) */
1035
1036 if (uap->pid == 0)
1037 PROC_LOCK(p);
1038 else if ((p = svr4_pfind(uap->pid)) == NULL)
1039 return ESRCH;
1040
1041 *retval = (int) p->p_pgrp->pg_id;
1042 PROC_UNLOCK(p);
1043 return 0;
1044
1045 case 5: /* setpgid(pid, pgid); */
1046 {
1047 struct setpgid_args sa;
1048
1049 sa.pid = uap->pid;
1050 sa.pgid = uap->pgid;
1051 return setpgid(td, &sa);
1052 }
1053
1054 default:
1055 return EINVAL;
1056 }
1057 }
1058
1059 #define syscallarg(x) union { x datum; register_t pad; }
1060
1061 struct svr4_hrtcntl_args {
1062 int cmd;
1063 int fun;
1064 int clk;
1065 svr4_hrt_interval_t * iv;
1066 svr4_hrt_time_t * ti;
1067 };
1068
1069
1070 static int
1071 svr4_hrtcntl(td, uap, retval)
1072 struct thread *td;
1073 struct svr4_hrtcntl_args *uap;
1074 register_t *retval;
1075 {
1076 switch (uap->fun) {
1077 case SVR4_HRT_CNTL_RES:
1078 DPRINTF(("htrcntl(RES)\n"));
1079 *retval = SVR4_HRT_USEC;
1080 return 0;
1081
1082 case SVR4_HRT_CNTL_TOFD:
1083 DPRINTF(("htrcntl(TOFD)\n"));
1084 {
1085 struct timeval tv;
1086 svr4_hrt_time_t t;
1087 if (uap->clk != SVR4_HRT_CLK_STD) {
1088 DPRINTF(("clk == %d\n", uap->clk));
1089 return EINVAL;
1090 }
1091 if (uap->ti == NULL) {
1092 DPRINTF(("ti NULL\n"));
1093 return EINVAL;
1094 }
1095 microtime(&tv);
1096 t.h_sec = tv.tv_sec;
1097 t.h_rem = tv.tv_usec;
1098 t.h_res = SVR4_HRT_USEC;
1099 return copyout(&t, uap->ti, sizeof(t));
1100 }
1101
1102 case SVR4_HRT_CNTL_START:
1103 DPRINTF(("htrcntl(START)\n"));
1104 return ENOSYS;
1105
1106 case SVR4_HRT_CNTL_GET:
1107 DPRINTF(("htrcntl(GET)\n"));
1108 return ENOSYS;
1109 default:
1110 DPRINTF(("Bad htrcntl command %d\n", uap->fun));
1111 return ENOSYS;
1112 }
1113 }
1114
1115
1116 int
1117 svr4_sys_hrtsys(td, uap)
1118 struct thread *td;
1119 struct svr4_sys_hrtsys_args *uap;
1120 {
1121 int *retval = td->td_retval;
1122
1123 switch (uap->cmd) {
1124 case SVR4_HRT_CNTL:
1125 return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
1126 retval);
1127
1128 case SVR4_HRT_ALRM:
1129 DPRINTF(("hrtalarm\n"));
1130 return ENOSYS;
1131
1132 case SVR4_HRT_SLP:
1133 DPRINTF(("hrtsleep\n"));
1134 return ENOSYS;
1135
1136 case SVR4_HRT_CAN:
1137 DPRINTF(("hrtcancel\n"));
1138 return ENOSYS;
1139
1140 default:
1141 DPRINTF(("Bad hrtsys command %d\n", uap->cmd));
1142 return EINVAL;
1143 }
1144 }
1145
1146
1147 static int
1148 svr4_setinfo(p, st, s)
1149 struct proc *p;
1150 int st;
1151 svr4_siginfo_t *s;
1152 {
1153 svr4_siginfo_t i;
1154 int sig;
1155
1156 memset(&i, 0, sizeof(i));
1157
1158 i.si_signo = SVR4_SIGCHLD;
1159 i.si_errno = 0; /* XXX? */
1160
1161 if (p) {
1162 i.si_pid = p->p_pid;
1163 mtx_lock_spin(&sched_lock);
1164 if (p->p_state == PRS_ZOMBIE) {
1165 i.si_stime = p->p_ru->ru_stime.tv_sec;
1166 i.si_utime = p->p_ru->ru_utime.tv_sec;
1167 }
1168 else {
1169 i.si_stime = p->p_stats->p_ru.ru_stime.tv_sec;
1170 i.si_utime = p->p_stats->p_ru.ru_utime.tv_sec;
1171 }
1172 mtx_unlock_spin(&sched_lock);
1173 }
1174
1175 if (WIFEXITED(st)) {
1176 i.si_status = WEXITSTATUS(st);
1177 i.si_code = SVR4_CLD_EXITED;
1178 } else if (WIFSTOPPED(st)) {
1179 sig = WSTOPSIG(st);
1180 if (sig >= 0 && sig < NSIG)
1181 i.si_status = SVR4_BSD2SVR4_SIG(sig);
1182
1183 if (i.si_status == SVR4_SIGCONT)
1184 i.si_code = SVR4_CLD_CONTINUED;
1185 else
1186 i.si_code = SVR4_CLD_STOPPED;
1187 } else {
1188 sig = WTERMSIG(st);
1189 if (sig >= 0 && sig < NSIG)
1190 i.si_status = SVR4_BSD2SVR4_SIG(sig);
1191
1192 if (WCOREDUMP(st))
1193 i.si_code = SVR4_CLD_DUMPED;
1194 else
1195 i.si_code = SVR4_CLD_KILLED;
1196 }
1197
1198 DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1199 i.si_pid, i.si_signo, i.si_code, i.si_errno, i.si_status));
1200
1201 return copyout(&i, s, sizeof(i));
1202 }
1203
1204
1205 int
1206 svr4_sys_waitsys(td, uap)
1207 struct thread *td;
1208 struct svr4_sys_waitsys_args *uap;
1209 {
1210 int nfound;
1211 int error, *retval = td->td_retval;
1212 struct proc *q, *t;
1213
1214
1215 switch (uap->grp) {
1216 case SVR4_P_PID:
1217 break;
1218
1219 case SVR4_P_PGID:
1220 PROC_LOCK(td->td_proc);
1221 uap->id = -td->td_proc->p_pgid;
1222 PROC_UNLOCK(td->td_proc);
1223 break;
1224
1225 case SVR4_P_ALL:
1226 uap->id = WAIT_ANY;
1227 break;
1228
1229 default:
1230 return EINVAL;
1231 }
1232
1233 DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1234 uap->grp, uap->id,
1235 uap->info, uap->options));
1236
1237 loop:
1238 nfound = 0;
1239 sx_slock(&proctree_lock);
1240 LIST_FOREACH(q, &td->td_proc->p_children, p_sibling) {
1241 PROC_LOCK(q);
1242 if (uap->id != WAIT_ANY &&
1243 q->p_pid != uap->id &&
1244 q->p_pgid != -uap->id) {
1245 PROC_UNLOCK(q);
1246 DPRINTF(("pid %d pgid %d != %d\n", q->p_pid,
1247 q->p_pgid, uap->id));
1248 continue;
1249 }
1250 nfound++;
1251 if ((q->p_state == PRS_ZOMBIE) &&
1252 ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
1253 PROC_UNLOCK(q);
1254 sx_sunlock(&proctree_lock);
1255 *retval = 0;
1256 DPRINTF(("found %d\n", q->p_pid));
1257 error = svr4_setinfo(q, q->p_xstat, uap->info);
1258 if (error != 0)
1259 return error;
1260
1261
1262 if ((uap->options & SVR4_WNOWAIT)) {
1263 DPRINTF(("Don't wait\n"));
1264 return 0;
1265 }
1266
1267 /*
1268 * If we got the child via ptrace(2) or procfs, and
1269 * the parent is different (meaning the process was
1270 * attached, rather than run as a child), then we need
1271 * to give it back to the old parent, and send the
1272 * parent a SIGCHLD. The rest of the cleanup will be
1273 * done when the old parent waits on the child.
1274 */
1275 sx_xlock(&proctree_lock);
1276 PROC_LOCK(q);
1277 if (q->p_flag & P_TRACED) {
1278 if (q->p_oppid != q->p_pptr->p_pid) {
1279 PROC_UNLOCK(q);
1280 t = pfind(q->p_oppid);
1281 if (t == NULL) {
1282 t = initproc;
1283 PROC_LOCK(initproc);
1284 }
1285 PROC_LOCK(q);
1286 proc_reparent(q, t);
1287 q->p_oppid = 0;
1288 q->p_flag &= ~(P_TRACED | P_WAITED);
1289 PROC_UNLOCK(q);
1290 psignal(t, SIGCHLD);
1291 wakeup(t);
1292 PROC_UNLOCK(t);
1293 sx_xunlock(&proctree_lock);
1294 return 0;
1295 }
1296 }
1297 PROC_UNLOCK(q);
1298 sx_xunlock(&proctree_lock);
1299 q->p_xstat = 0;
1300 ruadd(&td->td_proc->p_stats->p_cru, q->p_ru);
1301 FREE(q->p_ru, M_ZOMBIE);
1302 q->p_ru = 0;
1303
1304 /*
1305 * Decrement the count of procs running with this uid.
1306 */
1307 (void)chgproccnt(q->p_ucred->cr_ruidinfo, -1, 0);
1308
1309 /*
1310 * Release reference to text vnode.
1311 */
1312 if (q->p_textvp)
1313 vrele(q->p_textvp);
1314
1315 /*
1316 * Free up credentials.
1317 */
1318 crfree(q->p_ucred);
1319 q->p_ucred = NULL;
1320
1321 /*
1322 * Remove unused arguments
1323 */
1324 pargs_drop(q->p_args);
1325 PROC_UNLOCK(q);
1326
1327 /*
1328 * Finally finished with old proc entry.
1329 * Unlink it from its process group and free it.
1330 */
1331 sx_xlock(&proctree_lock);
1332 leavepgrp(q);
1333
1334 sx_xlock(&allproc_lock);
1335 LIST_REMOVE(q, p_list); /* off zombproc */
1336 sx_xunlock(&allproc_lock);
1337
1338 LIST_REMOVE(q, p_sibling);
1339 sx_xunlock(&proctree_lock);
1340
1341 PROC_LOCK(q);
1342 sigacts_free(q->p_sigacts);
1343 q->p_sigacts = NULL;
1344 PROC_UNLOCK(q);
1345
1346 /*
1347 * Give machine-dependent layer a chance
1348 * to free anything that cpu_exit couldn't
1349 * release while still running in process context.
1350 */
1351 vm_waitproc(q);
1352 #if defined(__NetBSD__)
1353 pool_put(&proc_pool, q);
1354 #endif
1355 #ifdef __FreeBSD__
1356 mtx_destroy(&q->p_mtx);
1357 #ifdef MAC
1358 mac_destroy_proc(q);
1359 #endif
1360 uma_zfree(proc_zone, q);
1361 #endif
1362 nprocs--;
1363 return 0;
1364 }
1365 /* XXXKSE this needs clarification */
1366 if (P_SHOULDSTOP(q) && ((q->p_flag & P_WAITED) == 0) &&
1367 (q->p_flag & P_TRACED ||
1368 (uap->options & (SVR4_WSTOPPED|SVR4_WCONTINUED)))) {
1369 DPRINTF(("jobcontrol %d\n", q->p_pid));
1370 if (((uap->options & SVR4_WNOWAIT)) == 0)
1371 q->p_flag |= P_WAITED;
1372 PROC_UNLOCK(q);
1373 *retval = 0;
1374 return svr4_setinfo(q, W_STOPCODE(q->p_xstat),
1375 uap->info);
1376 }
1377 PROC_UNLOCK(q);
1378 }
1379
1380 if (nfound == 0)
1381 return ECHILD;
1382
1383 if (uap->options & SVR4_WNOHANG) {
1384 *retval = 0;
1385 if ((error = svr4_setinfo(NULL, 0, uap->info)) != 0)
1386 return error;
1387 return 0;
1388 }
1389
1390 if ((error = tsleep(td->td_proc, PWAIT | PCATCH, "svr4_wait", 0)) != 0)
1391 return error;
1392 goto loop;
1393 }
1394
1395
1396 static void
1397 bsd_statfs_to_svr4_statvfs(bfs, sfs)
1398 const struct statfs *bfs;
1399 struct svr4_statvfs *sfs;
1400 {
1401 sfs->f_bsize = bfs->f_iosize; /* XXX */
1402 sfs->f_frsize = bfs->f_bsize;
1403 sfs->f_blocks = bfs->f_blocks;
1404 sfs->f_bfree = bfs->f_bfree;
1405 sfs->f_bavail = bfs->f_bavail;
1406 sfs->f_files = bfs->f_files;
1407 sfs->f_ffree = bfs->f_ffree;
1408 sfs->f_favail = bfs->f_ffree;
1409 sfs->f_fsid = bfs->f_fsid.val[0];
1410 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1411 sfs->f_flag = 0;
1412 if (bfs->f_flags & MNT_RDONLY)
1413 sfs->f_flag |= SVR4_ST_RDONLY;
1414 if (bfs->f_flags & MNT_NOSUID)
1415 sfs->f_flag |= SVR4_ST_NOSUID;
1416 sfs->f_namemax = MAXNAMLEN;
1417 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1418 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1419 }
1420
1421
1422 static void
1423 bsd_statfs_to_svr4_statvfs64(bfs, sfs)
1424 const struct statfs *bfs;
1425 struct svr4_statvfs64 *sfs;
1426 {
1427 sfs->f_bsize = bfs->f_iosize; /* XXX */
1428 sfs->f_frsize = bfs->f_bsize;
1429 sfs->f_blocks = bfs->f_blocks;
1430 sfs->f_bfree = bfs->f_bfree;
1431 sfs->f_bavail = bfs->f_bavail;
1432 sfs->f_files = bfs->f_files;
1433 sfs->f_ffree = bfs->f_ffree;
1434 sfs->f_favail = bfs->f_ffree;
1435 sfs->f_fsid = bfs->f_fsid.val[0];
1436 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1437 sfs->f_flag = 0;
1438 if (bfs->f_flags & MNT_RDONLY)
1439 sfs->f_flag |= SVR4_ST_RDONLY;
1440 if (bfs->f_flags & MNT_NOSUID)
1441 sfs->f_flag |= SVR4_ST_NOSUID;
1442 sfs->f_namemax = MAXNAMLEN;
1443 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1444 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1445 }
1446
1447
1448 int
1449 svr4_sys_statvfs(td, uap)
1450 struct thread *td;
1451 struct svr4_sys_statvfs_args *uap;
1452 {
1453 struct statfs_args fs_args;
1454 caddr_t sg = stackgap_init();
1455 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
1456 struct statfs bfs;
1457 struct svr4_statvfs sfs;
1458 int error;
1459
1460 CHECKALTEXIST(td, &sg, uap->path);
1461 fs_args.path = uap->path;
1462 fs_args.buf = fs;
1463
1464 if ((error = statfs(td, &fs_args)) != 0)
1465 return error;
1466
1467 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
1468 return error;
1469
1470 bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1471
1472 return copyout(&sfs, uap->fs, sizeof(sfs));
1473 }
1474
1475
1476 int
1477 svr4_sys_fstatvfs(td, uap)
1478 struct thread *td;
1479 struct svr4_sys_fstatvfs_args *uap;
1480 {
1481 struct fstatfs_args fs_args;
1482 caddr_t sg = stackgap_init();
1483 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
1484 struct statfs bfs;
1485 struct svr4_statvfs sfs;
1486 int error;
1487
1488 fs_args.fd = uap->fd;
1489 fs_args.buf = fs;
1490
1491 if ((error = fstatfs(td, &fs_args)) != 0)
1492 return error;
1493
1494 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
1495 return error;
1496
1497 bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1498
1499 return copyout(&sfs, uap->fs, sizeof(sfs));
1500 }
1501
1502
1503 int
1504 svr4_sys_statvfs64(td, uap)
1505 struct thread *td;
1506 struct svr4_sys_statvfs64_args *uap;
1507 {
1508 struct statfs_args fs_args;
1509 caddr_t sg = stackgap_init();
1510 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
1511 struct statfs bfs;
1512 struct svr4_statvfs64 sfs;
1513 int error;
1514
1515 CHECKALTEXIST(td, &sg, uap->path);
1516 fs_args.path = uap->path;
1517 fs_args.buf = fs;
1518
1519 if ((error = statfs(td, &fs_args)) != 0)
1520 return error;
1521
1522 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
1523 return error;
1524
1525 bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1526
1527 return copyout(&sfs, uap->fs, sizeof(sfs));
1528 }
1529
1530
1531 int
1532 svr4_sys_fstatvfs64(td, uap)
1533 struct thread *td;
1534 struct svr4_sys_fstatvfs64_args *uap;
1535 {
1536 struct fstatfs_args fs_args;
1537 caddr_t sg = stackgap_init();
1538 struct statfs *fs = stackgap_alloc(&sg, sizeof(struct statfs));
1539 struct statfs bfs;
1540 struct svr4_statvfs64 sfs;
1541 int error;
1542
1543 fs_args.fd = uap->fd;
1544 fs_args.buf = fs;
1545
1546 if ((error = fstatfs(td, &fs_args)) != 0)
1547 return error;
1548
1549 if ((error = copyin(fs, &bfs, sizeof(bfs))) != 0)
1550 return error;
1551
1552 bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1553
1554 return copyout(&sfs, uap->fs, sizeof(sfs));
1555 }
1556
1557 int
1558 svr4_sys_alarm(td, uap)
1559 struct thread *td;
1560 struct svr4_sys_alarm_args *uap;
1561 {
1562 int error;
1563 struct itimerval *itp, *oitp;
1564 struct setitimer_args sa;
1565 caddr_t sg = stackgap_init();
1566
1567 itp = stackgap_alloc(&sg, sizeof(*itp));
1568 oitp = stackgap_alloc(&sg, sizeof(*oitp));
1569 timevalclear(&itp->it_interval);
1570 itp->it_value.tv_sec = uap->sec;
1571 itp->it_value.tv_usec = 0;
1572
1573 sa.which = ITIMER_REAL;
1574 sa.itv = itp;
1575 sa.oitv = oitp;
1576 error = setitimer(td, &sa);
1577 if (error)
1578 return error;
1579 if (oitp->it_value.tv_usec)
1580 oitp->it_value.tv_sec++;
1581 td->td_retval[0] = oitp->it_value.tv_sec;
1582 return 0;
1583
1584 }
1585
1586 int
1587 svr4_sys_gettimeofday(td, uap)
1588 struct thread *td;
1589 struct svr4_sys_gettimeofday_args *uap;
1590 {
1591 if (uap->tp) {
1592 struct timeval atv;
1593
1594 microtime(&atv);
1595 return copyout(&atv, uap->tp, sizeof (atv));
1596 }
1597
1598 return 0;
1599 }
1600
1601 int
1602 svr4_sys_facl(td, uap)
1603 struct thread *td;
1604 struct svr4_sys_facl_args *uap;
1605 {
1606 int *retval;
1607
1608 retval = td->td_retval;
1609 *retval = 0;
1610
1611 switch (uap->cmd) {
1612 case SVR4_SYS_SETACL:
1613 /* We don't support acls on any filesystem */
1614 return ENOSYS;
1615
1616 case SVR4_SYS_GETACL:
1617 return copyout(retval, &uap->num,
1618 sizeof(uap->num));
1619
1620 case SVR4_SYS_GETACLCNT:
1621 return 0;
1622
1623 default:
1624 return EINVAL;
1625 }
1626 }
1627
1628
1629 int
1630 svr4_sys_acl(td, uap)
1631 struct thread *td;
1632 struct svr4_sys_acl_args *uap;
1633 {
1634 /* XXX: for now the same */
1635 return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
1636 }
1637
1638 int
1639 svr4_sys_auditsys(td, uap)
1640 struct thread *td;
1641 struct svr4_sys_auditsys_args *uap;
1642 {
1643 /*
1644 * XXX: Big brother is *not* watching.
1645 */
1646 return 0;
1647 }
1648
1649 int
1650 svr4_sys_memcntl(td, uap)
1651 struct thread *td;
1652 struct svr4_sys_memcntl_args *uap;
1653 {
1654 switch (uap->cmd) {
1655 case SVR4_MC_SYNC:
1656 {
1657 struct msync_args msa;
1658
1659 msa.addr = uap->addr;
1660 msa.len = uap->len;
1661 msa.flags = (int)uap->arg;
1662
1663 return msync(td, &msa);
1664 }
1665 case SVR4_MC_ADVISE:
1666 {
1667 struct madvise_args maa;
1668
1669 maa.addr = uap->addr;
1670 maa.len = uap->len;
1671 maa.behav = (int)uap->arg;
1672
1673 return madvise(td, &maa);
1674 }
1675 case SVR4_MC_LOCK:
1676 case SVR4_MC_UNLOCK:
1677 case SVR4_MC_LOCKAS:
1678 case SVR4_MC_UNLOCKAS:
1679 return EOPNOTSUPP;
1680 default:
1681 return ENOSYS;
1682 }
1683 }
1684
1685
1686 int
1687 svr4_sys_nice(td, uap)
1688 struct thread *td;
1689 struct svr4_sys_nice_args *uap;
1690 {
1691 struct setpriority_args ap;
1692 int error;
1693
1694 ap.which = PRIO_PROCESS;
1695 ap.who = 0;
1696 ap.prio = uap->prio;
1697
1698 if ((error = setpriority(td, &ap)) != 0)
1699 return error;
1700
1701 /* the cast is stupid, but the structures are the same */
1702 if ((error = getpriority(td, (struct getpriority_args *)&ap)) != 0)
1703 return error;
1704
1705 return 0;
1706 }
1707
1708 int
1709 svr4_sys_resolvepath(td, uap)
1710 struct thread *td;
1711 struct svr4_sys_resolvepath_args *uap;
1712 {
1713 struct nameidata nd;
1714 int error, *retval = td->td_retval;
1715 unsigned int ncopy;
1716
1717 NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME, UIO_USERSPACE,
1718 uap->path, td);
1719
1720 if ((error = namei(&nd)) != 0)
1721 return error;
1722
1723 ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
1724 if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
1725 goto bad;
1726
1727 *retval = ncopy;
1728 bad:
1729 NDFREE(&nd, NDF_ONLY_PNBUF);
1730 vput(nd.ni_vp);
1731 return error;
1732 }
Cache object: d0ccb3c1ed9c2fb6290c5cbfbd5cc885
|