1/*	$NetBSD: svr4_32_misc.c,v 1.73 2010/11/30 10:43:02 dholland 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.73 2010/11/30 10:43:02 dholland 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
99static int svr4_to_bsd_mmap_flags(int);
100
101static inline clock_t timeval_to_clock_t(struct timeval *);
102static int svr4_32_setinfo(int, struct rusage *, int, svr4_32_siginfo_tp);
103
104static int svr4_32_mknod(struct lwp *, register_t *, const char *,
105    svr4_32_mode_t, svr4_32_dev_t);
106
107int
108svr4_32_sys_wait(struct lwp *l, const struct svr4_32_sys_wait_args *uap,
109    register_t *retval)
110{
111	int error, st, sig, pid = WAIT_ANY;
112
113	error = do_sys_wait(&pid, &st, 0, NULL);
114
115	retval[0] = pid;
116	if (pid == 0)
117		return error;
118
119	if (WIFSIGNALED(st)) {
120		sig = WTERMSIG(st);
121		if (sig >= 0 && sig < NSIG)
122			st = (st & ~0177) | native_to_svr4_signo[sig];
123	} else if (WIFSTOPPED(st)) {
124		sig = WSTOPSIG(st);
125		if (sig >= 0 && sig < NSIG)
126			st = (st & ~0xff00) | (native_to_svr4_signo[sig] << 8);
127	}
128
129	/*
130	 * It looks like wait(2) on svr4/solaris/2.4 returns
131	 * the status in retval[1], and the pid on retval[0].
132	 */
133	retval[1] = st;
134
135	if (SCARG_P32(uap, status))
136		error = copyout(&st, SCARG_P32(uap, status), sizeof(st));
137	return error;
138}
139
140
141int
142svr4_32_sys_execv(struct lwp *l, const struct svr4_32_sys_execv_args *uap, register_t *retval)
143{
144	/* {
145		syscallarg(char *) path;
146		syscallarg(char **) argv;
147	} */
148	struct netbsd32_execve_args ap;
149
150	SCARG(&ap, path) = SCARG(uap, path);
151	SCARG(&ap, argp) = SCARG(uap, argp);
152	NETBSD32PTR32(SCARG(&ap, envp), 0);
153
154	return netbsd32_execve(l, &ap, retval);
155}
156
157#if 0
158int
159svr4_32_sys_execve(struct proc *p, void *v, register_t *retval)
160{
161	struct svr4_32_sys_execve_args /* {
162		syscallarg(const char *) path;
163		syscallarg(char **) argv;
164		syscallarg(char **) envp;
165	} */ *uap = v;
166	struct sys_execve_args ap;
167
168	SCARG(&ap, path) = SCARG_P32(uap, path);
169	SCARG(&ap, argp) = SCARG_P32(uap, argp);
170	SCARG(&ap, envp) = SCARG_P32(uap, envp);
171
172	return netbsd32_execve(p, &ap, retval);
173}
174#endif
175
176int
177svr4_32_sys_time(struct lwp *l, const struct svr4_32_sys_time_args *uap, register_t *retval)
178{
179	int error = 0;
180	struct timeval tv;
181	struct netbsd32_timeval ntv;
182
183	microtime(&tv);
184	ntv.tv_sec = tv.tv_sec;
185	ntv.tv_usec = tv.tv_usec;
186	if (SCARG_P32(uap, t))
187		error = copyout(&ntv.tv_sec, SCARG_P32(uap, t),
188				sizeof(ntv.tv_sec));
189	*retval = (int) ntv.tv_sec;
190
191	return error;
192}
193
194
195/*
196 * Read SVR4-style directory entries.  We suck them into kernel space so
197 * that they can be massaged before being copied out to user code.  Like
198 * SunOS, we squish out `empty' entries.
199 *
200 * This is quite ugly, but what do you expect from compatibility code?
201 */
202int
203svr4_32_sys_getdents64(struct lwp *l, const struct svr4_32_sys_getdents64_args *uap, register_t *retval)
204{
205	struct dirent *bdp;
206	struct vnode *vp;
207	char *inp, *sbuf;	/* BSD-format */
208	int len, reclen;	/* BSD-format */
209	char *outp;		/* SVR4-format */
210	int resid, svr4_32_reclen;	/* SVR4-format */
211	file_t *fp;
212	struct uio auio;
213	struct iovec aiov;
214	struct svr4_32_dirent64 idb;
215	off_t off;		/* true file offset */
216	int buflen, error, eofflag;
217	off_t *cookiebuf = NULL, *cookie;
218	int ncookies;
219
220	/* fd_getvnode() will use the descriptor for us */
221	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
222		return (error);
223
224	if ((fp->f_flag & FREAD) == 0) {
225		error = EBADF;
226		goto out1;
227	}
228
229	vp = fp->f_data;
230	if (vp->v_type != VDIR) {
231		error = EINVAL;
232		goto out1;
233	}
234
235	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
236	sbuf = malloc(buflen, M_TEMP, M_WAITOK);
237	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
238	off = fp->f_offset;
239again:
240	aiov.iov_base = sbuf;
241	aiov.iov_len = buflen;
242	auio.uio_iov = &aiov;
243	auio.uio_iovcnt = 1;
244	auio.uio_rw = UIO_READ;
245	auio.uio_resid = buflen;
246	auio.uio_offset = off;
247	UIO_SETUP_SYSSPACE(&auio);
248	/*
249         * First we read into the malloc'ed buffer, then
250         * we massage it into user space, one record at a time.
251         */
252	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
253	    &ncookies);
254	if (error)
255		goto out;
256
257	inp = sbuf;
258	outp = SCARG_P32(uap, dp);
259	resid = SCARG(uap, nbytes);
260	if ((len = buflen - auio.uio_resid) == 0)
261		goto eof;
262
263	for (cookie = cookiebuf; len > 0; len -= reclen) {
264		bdp = (struct dirent *)inp;
265		reclen = bdp->d_reclen;
266		if (reclen & 3)
267			panic("svr4_32_getdents64: bad reclen");
268		if (bdp->d_fileno == 0) {
269			inp += reclen;	/* it is a hole; squish it out */
270			if (cookie)
271				off = *cookie++;
272			else
273				off += reclen;
274			continue;
275		}
276		svr4_32_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
277		if (reclen > len || resid < svr4_32_reclen) {
278			/* entry too big for buffer, so just stop */
279			outp++;
280			break;
281		}
282		if (cookie)
283			off = *cookie++; /* each entry points to the next */
284		else
285			off += reclen;
286		/*
287		 * Massage in place to make a SVR4-shaped dirent (otherwise
288		 * we have to worry about touching user memory outside of
289		 * the copyout() call).
290		 */
291		idb.d_ino = (svr4_32_ino64_t)bdp->d_fileno;
292		idb.d_off = (svr4_32_off64_t)off;
293		idb.d_reclen = (u_short)svr4_32_reclen;
294		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
295		if ((error = copyout((void *)&idb, outp, svr4_32_reclen)))
296			goto out;
297		/* advance past this real entry */
298		inp += reclen;
299		/* advance output past SVR4-shaped entry */
300		outp += svr4_32_reclen;
301		resid -= svr4_32_reclen;
302	}
303
304	/* if we squished out the whole block, try again */
305	if (outp == SCARG_P32(uap, dp)) {
306		if (cookiebuf)
307			free(cookiebuf, M_TEMP);
308		cookiebuf = NULL;
309		goto again;
310	}
311	fp->f_offset = off;	/* update the vnode offset */
312
313eof:
314	*retval = SCARG(uap, nbytes) - resid;
315out:
316	VOP_UNLOCK(vp);
317	if (cookiebuf)
318		free(cookiebuf, M_TEMP);
319	free(sbuf, M_TEMP);
320 out1:
321	fd_putfile(SCARG(uap, fd));
322	return error;
323}
324
325
326int
327svr4_32_sys_getdents(struct lwp *l, const struct svr4_32_sys_getdents_args *uap, register_t *retval)
328{
329	struct dirent *bdp;
330	struct vnode *vp;
331	char *inp, *sbuf;	/* BSD-format */
332	int len, reclen;	/* BSD-format */
333	char *outp;		/* SVR4-format */
334	int resid, svr4_reclen;	/* SVR4-format */
335	file_t *fp;
336	struct uio auio;
337	struct iovec aiov;
338	struct svr4_32_dirent idb;
339	off_t off;		/* true file offset */
340	int buflen, error, eofflag;
341	off_t *cookiebuf = NULL, *cookie;
342	int ncookies;
343
344	/* fd_getvnode() will use the descriptor for us */
345	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
346		return (error);
347
348	if ((fp->f_flag & FREAD) == 0) {
349		error = EBADF;
350		goto out1;
351	}
352
353	vp = fp->f_data;
354	if (vp->v_type != VDIR) {
355		error = EINVAL;
356		goto out1;
357	}
358
359	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
360	sbuf = malloc(buflen, M_TEMP, M_WAITOK);
361	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
362	off = fp->f_offset;
363again:
364	aiov.iov_base = sbuf;
365	aiov.iov_len = buflen;
366	auio.uio_iov = &aiov;
367	auio.uio_iovcnt = 1;
368	auio.uio_rw = UIO_READ;
369	auio.uio_resid = buflen;
370	auio.uio_offset = off;
371	UIO_SETUP_SYSSPACE(&auio);
372	/*
373         * First we read into the malloc'ed buffer, then
374         * we massage it into user space, one record at a time.
375         */
376	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
377	    &ncookies);
378	if (error)
379		goto out;
380
381	inp = sbuf;
382	outp = SCARG_P32(uap, buf);
383	resid = SCARG(uap, nbytes);
384	if ((len = buflen - auio.uio_resid) == 0)
385		goto eof;
386
387	for (cookie = cookiebuf; len > 0; len -= reclen) {
388		bdp = (struct dirent *)inp;
389		reclen = bdp->d_reclen;
390		if (reclen & 3)
391			panic("svr4_32_getdents: bad reclen");
392		if (cookie)
393			off = *cookie++; /* each entry points to the next */
394		else
395			off += reclen;
396		if ((off >> 32) != 0) {
397			compat_offseterr(vp, "svr4_32_getdents");
398			error = EINVAL;
399			goto out;
400		}
401		if (bdp->d_fileno == 0) {
402			inp += reclen;	/* it is a hole; squish it out */
403			continue;
404		}
405		svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
406		if (reclen > len || resid < svr4_reclen) {
407			/* entry too big for buffer, so just stop */
408			outp++;
409			break;
410		}
411		/*
412		 * Massage in place to make a SVR4-shaped dirent (otherwise
413		 * we have to worry about touching user memory outside of
414		 * the copyout() call).
415		 */
416		idb.d_ino = (svr4_32_ino_t)bdp->d_fileno;
417		idb.d_off = (svr4_32_off_t)off;
418		idb.d_reclen = (u_short)svr4_reclen;
419		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
420		if ((error = copyout((void *)&idb, outp, svr4_reclen)))
421			goto out;
422		/* advance past this real entry */
423		inp += reclen;
424		/* advance output past SVR4-shaped entry */
425		outp += svr4_reclen;
426		resid -= svr4_reclen;
427	}
428
429	/* if we squished out the whole block, try again */
430	if (outp == SCARG_P32(uap, buf)) {
431		if (cookiebuf)
432			free(cookiebuf, M_TEMP);
433		cookiebuf = NULL;
434		goto again;
435	}
436	fp->f_offset = off;	/* update the vnode offset */
437
438eof:
439	*retval = SCARG(uap, nbytes) - resid;
440out:
441	VOP_UNLOCK(vp);
442	if (cookiebuf)
443		free(cookiebuf, M_TEMP);
444	free(sbuf, M_TEMP);
445 out1:
446	fd_putfile(SCARG(uap, fd));
447	return error;
448}
449
450
451static int
452svr4_to_bsd_mmap_flags(int f)
453{
454	int type = f & SVR4_MAP_TYPE;
455	int nf;
456
457	if (type != MAP_PRIVATE && type != MAP_SHARED)
458		return -1;
459
460	nf = f & SVR4_MAP_COPYFLAGS;
461	if (f & SVR4_MAP_ANON)
462	nf |= MAP_ANON;
463
464	return nf;
465}
466
467
468int
469svr4_32_sys_mmap(struct lwp *l, const struct svr4_32_sys_mmap_args *uap, register_t *retval)
470{
471	struct sys_mmap_args		 mm;
472	int				 error;
473	/*
474         * Verify the arguments.
475         */
476	if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
477		return EINVAL;	/* XXX still needed? */
478
479	if (SCARG(uap, len) == 0)
480		return EINVAL;
481
482	if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
483		return EINVAL;
484
485	SCARG(&mm, prot) = SCARG(uap, prot);
486	SCARG(&mm, len) = SCARG(uap, len);
487	SCARG(&mm, fd) = SCARG(uap, fd);
488	SCARG(&mm, addr) = SCARG_P32(uap, addr);
489	SCARG(&mm, pos) = SCARG(uap, pos);
490
491	error = sys_mmap(l, &mm, retval);
492	if ((u_long)*retval > (u_long)UINT_MAX) {
493		printf("svr4_32_mmap: retval out of range: 0x%lx",
494		       (u_long)*retval);
495		/* Should try to recover and return an error here. */
496	}
497	return (error);
498}
499
500
501int
502svr4_32_sys_mmap64(struct lwp *l, const struct svr4_32_sys_mmap64_args *uap, register_t *retval)
503{
504	struct sys_mmap_args		 mm;
505	int				 error;
506	/*
507         * Verify the arguments.
508         */
509	if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
510		return EINVAL;	/* XXX still needed? */
511
512	if (SCARG(uap, len) == 0)
513		return EINVAL;
514
515	if ((SCARG(&mm, flags) = svr4_to_bsd_mmap_flags(SCARG(uap, flags))) == -1)
516		return EINVAL;
517
518	SCARG(&mm, prot) = SCARG(uap, prot);
519	SCARG(&mm, len) = SCARG(uap, len);
520	SCARG(&mm, fd) = SCARG(uap, fd);
521	SCARG(&mm, addr) = SCARG_P32(uap, addr);
522	SCARG(&mm, pos) = SCARG(uap, pos);
523
524	error = sys_mmap(l, &mm, retval);
525	if ((u_long)*retval > (u_long)UINT_MAX) {
526		printf("svr4_32_mmap64: retval out of range: 0x%lx",
527		       (u_long)*retval);
528		/* Should try to recover and return an error here. */
529	}
530	return (error);
531}
532
533
534static int
535svr4_32_mknod(struct lwp *l, register_t *retval, const char *path, svr4_32_mode_t mode, svr4_32_dev_t dev)
536{
537	if (S_ISFIFO(mode)) {
538		struct sys_mkfifo_args ap;
539		SCARG(&ap, path) = path;
540		SCARG(&ap, mode) = mode;
541		return sys_mkfifo(l, &ap, retval);
542	} else {
543		return do_sys_mknod(l, path, mode, dev, retval, UIO_USERSPACE);
544	}
545}
546
547
548int
549svr4_32_sys_mknod(struct lwp *l, const struct svr4_32_sys_mknod_args *uap, register_t *retval)
550{
551	return svr4_32_mknod(l, retval,
552			  SCARG_P32(uap, path), SCARG(uap, mode),
553			  svr4_32_to_bsd_odev_t(SCARG(uap, dev)));
554}
555
556
557int
558svr4_32_sys_xmknod(struct lwp *l, const struct svr4_32_sys_xmknod_args *uap, register_t *retval)
559{
560	return svr4_32_mknod(l, retval,
561			  SCARG_P32(uap, path), SCARG(uap, mode),
562			  svr4_32_to_bsd_dev_t(SCARG(uap, dev)));
563}
564
565
566int
567svr4_32_sys_vhangup(struct lwp *l, const void *v, register_t *retval)
568{
569	return 0;
570}
571
572
573int
574svr4_32_sys_sysconfig(struct lwp *l, const struct svr4_32_sys_sysconfig_args *uap, register_t *retval)
575{
576	extern u_int	maxfiles;
577	int active;
578
579	switch (SCARG(uap, name)) {
580	case SVR4_CONFIG_NGROUPS:
581		*retval = NGROUPS_MAX;
582		break;
583	case SVR4_CONFIG_CHILD_MAX:
584		*retval = maxproc;
585		break;
586	case SVR4_CONFIG_OPEN_FILES:
587		*retval = maxfiles;
588		break;
589	case SVR4_CONFIG_POSIX_VER:
590		*retval = 198808;
591		break;
592	case SVR4_CONFIG_PAGESIZE:
593		*retval = PAGE_SIZE;
594		break;
595	case SVR4_CONFIG_CLK_TCK:
596		*retval = 60;	/* should this be `hz', ie. 100? */
597		break;
598	case SVR4_CONFIG_XOPEN_VER:
599		*retval = 2;	/* XXX: What should that be? */
600		break;
601	case SVR4_CONFIG_PROF_TCK:
602		*retval = 60;	/* XXX: What should that be? */
603		break;
604	case SVR4_CONFIG_NPROC_CONF:
605		*retval = 1;	/* Only one processor for now */
606		break;
607	case SVR4_CONFIG_NPROC_ONLN:
608		*retval = 1;	/* And it better be online */
609		break;
610	case SVR4_CONFIG_AIO_LISTIO_MAX:
611	case SVR4_CONFIG_AIO_MAX:
612	case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
613		*retval = 0;	/* No aio support */
614		break;
615	case SVR4_CONFIG_DELAYTIMER_MAX:
616		*retval = 0;	/* No delaytimer support */
617		break;
618	case SVR4_CONFIG_MQ_OPEN_MAX:
619#ifdef SYSVMSG
620		*retval = msginfo.msgmni;
621#else
622		*retval = 0;
623#endif
624		break;
625	case SVR4_CONFIG_MQ_PRIO_MAX:
626		*retval = 0;	/* XXX: Don't know */
627		break;
628	case SVR4_CONFIG_RTSIG_MAX:
629		*retval = 0;
630		break;
631	case SVR4_CONFIG_SEM_NSEMS_MAX:
632#ifdef SYSVSEM
633		*retval = seminfo.semmni;
634#else
635		*retval = 0;
636#endif
637		break;
638	case SVR4_CONFIG_SEM_VALUE_MAX:
639#ifdef SYSVSEM
640		*retval = seminfo.semvmx;
641#else
642		*retval = 0;
643#endif
644		break;
645	case SVR4_CONFIG_SIGQUEUE_MAX:
646		*retval = 0;	/* XXX: Don't know */
647		break;
648	case SVR4_CONFIG_SIGRT_MIN:
649	case SVR4_CONFIG_SIGRT_MAX:
650		*retval = 0;	/* No real time signals */
651		break;
652	case SVR4_CONFIG_TIMER_MAX:
653		*retval = 3;	/* XXX: real, virtual, profiling */
654		break;
655	case SVR4_CONFIG_PHYS_PAGES:
656		*retval = uvmexp.free;	/* XXX: free instead of total */
657		break;
658	case SVR4_CONFIG_AVPHYS_PAGES:
659		uvm_estimatepageable(&active, NULL);
660		*retval = active;	/* XXX: active instead of avg */
661		break;
662	case SVR4_CONFIG_COHERENCY:
663		*retval = 0;	/* XXX */
664		break;
665	case SVR4_CONFIG_SPLIT_CACHE:
666		*retval = 0;	/* XXX */
667		break;
668	case SVR4_CONFIG_ICACHESZ:
669		*retval = 256;	/* XXX */
670		break;
671	case SVR4_CONFIG_DCACHESZ:
672		*retval = 256;	/* XXX */
673		break;
674	case SVR4_CONFIG_ICACHELINESZ:
675		*retval = 64;	/* XXX */
676		break;
677	case SVR4_CONFIG_DCACHELINESZ:
678		*retval = 64;	/* XXX */
679		break;
680	case SVR4_CONFIG_ICACHEBLKSZ:
681		*retval = 64;	/* XXX */
682		break;
683	case SVR4_CONFIG_DCACHEBLKSZ:
684		*retval = 64;	/* XXX */
685		break;
686	case SVR4_CONFIG_DCACHETBLKSZ:
687		*retval = 64;	/* XXX */
688		break;
689	case SVR4_CONFIG_ICACHE_ASSOC:
690		*retval = 1;	/* XXX */
691		break;
692	case SVR4_CONFIG_DCACHE_ASSOC:
693		*retval = 1;	/* XXX */
694		break;
695	case SVR4_CONFIG_MAXPID:
696		*retval = PID_MAX;
697		break;
698	case SVR4_CONFIG_STACK_PROT:
699		*retval = PROT_READ|PROT_WRITE|PROT_EXEC;
700		break;
701	default:
702		return EINVAL;
703	}
704	return 0;
705}
706
707
708/* ARGSUSED */
709int
710svr4_32_sys_break(struct lwp *l, const struct svr4_32_sys_break_args *uap, register_t *retval)
711{
712	struct proc *p = l->l_proc;
713	struct vmspace *vm = p->p_vmspace;
714	vaddr_t new, old;
715	int error;
716
717	old = (vaddr_t) vm->vm_daddr;
718	new = round_page((vaddr_t)SCARG_P32(uap, nsize));
719
720	if (new - old > p->p_rlimit[RLIMIT_DATA].rlim_cur && new > old)
721		return ENOMEM;
722
723	old = round_page(old + ctob(vm->vm_dsize));
724	DPRINTF(("break(2): dsize = %x ctob %x\n",
725		 vm->vm_dsize, ctob(vm->vm_dsize)));
726
727	if (new > old) {
728		error = uvm_map(&vm->vm_map, &old, new - old, NULL,
729			UVM_UNKNOWN_OFFSET, 0,
730           		UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
731			UVM_ADV_NORMAL,
732			UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
733			UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
734		if (error) {
735			uprintf("sbrk: grow failed, return = %d\n", error);
736			return error;
737		}
738		vm->vm_dsize += btoc(new - old);
739	} else if (new < old) {
740		uvm_deallocate(&vm->vm_map, new, old - new);
741		vm->vm_dsize -= btoc(old - new);
742	}
743	return 0;
744}
745
746
747static inline clock_t
748timeval_to_clock_t(struct timeval *tv)
749{
750	return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
751}
752
753int
754svr4_32_sys_times(struct lwp *l, const struct svr4_32_sys_times_args *uap, register_t *retval)
755{
756	struct tms		 tms;
757	struct timeval		 t;
758	struct rusage		 ru, *rup;
759	struct proc		 *p = l->l_proc;
760
761	ru = l->l_proc->p_stats->p_ru;
762	mutex_enter(p->p_lock);
763	calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
764	rulwps(p, &ru);
765	mutex_exit(p->p_lock);
766
767	tms.tms_utime = timeval_to_clock_t(&ru.ru_utime);
768	tms.tms_stime = timeval_to_clock_t(&ru.ru_stime);
769
770	rup = &l->l_proc->p_stats->p_cru;
771	tms.tms_cutime = timeval_to_clock_t(&rup->ru_utime);
772	tms.tms_cstime = timeval_to_clock_t(&rup->ru_stime);
773
774	microtime(&t);
775	*retval = timeval_to_clock_t(&t);
776
777	return copyout(&tms, SCARG_P32(uap, tp), sizeof(tms));
778}
779
780
781int
782svr4_32_sys_ulimit(struct lwp *l, const struct svr4_32_sys_ulimit_args *uap, register_t *retval)
783{
784	struct proc *p = l->l_proc;
785	int error;
786	struct rlimit krl;
787	register_t r;
788
789	switch (SCARG(uap, cmd)) {
790	case SVR4_GFILLIM:
791		r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;
792		break;
793
794	case SVR4_SFILLIM:
795		krl.rlim_cur = SCARG(uap, newlimit) * 512;
796		krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max;
797
798		error = dosetrlimit(l, l->l_proc, RLIMIT_FSIZE, &krl);
799		if (error)
800			return error;
801
802		r = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
803		break;
804
805	case SVR4_GMEMLIM:
806		r = p->p_rlimit[RLIMIT_DATA].rlim_cur;
807		if (r > 0x7fffffff)
808			r = 0x7fffffff;
809		r += (long)p->p_vmspace->vm_daddr;
810		break;
811
812	case SVR4_GDESLIM:
813		r = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
814		break;
815
816	default:
817		return EINVAL;
818	}
819
820	*retval = r > 0x7fffffff ? 0x7fffffff : r;
821	return 0;
822}
823
824
825int
826svr4_32_sys_pgrpsys(struct lwp *l, const struct svr4_32_sys_pgrpsys_args *uap, register_t *retval)
827{
828	struct proc *p = l->l_proc;
829	pid_t pid;
830
831	switch (SCARG(uap, cmd)) {
832	case 1:			/* setpgrp() */
833		/*
834		 * SVR4 setpgrp() (which takes no arguments) has the
835		 * semantics that the session ID is also created anew, so
836		 * in almost every sense, setpgrp() is identical to
837		 * setsid() for SVR4.  (Under BSD, the difference is that
838		 * a setpgid(0,0) will not create a new session.)
839		 */
840		sys_setsid(l, NULL, retval);
841		/*FALLTHROUGH*/
842
843	case 0:			/* getpgrp() */
844		*retval = p->p_pgrp->pg_id;
845		return 0;
846
847	case 2:			/* getsid(pid) */
848		mutex_enter(proc_lock);
849		pid = SCARG(uap, pid);
850		if (pid && (p = proc_find(pid)) == NULL) {
851			mutex_exit(proc_lock);
852			return ESRCH;
853		}
854		mutex_exit(proc_lock);
855		/*
856		 * This has already been initialized to the pid of
857		 * the session leader.
858		 */
859		*retval = (register_t) p->p_session->s_sid;
860		return 0;
861
862	case 3:			/* setsid() */
863		return sys_setsid(l, NULL, retval);
864
865	case 4:			/* getpgid(pid) */
866		mutex_enter(proc_lock);
867		pid = SCARG(uap, pid);
868		if (pid && (p = proc_find(pid)) == NULL) {
869			mutex_exit(proc_lock);
870			return ESRCH;
871		}
872		*retval = (int) p->p_pgrp->pg_id;
873		mutex_exit(proc_lock);
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
890struct 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
899static int
900svr4_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
943int
944svr4_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
971static int
972svr4_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
1019int
1020svr4_32_sys_waitsys(struct lwp *l, const struct svr4_32_sys_waitsys_args *uap, register_t *retval)
1021{
1022	int options, error, status;
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(&id, &status, options, &ru);
1058
1059	retval[0] = id;
1060	if (error != 0)
1061		return error;
1062
1063	return svr4_32_setinfo(id, &ru, status, SCARG(uap, info));
1064}
1065
1066static int
1067svr4_32_copyout_statvfs(const struct statvfs *bfs, struct svr4_32_statvfs *sufs)
1068{
1069	struct svr4_32_statvfs *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1070	int error;
1071
1072	sfs->f_bsize = bfs->f_iosize; /* XXX */
1073	sfs->f_frsize = bfs->f_bsize;
1074	sfs->f_blocks = bfs->f_blocks;
1075	sfs->f_bfree = bfs->f_bfree;
1076	sfs->f_bavail = bfs->f_bavail;
1077	sfs->f_files = bfs->f_files;
1078	sfs->f_ffree = bfs->f_ffree;
1079	sfs->f_favail = bfs->f_ffree;
1080	sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1081	memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1082	sfs->f_flag = 0;
1083	if (bfs->f_flag & MNT_RDONLY)
1084		sfs->f_flag |= SVR4_ST_RDONLY;
1085	if (bfs->f_flag & MNT_NOSUID)
1086		sfs->f_flag |= SVR4_ST_NOSUID;
1087	sfs->f_namemax = bfs->f_namemax;
1088	memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1089	memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1090
1091	error = copyout(sfs, sufs, sizeof(*sfs));
1092
1093	free(sfs, M_TEMP);
1094	return error;
1095}
1096
1097
1098static int
1099svr4_32_copyout_statvfs64(const struct statvfs *bfs, struct svr4_32_statvfs64 *sufs)
1100{
1101	struct svr4_32_statvfs64 *sfs = malloc(sizeof(*sfs), M_TEMP, M_WAITOK);
1102	int error;
1103
1104	sfs->f_bsize = bfs->f_iosize; /* XXX */
1105	sfs->f_frsize = bfs->f_bsize;
1106	sfs->f_blocks = bfs->f_blocks;
1107	sfs->f_bfree = bfs->f_bfree;
1108	sfs->f_bavail = bfs->f_bavail;
1109	sfs->f_files = bfs->f_files;
1110	sfs->f_ffree = bfs->f_ffree;
1111	sfs->f_favail = bfs->f_ffree;
1112	sfs->f_fsid = bfs->f_fsidx.__fsid_val[0];
1113	memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1114	sfs->f_flag = 0;
1115	if (bfs->f_flag & MNT_RDONLY)
1116		sfs->f_flag |= SVR4_ST_RDONLY;
1117	if (bfs->f_flag & MNT_NOSUID)
1118		sfs->f_flag |= SVR4_ST_NOSUID;
1119	sfs->f_namemax = bfs->f_namemax;
1120	memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1121	memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1122
1123	error = copyout(sfs, sufs, sizeof(*sfs));
1124
1125	free(sfs, M_TEMP);
1126	return error;
1127}
1128
1129
1130int
1131svr4_32_sys_statvfs(struct lwp *l, const struct svr4_32_sys_statvfs_args *uap, register_t *retval)
1132{
1133	struct statvfs *sb;
1134	int error;
1135
1136	sb =  STATVFSBUF_GET();
1137	error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
1138	if (error == 0)
1139		error = svr4_32_copyout_statvfs(sb, SCARG_P32(uap, fs));
1140	STATVFSBUF_PUT(sb);
1141	return error;
1142}
1143
1144
1145int
1146svr4_32_sys_fstatvfs(struct lwp *l, const struct svr4_32_sys_fstatvfs_args *uap, register_t *retval)
1147{
1148	struct statvfs *sb;
1149	int error;
1150
1151	sb =  STATVFSBUF_GET();
1152	error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1153	if (error == 0)
1154		error = svr4_32_copyout_statvfs(sb, SCARG_P32(uap, fs));
1155	STATVFSBUF_PUT(sb);
1156	return error;
1157}
1158
1159
1160int
1161svr4_32_sys_statvfs64(struct lwp *l, const struct svr4_32_sys_statvfs64_args *uap, register_t *retval)
1162{
1163	struct statvfs *sb;
1164	int error;
1165
1166	sb =  STATVFSBUF_GET();
1167	error = do_sys_pstatvfs(l, SCARG_P32(uap, path), ST_WAIT, sb);
1168	if (error == 0)
1169		error = svr4_32_copyout_statvfs64(sb, SCARG_P32(uap, fs));
1170	STATVFSBUF_PUT(sb);
1171	return error;
1172}
1173
1174
1175int
1176svr4_32_sys_fstatvfs64(struct lwp *l, const struct svr4_32_sys_fstatvfs64_args *uap, register_t *retval)
1177{
1178	struct statvfs *sb;
1179	int error;
1180
1181	sb =  STATVFSBUF_GET();
1182	error = do_sys_fstatvfs(l, SCARG(uap, fd), ST_WAIT, sb);
1183	if (error == 0)
1184		error = svr4_32_copyout_statvfs64(sb, SCARG_P32(uap, fs));
1185	STATVFSBUF_PUT(sb);
1186	return error;
1187}
1188
1189
1190
1191int
1192svr4_32_sys_alarm(struct lwp *l, const struct svr4_32_sys_alarm_args *uap, register_t *retval)
1193{
1194        struct itimerval tp;
1195
1196	dogetitimer(l->l_proc, ITIMER_REAL, &tp);
1197        if (tp.it_value.tv_usec)
1198                tp.it_value.tv_sec++;
1199        *retval = (register_t)tp.it_value.tv_sec;
1200
1201        timerclear(&tp.it_interval);
1202        tp.it_value.tv_sec = SCARG(uap, sec);
1203        tp.it_value.tv_usec = 0;
1204
1205        return dosetitimer(l->l_proc, ITIMER_REAL, &tp);
1206}
1207
1208
1209int
1210svr4_32_sys_gettimeofday(struct lwp *l, const struct svr4_32_sys_gettimeofday_args *uap, register_t *retval)
1211{
1212
1213	if (SCARG_P32(uap, tp)) {
1214		struct timeval atv;
1215
1216		microtime(&atv);
1217		return copyout(&atv, SCARG_P32(uap, tp), sizeof (atv));
1218	}
1219
1220	return 0;
1221}
1222
1223
1224int
1225svr4_32_sys_facl(struct lwp *l, const struct svr4_32_sys_facl_args *uap, register_t *retval)
1226{
1227
1228	*retval = 0;
1229
1230	switch (SCARG(uap, cmd)) {
1231	case SVR4_SYS_SETACL:
1232		/* We don't support acls on any filesystem */
1233		return ENOSYS;
1234
1235	case SVR4_SYS_GETACL:
1236		return 0;
1237/*
1238		return copyout(retval, &SCARG(uap, num),
1239		    sizeof(SCARG(uap, num)));
1240*/
1241
1242	case SVR4_SYS_GETACLCNT:
1243		return 0;
1244
1245	default:
1246		return EINVAL;
1247	}
1248}
1249
1250
1251int
1252svr4_32_sys_acl(struct lwp *l, const struct svr4_32_sys_acl_args *uap, register_t *retval)
1253{
1254	return svr4_32_sys_facl(l, (const void *)uap, retval);	/* XXX: for now the same */
1255}
1256
1257
1258int
1259svr4_32_sys_auditsys(struct lwp *l, const struct svr4_32_sys_auditsys_args *uap, register_t *retval)
1260{
1261	/*
1262	 * XXX: Big brother is *not* watching.
1263	 */
1264	return 0;
1265}
1266
1267
1268int
1269svr4_32_sys_memcntl(struct lwp *l, const struct svr4_32_sys_memcntl_args *uap, register_t *retval)
1270{
1271	switch (SCARG(uap, cmd)) {
1272	case SVR4_MC_SYNC:
1273		{
1274			struct sys___msync13_args msa;
1275
1276			SCARG(&msa, addr) = SCARG_P32(uap, addr);
1277			SCARG(&msa, len) = SCARG(uap, len);
1278			SCARG(&msa, flags) = (uintptr_t)SCARG_P32(uap, arg);
1279
1280			return sys___msync13(l, &msa, retval);
1281		}
1282	case SVR4_MC_ADVISE:
1283		{
1284			struct sys_madvise_args maa;
1285
1286			SCARG(&maa, addr) = SCARG_P32(uap, addr);
1287			SCARG(&maa, len) = SCARG(uap, len);
1288			SCARG(&maa, behav) = (uintptr_t)SCARG_P32(uap, arg);
1289
1290			return sys_madvise(l, &maa, retval);
1291		}
1292	case SVR4_MC_LOCK:
1293	case SVR4_MC_UNLOCK:
1294	case SVR4_MC_LOCKAS:
1295	case SVR4_MC_UNLOCKAS:
1296		return EOPNOTSUPP;
1297	default:
1298		return ENOSYS;
1299	}
1300}
1301
1302
1303int
1304svr4_32_sys_nice(struct lwp *l, const struct svr4_32_sys_nice_args *uap, register_t *retval)
1305{
1306	struct sys_setpriority_args ap;
1307	int error;
1308
1309	SCARG(&ap, which) = PRIO_PROCESS;
1310	SCARG(&ap, who) = 0;
1311	SCARG(&ap, prio) = SCARG(uap, prio);
1312
1313	if ((error = sys_setpriority(l, &ap, retval)) != 0)
1314		return error;
1315
1316	if ((error = sys_getpriority(l, (const void *)&ap, retval)) != 0)
1317		return error;
1318
1319	return 0;
1320}
1321
1322
1323int
1324svr4_32_sys_resolvepath(struct lwp *l, const struct svr4_32_sys_resolvepath_args *uap, register_t *retval)
1325{
1326	struct pathbuf *pb;
1327	struct nameidata nd;
1328	int error;
1329	size_t len;
1330
1331	error = pathbuf_copyin(SCARG_P32(uap, path), &pb);
1332	if (error) {
1333		return error;
1334	}
1335
1336	NDINIT(&nd, LOOKUP, NOFOLLOW | TRYEMULROOT, pb);
1337	if ((error = namei(&nd)) != 0) {
1338		pathbuf_destroy(pb);
1339		return error;
1340	}
1341
1342	if ((error = copyoutstr(nd.ni_pnbuf,
1343	    SCARG_P32(uap, buf),
1344	    SCARG(uap, bufsiz), &len)) != 0)
1345		goto bad;
1346
1347	*retval = len;
1348bad:
1349	vrele(nd.ni_vp);
1350	pathbuf_destroy(pb);
1351	return error;
1352}
1353