1 /* $NetBSD: svr4_32_misc.c,v 1.63.6.1 2010/03/17 02:59:53 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_32_misc.c,v 1.63.6.1 2010/03/17 02:59:53 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_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>
94
95 #include <sys/cpu.h>
96
97 #include <uvm/uvm_extern.h>
98
99 static int svr4_to_bsd_mmap_flags(int);
100
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);
103
104 #define svr4_32_pfind(pid) p_find((pid), PFIND_UNLOCK | PFIND_ZOMBIE)
105
106 static int svr4_32_mknod(struct lwp *, register_t *, const char *,
107 svr4_32_mode_t, svr4_32_dev_t);
108
109 int
110 svr4_32_sys_wait(struct lwp *l, const struct svr4_32_sys_wait_args *uap, register_t *retval)
111 {
112 int error, was_zombie;
113 int pid = WAIT_ANY;
114 int st, sig;
115
116 error = do_sys_wait(l, &pid, &st, 0, NULL, &was_zombie);
117
118 retval[0] = pid;
119 if (pid == 0)
120 return error;
121
122 if (WIFSIGNALED(st)) {
123 sig = WTERMSIG(st);
124 if (sig >= 0 && sig < NSIG)
125 st = (st & ~0177) | native_to_svr4_signo[sig];
126 } else if (WIFSTOPPED(st)) {
127 sig = WSTOPSIG(st);
128 if (sig >= 0 && sig < NSIG)
129 st = (st & ~0xff00) | (native_to_svr4_signo[sig] << 8);
130 }
131
132 /*
133 * It looks like wait(2) on svr4/solaris/2.4 returns
134 * the status in retval[1], and the pid on retval[0].
135 */
136 retval[1] = st;
137
138 if (SCARG_P32(uap, status))
139 error = copyout(&st, SCARG_P32(uap, status), sizeof(st));
140 return error;
141 }
142
143
144 int
145 svr4_32_sys_execv(struct lwp *l, const struct svr4_32_sys_execv_args *uap, register_t *retval)
146 {
147 /* {
148 syscallarg(char *) path;
149 syscallarg(char **) argv;
150 } */
151 struct netbsd32_execve_args ap;
152
153 SCARG(&ap, path) = SCARG(uap, path);
154 SCARG(&ap, argp) = SCARG(uap, argp);
155 NETBSD32PTR32(SCARG(&ap, envp), 0);
156
157 return netbsd32_execve(l, &ap, retval);
158 }
159
160 #if 0
161 int
162 svr4_32_sys_execve(struct proc *p, void *v, register_t *retval)
163 {
164 struct svr4_32_sys_execve_args /* {
165 syscallarg(const char *) path;
166 syscallarg(char **) argv;
167 syscallarg(char **) envp;
168 } */ *uap = v;
169 struct sys_execve_args ap;
170
171 SCARG(&ap, path) = SCARG_P32(uap, path);
172 SCARG(&ap, argp) = SCARG_P32(uap, argp);
173 SCARG(&ap, envp) = SCARG_P32(uap, envp);
174
175 return netbsd32_execve(p, &ap, retval);
176 }
177 #endif
178
179 int
180 svr4_32_sys_time(struct lwp *l, const struct svr4_32_sys_time_args *uap, register_t *retval)
181 {
182 int error = 0;
183 struct timeval tv;
184 struct netbsd32_timeval ntv;
185
186 microtime(&tv);
187 ntv.tv_sec = tv.tv_sec;
188 ntv.tv_usec = tv.tv_usec;
189 if (SCARG_P32(uap, t))
190 error = copyout(&ntv.tv_sec, SCARG_P32(uap, t),
191 sizeof(ntv.tv_sec));
192 *retval = (int) ntv.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_32_sys_getdents64(struct lwp *l, const struct svr4_32_sys_getdents64_args *uap, register_t *retval)
207 {
208 struct dirent *bdp;
209 struct vnode *vp;
210 char *inp, *sbuf; /* BSD-format */
211 int len, reclen; /* BSD-format */
212 char *outp; /* SVR4-format */
213 int resid, svr4_32_reclen; /* SVR4-format */
214 file_t *fp;
215 struct uio auio;
216 struct iovec aiov;
217 struct svr4_32_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 = 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 sbuf = 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 = sbuf;
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 = sbuf;
261 outp = SCARG_P32(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_32_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_32_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
280 if (reclen > len || resid < svr4_32_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_32_ino64_t)bdp->d_fileno;
295 idb.d_off = (svr4_32_off64_t)off;
296 idb.d_reclen = (u_short)svr4_32_reclen;
297 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
298 if ((error = copyout((void *)&idb, outp, svr4_32_reclen)))
299 goto out;
300 /* advance past this real entry */
301 inp += reclen;
302 /* advance output past SVR4-shaped entry */
303 outp += svr4_32_reclen;
304 resid -= svr4_32_reclen;
305 }
306
307 /* if we squished out the whole block, try again */
308 if (outp == SCARG_P32(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(sbuf, M_TEMP);
323 out1:
324 fd_putfile(SCARG(uap, fd));
325 return error;
326 }
327
328
329 int
330 svr4_32_sys_getdents(struct lwp *l, const struct svr4_32_sys_getdents_args *uap, register_t *retval)
331 {
332 struct dirent *bdp;
333 struct vnode *vp;
334 char *inp, *sbuf; /* BSD-format */
335 int len, reclen; /* BSD-format */
336 char *outp; /* SVR4-format */
337 int resid, svr4_reclen; /* SVR4-format */
338 file_t *fp;
339 struct uio auio;
340 struct iovec aiov;
341 struct svr4_32_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 = 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 sbuf = 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 = sbuf;
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 = sbuf;
385 outp = SCARG_P32(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_32_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_32_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_32_ino_t)bdp->d_fileno;
420 idb.d_off = (svr4_32_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_P32(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(sbuf, 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_32_sys_mmap(struct lwp *l, const struct svr4_32_sys_mmap_args *uap, register_t *retval)
473 {
474 struct sys_mmap_args mm;
475 int error;
476 /*
477 * Verify the arguments.
478 */
479 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
480 return EINVAL; /* XXX still needed? */
481
482 if (SCARG(uap, len) == 0)
483 return EINVAL;
484
485 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
486 return EINVAL;
487
488 SCARG(&mm, prot) = SCARG(uap, prot);
489 SCARG(&mm, len) = SCARG(uap, len);
490 SCARG(&mm, fd) = SCARG(uap, fd);
491 SCARG(&mm, addr) = SCARG_P32(uap, addr);
492 SCARG(&mm, pos) = SCARG(uap, pos);
493
494 error = sys_mmap(l, &mm, retval);
495 if ((u_long)*retval > (u_long)UINT_MAX) {
496 printf("svr4_32_mmap: retval out of range: 0x%lx",
497 (u_long)*retval);
498 /* Should try to recover and return an error here. */
499 }
500 return (error);
501 }
502
503
504 int
505 svr4_32_sys_mmap64(struct lwp *l, const struct svr4_32_sys_mmap64_args *uap, register_t *retval)
506 {
507 struct sys_mmap_args mm;
508 int error;
509 /*
510 * Verify the arguments.
511 */
512 if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
513 return EINVAL; /* XXX still needed? */
514
515 if (SCARG(uap, len) == 0)
516 return EINVAL;
517
518 if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
519 return EINVAL;
520
521 SCARG(&mm, prot) = SCARG(uap, prot);
522 SCARG(&mm, len) = SCARG(uap, len);
523 SCARG(&mm, fd) = SCARG(uap, fd);
524 SCARG(&mm, addr) = SCARG_P32(uap, addr);
525 SCARG(&mm, pos) = SCARG(uap, pos);
526
527 error = sys_mmap(l, &mm, retval);
528 if ((u_long)*retval > (u_long)UINT_MAX) {
529 printf("svr4_32_mmap64: retval out of range: 0x%lx",
530 (u_long)*retval);
531 /* Should try to recover and return an error here. */
532 }
533 return (error);
534 }
535
536
537 static int
538 svr4_32_mknod(struct lwp *l, register_t *retval, const char *path, svr4_32_mode_t mode, svr4_32_dev_t dev)
539 {
540 if (S_ISFIFO(mode)) {
541 struct sys_mkfifo_args ap;
542 SCARG(&ap, path) = path;
543 SCARG(&ap, mode) = mode;
544 return sys_mkfifo(l, &ap, retval);
545 } else {
546 struct sys_mknod_args ap;
547 SCARG(&ap, path) = path;
548 SCARG(&ap, mode) = mode;
549 SCARG(&ap, dev) = dev;
550 return sys_mknod(l, &ap, retval);
551 }
552 }
553
554
555 int
556 svr4_32_sys_mknod(struct lwp *l, const struct svr4_32_sys_mknod_args *uap, register_t *retval)
557 {
558 return svr4_32_mknod(l, retval,
559 SCARG_P32(uap, path), SCARG(uap, mode),
560 svr4_32_to_bsd_odev_t(SCARG(uap, dev)));
561 }
562
563
564 int
565 svr4_32_sys_xmknod(struct lwp *l, const struct svr4_32_sys_xmknod_args *uap, register_t *retval)
566 {
567 return svr4_32_mknod(l, retval,
568 SCARG_P32(uap, path), SCARG(uap, mode),
569 svr4_32_to_bsd_dev_t(SCARG(uap, dev)));
570 }
571
572
573 int
574 svr4_32_sys_vhangup(struct lwp *l, const void *v, register_t *retval)
575 {
576 return 0;
577 }
578
579
580 int
581 svr4_32_sys_sysconfig(struct lwp *l, const struct svr4_32_sys_sysconfig_args *uap, register_t *retval)
582 {
583 extern u_int maxfiles;
584 int active;
585
586 switch (SCARG(uap, name)) {
587 case SVR4_CONFIG_NGROUPS:
588 *retval = NGROUPS_MAX;
589 break;
590 case SVR4_CONFIG_CHILD_MAX:
591 *retval = maxproc;
592 break;
593 case SVR4_CONFIG_OPEN_FILES:
594 *retval = maxfiles;
595 break;
596 case SVR4_CONFIG_POSIX_VER:
597 *retval = 198808;
598 break;
599 case SVR4_CONFIG_PAGESIZE:
600 *retval = PAGE_SIZE;
601 break;
602 case SVR4_CONFIG_CLK_TCK:
603 *retval = 60; /* should this be `hz', ie. 100? */
604 break;
605 case SVR4_CONFIG_XOPEN_VER:
606 *retval = 2; /* XXX: What should that be? */
607 break;
608 case SVR4_CONFIG_PROF_TCK:
609 *retval = 60; /* XXX: What should that be? */
610 break;
611 case SVR4_CONFIG_NPROC_CONF:
612 *retval = 1; /* Only one processor for now */
613 break;
614 case SVR4_CONFIG_NPROC_ONLN:
615 *retval = 1; /* And it better be online */
616 break;
617 case SVR4_CONFIG_AIO_LISTIO_MAX:
618 case SVR4_CONFIG_AIO_MAX:
619 case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
620 *retval = 0; /* No aio support */
621 break;
622 case SVR4_CONFIG_DELAYTIMER_MAX:
623 *retval = 0; /* No delaytimer support */
624 break;
625 case SVR4_CONFIG_MQ_OPEN_MAX:
626 #ifdef SYSVMSG
627 *retval = msginfo.msgmni;
628 #else
629 *retval = 0;
630 #endif
631 break;
632 case SVR4_CONFIG_MQ_PRIO_MAX:
633 *retval = 0; /* XXX: Don't know */
634 break;
635 case SVR4_CONFIG_RTSIG_MAX:
636 *retval = 0;
637 break;
638 case SVR4_CONFIG_SEM_NSEMS_MAX:
639 #ifdef SYSVSEM
640 *retval = seminfo.semmni;
641 #else
642 *retval = 0;
643 #endif
644 break;
645 case SVR4_CONFIG_SEM_VALUE_MAX:
646 #ifdef SYSVSEM
647 *retval = seminfo.semvmx;
648 #else
649 *retval = 0;
650 #endif
651 break;
652 case SVR4_CONFIG_SIGQUEUE_MAX:
653 *retval = 0; /* XXX: Don't know */
654 break;
655 case SVR4_CONFIG_SIGRT_MIN:
656 case SVR4_CONFIG_SIGRT_MAX:
657 *retval = 0; /* No real time signals */
658 break;
659 case SVR4_CONFIG_TIMER_MAX:
660 *retval = 3; /* XXX: real, virtual, profiling */
661 break;
662 case SVR4_CONFIG_PHYS_PAGES:
663 *retval = uvmexp.free; /* XXX: free instead of total */
664 break;
665 case SVR4_CONFIG_AVPHYS_PAGES:
666 uvm_estimatepageable(&active, NULL);
667 *retval = active; /* XXX: active instead of avg */
668 break;
669 case SVR4_CONFIG_COHERENCY:
670 *retval = 0; /* XXX */
671 break;
672 case SVR4_CONFIG_SPLIT_CACHE:
673 *retval = 0; /* XXX */
674 break;
675 case SVR4_CONFIG_ICACHESZ:
676 *retval = 256; /* XXX */
677 break;
678 case SVR4_CONFIG_DCACHESZ:
679 *retval = 256; /* XXX */
680 break;
681 case SVR4_CONFIG_ICACHELINESZ:
682 *retval = 64; /* XXX */
683 break;
684 case SVR4_CONFIG_DCACHELINESZ:
685 *retval = 64; /* XXX */
686 break;
687 case SVR4_CONFIG_ICACHEBLKSZ:
688 *retval = 64; /* XXX */
689 break;
690 case SVR4_CONFIG_DCACHEBLKSZ:
691 *retval = 64; /* XXX */
692 break;
693 case SVR4_CONFIG_DCACHETBLKSZ:
694 *retval = 64; /* XXX */
695 break;
696 case SVR4_CONFIG_ICACHE_ASSOC:
697 *retval = 1; /* XXX */
698 break;
699 case SVR4_CONFIG_DCACHE_ASSOC:
700 *retval = 1; /* XXX */
701 break;
702 case SVR4_CONFIG_MAXPID:
703 *retval = PID_MAX;
704 break;
705 case SVR4_CONFIG_STACK_PROT:
706 *retval = PROT_READ|PROT_WRITE|PROT_EXEC;
707 break;
708 default:
709 return EINVAL;
710 }
711 return 0;
712 }
713
714
715 /* ARGSUSED */
716 int
717 svr4_32_sys_break(struct lwp *l, const struct svr4_32_sys_break_args *uap, register_t *retval)
718 {
719 struct proc *p = l->l_proc;
720 struct vmspace *vm = p->p_vmspace;
721 vaddr_t new, old;
722 int error;
723
724 old = (vaddr_t) vm->vm_daddr;
725 new = round_page((vaddr_t)SCARG_P32(uap, nsize));
726
727 if (new - old > p->p_rlimit[RLIMIT_DATA].rlim_cur && new > old)
728 return ENOMEM;
729
730 old = round_page(old + ctob(vm->vm_dsize));
731 DPRINTF(("break(2): dsize = %x ctob %x\n",
732 vm->vm_dsize, ctob(vm->vm_dsize)));
733
734 if (new > old) {
735 error = uvm_map(&vm->vm_map, &old, new - old, NULL,
736 UVM_UNKNOWN_OFFSET, 0,
737 UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
738 UVM_ADV_NORMAL,
739 UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
740 UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
741 if (error) {
742 uprintf("sbrk: grow failed, return = %d\n", error);
743 return error;
744 }
745 vm->vm_dsize += btoc(new - old);
746 } else if (new < old) {
747 uvm_deallocate(&vm->vm_map, new, old - new);
748 vm->vm_dsize -= btoc(old - new);
749 }
750 return 0;
751 }
752
753
754 static inline clock_t
755 timeval_to_clock_t(struct timeval *tv)
756 {
757 return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
758 }
759
760 int
761 svr4_32_sys_times(struct lwp *l, const struct svr4_32_sys_times_args *uap, register_t *retval)
762 {
763 struct tms tms;
764 struct timeval t;
765 struct rusage ru, *rup;
766 struct proc *p = l->l_proc;
767
768 ru = l->l_proc->p_stats->p_ru;
769 mutex_enter(p->p_lock);
770 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
771 rulwps(p, &ru);
772 mutex_exit(p->p_lock);
773
774 tms.tms_utime = timeval_to_clock_t(&ru.ru_utime);
775 tms.tms_stime = timeval_to_clock_t(&ru.ru_stime);
776
777 rup = &l->l_proc->p_stats->p_cru;
778 tms.tms_cutime = timeval_to_clock_t(&rup->ru_utime);
779 tms.tms_cstime = timeval_to_clock_t(&rup->ru_stime);
780
781 microtime(&t);
782 *retval = timeval_to_clock_t(&t);
783
784 return copyout(&tms, SCARG_P32(uap, tp), sizeof(tms));
785 }
786
787
788 int
789 svr4_32_sys_ulimit(struct lwp *l, const struct svr4_32_sys_ulimit_args *uap, register_t *retval)
790 {
791 struct proc *p = l->l_proc;
792 int error;
793 struct rlimit krl;
794 register_t r;
795
796 switch (SCARG(uap, cmd)) {
797 case SVR4_GFILLIM:
798 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;
799 break;
800
801 case SVR4_SFILLIM:
802 krl.rlim_cur = SCARG(uap, newlimit) * 512;
803 krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max;
804
805 error = dosetrlimit(l, l->l_proc, RLIMIT_FSIZE, &krl);
806 if (error)
807 return error;
808
809 r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
810 break;
811
812 case SVR4_GMEMLIM:
813 r = p->p_rlimit[RLIMIT_DATA].rlim_cur;
814 if (r > 0x7fffffff)
815 r = 0x7fffffff;
816 r += (long)p->p_vmspace->vm_daddr;
817 break;
818
819 case SVR4_GDESLIM:
820 r = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
821 break;
822
823 default:
824 return EINVAL;
825 }
826
827 *retval = r > 0x7fffffff ? 0x7fffffff : r;
828 return 0;
829 }
830
831
832 int
833 svr4_32_sys_pgrpsys(struct lwp *l, const struct svr4_32_sys_pgrpsys_args *uap, register_t *retval)
834 {
835 struct proc *p = l->l_proc;
836
837 switch (SCARG(uap, cmd)) {
838 case 1: /* setpgrp() */
839 /*
840 * SVR4 setpgrp() (which takes no arguments) has the
841 * semantics that the session ID is also created anew, so
842 * in almost every sense, setpgrp() is identical to
843 * setsid() for SVR4. (Under BSD, the difference is that
844 * a setpgid(0,0) will not create a new session.)
845 */
846 sys_setsid(l, NULL, retval);
847 /*FALLTHROUGH*/
848
849 case 0: /* getpgrp() */
850 *retval = p->p_pgrp->pg_id;
851 return 0;
852
853 case 2: /* getsid(pid) */
854 if (SCARG(uap, pid) != 0 &&
855 (p = svr4_32_pfind(SCARG(uap, pid))) == NULL)
856 return ESRCH;
857 /*
858 * This has already been initialized to the pid of
859 * the session leader.
860 */
861 *retval = (register_t) p->p_session->s_sid;
862 return 0;
863
864 case 3: /* setsid() */
865 return sys_setsid(l, NULL, retval);
866
867 case 4: /* getpgid(pid) */
868
869 if (SCARG(uap, pid) != 0 &&
870 (p = svr4_32_pfind(SCARG(uap, pid))) == NULL)
871 return ESRCH;
872
873 *retval = (int) p->p_pgrp->pg_id;
874 return 0;
875
876 case 5: /* setpgid(pid, pgid); */
877 {
878 struct sys_setpgid_args sa;
879
880 SCARG(&sa, pid) = SCARG(uap, pid);
881 SCARG(&sa, pgid) = SCARG(uap, pgid);
882 return sys_setpgid(l, &sa, retval);
883 }
884
885 default:
886 return EINVAL;
887 }
888 }
889
890 struct svr4_32_hrtcntl_args {
891 syscallarg(int) cmd;
892 syscallarg(int) fun;
893 syscallarg(int) clk;
894 syscallarg(svr4_32_hrt_interval_tp) iv;
895 syscallarg(svr4_32_hrt_time_tp) ti;
896 };
897
898
899 static int
900 svr4_32_hrtcntl(struct proc *p, const struct svr4_32_hrtcntl_args *uap, register_t *retval)
901 {
902 switch (SCARG(uap, fun)) {
903 case SVR4_HRT_CNTL_RES:
904 DPRINTF(("htrcntl(RES)\n"));
905 *retval = SVR4_HRT_USEC;
906 return 0;
907
908 case SVR4_HRT_CNTL_TOFD:
909 DPRINTF(("htrcntl(TOFD)\n"));
910 {
911 struct timeval tv;
912 svr4_hrt_time_t t;
913 if (SCARG(uap, clk) != SVR4_HRT_CLK_STD) {
914 DPRINTF(("clk == %d\n", SCARG(uap, clk)));
915 return EINVAL;
916 }
917 if (SCARG_P32(uap, ti) == 0) {
918 DPRINTF(("ti NULL\n"));
919 return EINVAL;
920 }
921 microtime(&tv);
922 t.h_sec = tv.tv_sec;
923 t.h_rem = tv.tv_usec;
924 t.h_res = SVR4_HRT_USEC;
925 return copyout(&t, SCARG_P32(uap, ti),
926 sizeof(t));
927 }
928
929 case SVR4_HRT_CNTL_START:
930 DPRINTF(("htrcntl(START)\n"));
931 return ENOSYS;
932
933 case SVR4_HRT_CNTL_GET:
934 DPRINTF(("htrcntl(GET)\n"));
935 return ENOSYS;
936 default:
937 DPRINTF(("Bad htrcntl command %d\n", SCARG(uap, fun)));
938 return ENOSYS;
939 }
940 }
941
942
943 int
944 svr4_32_sys_hrtsys(struct lwp *l, const struct svr4_32_sys_hrtsys_args *uap, register_t *retval)
945 {
946
947 switch (SCARG(uap, cmd)) {
948 case SVR4_HRT_CNTL:
949 return svr4_32_hrtcntl(l->l_proc, (const struct svr4_32_hrtcntl_args *) uap,
950 retval);
951
952 case SVR4_HRT_ALRM:
953 DPRINTF(("hrtalarm\n"));
954 return ENOSYS;
955
956 case SVR4_HRT_SLP:
957 DPRINTF(("hrtsleep\n"));
958 return ENOSYS;
959
960 case SVR4_HRT_CAN:
961 DPRINTF(("hrtcancel\n"));
962 return ENOSYS;
963
964 default:
965 DPRINTF(("Bad hrtsys command %d\n", SCARG(uap, cmd)));
966 return EINVAL;
967 }
968 }
969
970
971 static int
972 svr4_32_setinfo(int pid, struct rusage *ru, int st, svr4_32_siginfo_tp si)
973 {
974 svr4_32_siginfo_t *s = NETBSD32PTR64(si);
975 svr4_32_siginfo_t i;
976 int sig;
977
978 memset(&i, 0, sizeof(i));
979
980 i.si_signo = SVR4_SIGCHLD;
981 i.si_errno = 0; /* XXX? */
982
983 if (pid != 0) {
984 i.si_pid = pid;
985 i.si_stime = ru->ru_stime.tv_sec;
986 i.si_utime = ru->ru_utime.tv_sec;
987 }
988
989 if (WIFEXITED(st)) {
990 i.si_status = WEXITSTATUS(st);
991 i.si_code = SVR4_CLD_EXITED;
992 } else if (WIFSTOPPED(st)) {
993 sig = WSTOPSIG(st);
994 if (sig >= 0 && sig < NSIG)
995 i.si_status = native_to_svr4_signo[sig];
996
997 if (i.si_status == SVR4_SIGCONT)
998 i.si_code = SVR4_CLD_CONTINUED;
999 else
1000 i.si_code = SVR4_CLD_STOPPED;
1001 } else {
1002 sig = WTERMSIG(st);
1003 if (sig >= 0 && sig < NSIG)
1004 i.si_status = native_to_svr4_signo[sig];
1005
1006 if (WCOREDUMP(st))
1007 i.si_code = SVR4_CLD_DUMPED;
1008 else
1009 i.si_code = SVR4_CLD_KILLED;
1010 }
1011
1012 DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1013 i.si_pid, i.si_signo, i.si_code, i.si_errno, i.si_status));
1014
1015 return copyout(&i, s, sizeof(i));
1016 }
1017
1018
1019 int
1020 svr4_32_sys_waitsys(struct lwp *l, const struct svr4_32_sys_waitsys_args *uap, register_t *retval)
1021 {
1022 int options, error, status, was_zombie;;
1023 struct rusage ru;
1024 int id = SCARG(uap, id);
1025
1026 switch (SCARG(uap, grp)) {
1027 case SVR4_P_PID:
1028 break;
1029
1030 case SVR4_P_PGID:
1031 id = -l->l_proc->p_pgid;
1032 break;
1033
1034 case SVR4_P_ALL:
1035 id = WAIT_ANY;
1036 break;
1037
1038 default:
1039 return EINVAL;
1040 }
1041
1042 DPRINTF(("waitsys(%d, %d, %p, %x)\n",
1043 SCARG(uap, grp), id,
1044 SCARG(uap, info), SCARG(uap, options)));
1045
1046 /* Translate options */
1047 options = WOPTSCHECKED;
1048 if (SCARG(uap, options) & SVR4_WNOWAIT)
1049 options |= WNOWAIT;
1050 if (SCARG(uap, options) & SVR4_WNOHANG)
1051 options |= WNOHANG;
1052 if ((SCARG(uap, options) & (SVR4_WEXITED|SVR4_WTRAPPED)) == 0)
1053 options |= WNOZOMBIE;
1054 if (SCARG(uap, options) & (SVR4_WSTOPPED|SVR4_WCONTINUED))
1055 options |= WUNTRACED;
1056
1057 error = do_sys_wait(l, &id, &status, options, &ru,
1058 &was_zombie);
1059
1060 retval[0] = id;
1061 if (error != 0)
1062 return error;
1063
1064 return svr4_32_setinfo(id, &ru, status, SCARG(uap, info));
1065 }
1066
1067 static int
1068 svr4_32_copyout_statvfs(const struct statvfs *bfs, struct svr4_32_statvfs *sufs)
1069 {
1070 struct svr4_32_statvfs *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1071 int error;
1072
1073 sfs->f_bsize = bfs->f_iosize; /* XXX */
1074 sfs->f_frsize = bfs->f_bsize;
1075 sfs->f_blocks = bfs->f_blocks;
1076 sfs->f_bfree = bfs->f_bfree;
1077 sfs->f_bavail = bfs->f_bavail;
1078 sfs->f_files = bfs->f_files;
1079 sfs->f_ffree = bfs->f_ffree;
1080 sfs->f_favail = bfs->f_ffree;
1081 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1082 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1083 sfs->f_flag = 0;
1084 if (bfs->f_flag & MNT_RDONLY)
1085 sfs->f_flag |= SVR4_ST_RDONLY;
1086 if (bfs->f_flag & MNT_NOSUID)
1087 sfs->f_flag |= SVR4_ST_NOSUID;
1088 sfs->f_namemax = MAXNAMLEN;
1089 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1090 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1091
1092 error = copyout(sfs, sufs, sizeof(*sfs));
1093
1094 free(sfs, M_TEMP);
1095 return error;
1096 }
1097
1098
1099 static int
1100 svr4_32_copyout_statvfs64(const struct statvfs *bfs, struct svr4_32_statvfs64 *sufs)
1101 {
1102 struct svr4_32_statvfs64 *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1103 int error;
1104
1105 sfs->f_bsize = bfs->f_iosize; /* XXX */
1106 sfs->f_frsize = bfs->f_bsize;
1107 sfs->f_blocks = bfs->f_blocks;
1108 sfs->f_bfree = bfs->f_bfree;
1109 sfs->f_bavail = bfs->f_bavail;
1110 sfs->f_files = bfs->f_files;
1111 sfs->f_ffree = bfs->f_ffree;
1112 sfs->f_favail = bfs->f_ffree;
1113 sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1114 memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1115 sfs->f_flag = 0;
1116 if (bfs->f_flag & MNT_RDONLY)
1117 sfs->f_flag |= SVR4_ST_RDONLY;
1118 if (bfs->f_flag & MNT_NOSUID)
1119 sfs->f_flag |= SVR4_ST_NOSUID;
1120 sfs->f_namemax = MAXNAMLEN;
1121 memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1122 memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1123
1124 error = copyout(sfs, sufs, sizeof(*sfs));
1125
1126 free(sfs, M_TEMP);
1127 return error;
1128 }
1129
1130
1131 int
1132 svr4_32_sys_statvfs(struct lwp *l, const struct svr4_32_sys_statvfs_args *uap, register_t *retval)
1133 {
1134 struct statvfs *sb;
1135 int error;
1136
1137 sb = STATVFSBUF_GET();
1138 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
1139 if (error == 0)
1140 error = svr4_32_copyout_statvfs(sb, SCARG_P32(uap, fs));
1141 STATVFSBUF_PUT(sb);
1142 return error;
1143 }
1144
1145
1146 int
1147 svr4_32_sys_fstatvfs(struct lwp *l, const struct svr4_32_sys_fstatvfs_args *uap, register_t *retval)
1148 {
1149 struct statvfs *sb;
1150 int error;
1151
1152 sb = STATVFSBUF_GET();
1153 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1154 if (error == 0)
1155 error = svr4_32_copyout_statvfs(sb, SCARG_P32(uap, fs));
1156 STATVFSBUF_PUT(sb);
1157 return error;
1158 }
1159
1160
1161 int
1162 svr4_32_sys_statvfs64(struct lwp *l, const struct svr4_32_sys_statvfs64_args *uap, register_t *retval)
1163 {
1164 struct statvfs *sb;
1165 int error;
1166
1167 sb = STATVFSBUF_GET();
1168 error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
1169 if (error == 0)
1170 error = svr4_32_copyout_statvfs64(sb, SCARG_P32(uap, fs));
1171 STATVFSBUF_PUT(sb);
1172 return error;
1173 }
1174
1175
1176 int
1177 svr4_32_sys_fstatvfs64(struct lwp *l, const struct svr4_32_sys_fstatvfs64_args *uap, register_t *retval)
1178 {
1179 struct statvfs *sb;
1180 int error;
1181
1182 sb = STATVFSBUF_GET();
1183 error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1184 if (error == 0)
1185 error = svr4_32_copyout_statvfs64(sb, SCARG_P32(uap, fs));
1186 STATVFSBUF_PUT(sb);
1187 return error;
1188 }
1189
1190
1191
1192 int
1193 svr4_32_sys_alarm(struct lwp *l, const struct svr4_32_sys_alarm_args *uap, register_t *retval)
1194 {
1195 struct itimerval tp;
1196
1197 dogetitimer(l->l_proc, ITIMER_REAL, &tp);
1198 if (tp.it_value.tv_usec)
1199 tp.it_value.tv_sec++;
1200 *retval = (register_t)tp.it_value.tv_sec;
1201
1202 timerclear(&tp.it_interval);
1203 tp.it_value.tv_sec = SCARG(uap, sec);
1204 tp.it_value.tv_usec = 0;
1205
1206 return dosetitimer(l->l_proc, ITIMER_REAL, &tp);
1207 }
1208
1209
1210 int
1211 svr4_32_sys_gettimeofday(struct lwp *l, const struct svr4_32_sys_gettimeofday_args *uap, register_t *retval)
1212 {
1213
1214 if (SCARG_P32(uap, tp)) {
1215 struct timeval atv;
1216
1217 microtime(&atv);
1218 return copyout(&atv, SCARG_P32(uap, tp), sizeof (atv));
1219 }
1220
1221 return 0;
1222 }
1223
1224
1225 int
1226 svr4_32_sys_facl(struct lwp *l, const struct svr4_32_sys_facl_args *uap, register_t *retval)
1227 {
1228
1229 *retval = 0;
1230
1231 switch (SCARG(uap, cmd)) {
1232 case SVR4_SYS_SETACL:
1233 /* We don't support acls on any filesystem */
1234 return ENOSYS;
1235
1236 case SVR4_SYS_GETACL:
1237 return 0;
1238 /*
1239 return copyout(retval, &SCARG(uap, num),
1240 sizeof(SCARG(uap, num)));
1241 */
1242
1243 case SVR4_SYS_GETACLCNT:
1244 return 0;
1245
1246 default:
1247 return EINVAL;
1248 }
1249 }
1250
1251
1252 int
1253 svr4_32_sys_acl(struct lwp *l, const struct svr4_32_sys_acl_args *uap, register_t *retval)
1254 {
1255 return svr4_32_sys_facl(l, (const void *)uap, retval); /* XXX: for now the same */
1256 }
1257
1258
1259 int
1260 svr4_32_sys_auditsys(struct lwp *l, const struct svr4_32_sys_auditsys_args *uap, register_t *retval)
1261 {
1262 /*
1263 * XXX: Big brother is *not* watching.
1264 */
1265 return 0;
1266 }
1267
1268
1269 int
1270 svr4_32_sys_memcntl(struct lwp *l, const struct svr4_32_sys_memcntl_args *uap, register_t *retval)
1271 {
1272 switch (SCARG(uap, cmd)) {
1273 case SVR4_MC_SYNC:
1274 {
1275 struct sys___msync13_args msa;
1276
1277 SCARG(&msa, addr) = SCARG_P32(uap, addr);
1278 SCARG(&msa, len) = SCARG(uap, len);
1279 SCARG(&msa, flags) = (uintptr_t)SCARG_P32(uap, arg);
1280
1281 return sys___msync13(l, &msa, retval);
1282 }
1283 case SVR4_MC_ADVISE:
1284 {
1285 struct sys_madvise_args maa;
1286
1287 SCARG(&maa, addr) = SCARG_P32(uap, addr);
1288 SCARG(&maa, len) = SCARG(uap, len);
1289 SCARG(&maa, behav) = (uintptr_t)SCARG_P32(uap, arg);
1290
1291 return sys_madvise(l, &maa, retval);
1292 }
1293 case SVR4_MC_LOCK:
1294 case SVR4_MC_UNLOCK:
1295 case SVR4_MC_LOCKAS:
1296 case SVR4_MC_UNLOCKAS:
1297 return EOPNOTSUPP;
1298 default:
1299 return ENOSYS;
1300 }
1301 }
1302
1303
1304 int
1305 svr4_32_sys_nice(struct lwp *l, const struct svr4_32_sys_nice_args *uap, register_t *retval)
1306 {
1307 struct sys_setpriority_args ap;
1308 int error;
1309
1310 SCARG(&ap, which) = PRIO_PROCESS;
1311 SCARG(&ap, who) = 0;
1312 SCARG(&ap, prio) = SCARG(uap, prio);
1313
1314 if ((error = sys_setpriority(l, &ap, retval)) != 0)
1315 return error;
1316
1317 if ((error = sys_getpriority(l, (const void *)&ap, retval)) != 0)
1318 return error;
1319
1320 return 0;
1321 }
1322
1323
1324 int
1325 svr4_32_sys_resolvepath(struct lwp *l, const struct svr4_32_sys_resolvepath_args *uap, register_t *retval)
1326 {
1327 struct nameidata nd;
1328 int error;
1329 size_t len;
1330
1331 NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | TRYEMULROOT, UIO_USERSPACE,
1332 SCARG_P32(uap, path));
1333
1334 if ((error = namei(&nd)) != 0)
1335 return error;
1336
1337 if ((error = copyoutstr(nd.ni_cnd.cn_pnbuf,
1338 SCARG_P32(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: 701d15013866f033ba8819d422008ae7
|