xref: /NextBSD/sys/compat/svr4/svr4_stat.c (revision 4bf303e5af1834cdd3092175eeca7676420229c4)
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 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/proc.h>
35 #include <sys/stat.h>
36 #include <sys/filedesc.h>
37 #include <sys/fcntl.h>
38 #include <sys/jail.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/namei.h>
42 #include <sys/unistd.h>
43 #include <sys/time.h>
44 #include <sys/syscallsubr.h>
45 #include <sys/sysctl.h>
46 #include <sys/sysproto.h>
47 #include <sys/un.h>
48 
49 #include <vm/vm.h>
50 
51 #include <netinet/in.h>
52 
53 #include <compat/svr4/svr4.h>
54 #include <compat/svr4/svr4_types.h>
55 #include <compat/svr4/svr4_signal.h>
56 #include <compat/svr4/svr4_proto.h>
57 #include <compat/svr4/svr4_util.h>
58 #include <compat/svr4/svr4_stat.h>
59 #include <compat/svr4/svr4_ustat.h>
60 #include <compat/svr4/svr4_utsname.h>
61 #include <compat/svr4/svr4_systeminfo.h>
62 #include <compat/svr4/svr4_socket.h>
63 #include <compat/svr4/svr4_time.h>
64 #if defined(NOTYET)
65 #include "svr4_fuser.h"
66 #endif
67 
68 #ifdef sparc
69 /*
70  * Solaris-2.4 on the sparc has the old stat call using the new
71  * stat data structure...
72  */
73 # define SVR4_NO_OSTAT
74 #endif
75 
76 struct svr4_ustat_args {
77 	svr4_dev_t		dev;
78 	struct svr4_ustat * name;
79 };
80 
81 static void bsd_to_svr4_xstat(struct stat *, struct svr4_xstat *);
82 static void bsd_to_svr4_stat64(struct stat *, struct svr4_stat64 *);
83 int svr4_ustat(struct thread *, struct svr4_ustat_args *);
84 static int svr4_to_bsd_pathconf(int);
85 
86 /*
87  * SVR4 uses named pipes as named sockets, so we tell programs
88  * that sockets are named pipes with mode 0
89  */
90 #define BSD_TO_SVR4_MODE(mode) (S_ISSOCK(mode) ? S_IFIFO : (mode))
91 
92 
93 #ifndef SVR4_NO_OSTAT
94 static void bsd_to_svr4_stat(struct stat *, struct svr4_stat *);
95 
96 static void
bsd_to_svr4_stat(st,st4)97 bsd_to_svr4_stat(st, st4)
98 	struct stat		*st;
99 	struct svr4_stat 	*st4;
100 {
101 	memset(st4, 0, sizeof(*st4));
102 	st4->st_dev = bsd_to_svr4_odev_t(st->st_dev);
103 	st4->st_ino = st->st_ino;
104 	st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
105 	st4->st_nlink = st->st_nlink;
106 	st4->st_uid = st->st_uid;
107 	st4->st_gid = st->st_gid;
108 	st4->st_rdev = bsd_to_svr4_odev_t(st->st_rdev);
109 	st4->st_size = st->st_size;
110 	st4->st_atim = st->st_atim.tv_sec;
111 	st4->st_mtim = st->st_mtim.tv_sec;
112 	st4->st_ctim = st->st_ctim.tv_sec;
113 }
114 #endif
115 
116 
117 static void
bsd_to_svr4_xstat(st,st4)118 bsd_to_svr4_xstat(st, st4)
119 	struct stat		*st;
120 	struct svr4_xstat	*st4;
121 {
122 	memset(st4, 0, sizeof(*st4));
123 	st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
124 	st4->st_ino = st->st_ino;
125 	st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
126 	st4->st_nlink = st->st_nlink;
127 	st4->st_uid = st->st_uid;
128 	st4->st_gid = st->st_gid;
129 	st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
130 	st4->st_size = st->st_size;
131 	st4->st_atim = st->st_atim;
132 	st4->st_mtim = st->st_mtim;
133 	st4->st_ctim = st->st_ctim;
134 	st4->st_blksize = st->st_blksize;
135 	st4->st_blocks = st->st_blocks;
136 	strcpy(st4->st_fstype, "unknown");
137 }
138 
139 
140 static void
bsd_to_svr4_stat64(st,st4)141 bsd_to_svr4_stat64(st, st4)
142 	struct stat		*st;
143 	struct svr4_stat64	*st4;
144 {
145 	memset(st4, 0, sizeof(*st4));
146 	st4->st_dev = bsd_to_svr4_dev_t(st->st_dev);
147 	st4->st_ino = st->st_ino;
148 	st4->st_mode = BSD_TO_SVR4_MODE(st->st_mode);
149 	st4->st_nlink = st->st_nlink;
150 	st4->st_uid = st->st_uid;
151 	st4->st_gid = st->st_gid;
152 	st4->st_rdev = bsd_to_svr4_dev_t(st->st_rdev);
153 	st4->st_size = st->st_size;
154 	st4->st_atim = st->st_atim;
155 	st4->st_mtim = st->st_mtim;
156 	st4->st_ctim = st->st_ctim;
157 	st4->st_blksize = st->st_blksize;
158 	st4->st_blocks = st->st_blocks;
159 	strcpy(st4->st_fstype, "unknown");
160 }
161 
162 int
svr4_sys_stat(td,uap)163 svr4_sys_stat(td, uap)
164 	struct thread *td;
165 	struct svr4_sys_stat_args *uap;
166 {
167 	struct svr4_stat svr4_st;
168 	struct stat st;
169 	char *path;
170 	int error;
171 
172 	CHECKALTEXIST(td, uap->path, &path);
173 
174 	error = kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, NULL);
175 	free(path, M_TEMP);
176 	if (error)
177 		return (error);
178 	bsd_to_svr4_stat(&st, &svr4_st);
179 
180 	if (S_ISSOCK(st.st_mode))
181 		(void) svr4_add_socket(td, uap->path, &st);
182 
183 	return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
184 }
185 
186 
187 int
svr4_sys_lstat(td,uap)188 svr4_sys_lstat(td, uap)
189 	struct thread *td;
190 	struct svr4_sys_lstat_args *uap;
191 {
192 	struct svr4_stat svr4_st;
193 	struct stat st;
194 	char *path;
195 	int error;
196 
197 	CHECKALTEXIST(td, uap->path, &path);
198 
199 	error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
200 	    UIO_SYSSPACE, &st, NULL);
201 	free(path, M_TEMP);
202 	if (error)
203 		return (error);
204 	bsd_to_svr4_stat(&st, &svr4_st);
205 
206 	if (S_ISSOCK(st.st_mode))
207 		(void) svr4_add_socket(td, uap->path, &st);
208 
209 	return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
210 }
211 
212 
213 int
svr4_sys_fstat(td,uap)214 svr4_sys_fstat(td, uap)
215 	struct thread *td;
216 	struct svr4_sys_fstat_args *uap;
217 {
218 	struct svr4_stat svr4_st;
219 	struct stat st;
220 	int error;
221 
222 
223 	error = kern_fstat(td, uap->fd, &st);
224 	if (error)
225 		return (error);
226 	bsd_to_svr4_stat(&st, &svr4_st);
227 	return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
228 }
229 
230 
231 int
svr4_sys_xstat(td,uap)232 svr4_sys_xstat(td, uap)
233 	struct thread *td;
234 	struct svr4_sys_xstat_args *uap;
235 {
236 	struct svr4_xstat svr4_st;
237 	struct stat st;
238 	char *path;
239 	int error;
240 
241 	CHECKALTEXIST(td, uap->path, &path);
242 
243 	error = kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, NULL);
244 	free(path, M_TEMP);
245 	if (error)
246 		return (error);
247 
248 	bsd_to_svr4_xstat(&st, &svr4_st);
249 
250 #if defined(SOCKET_NOTYET)
251 	if (S_ISSOCK(st.st_mode))
252 		(void) svr4_add_socket(td, uap->path, &st);
253 #endif
254 
255 	return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
256 }
257 
258 int
svr4_sys_lxstat(td,uap)259 svr4_sys_lxstat(td, uap)
260 	struct thread *td;
261 	struct svr4_sys_lxstat_args *uap;
262 {
263 	struct svr4_xstat svr4_st;
264 	struct stat st;
265 	char *path;
266 	int error;
267 
268 	CHECKALTEXIST(td, uap->path, &path);
269 
270 	error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
271 	    UIO_SYSSPACE, &st, NULL);
272 	free(path, M_TEMP);
273 	if (error)
274 		return (error);
275 
276 	bsd_to_svr4_xstat(&st, &svr4_st);
277 
278 #if defined(SOCKET_NOTYET)
279 	if (S_ISSOCK(st.st_mode))
280 		(void) svr4_add_socket(td, uap->path, &st);
281 #endif
282 	return (copyout(&svr4_st, uap->ub, sizeof svr4_st));
283 }
284 
285 
286 int
svr4_sys_fxstat(td,uap)287 svr4_sys_fxstat(td, uap)
288 	struct thread *td;
289 	struct svr4_sys_fxstat_args *uap;
290 {
291 	struct svr4_xstat svr4_st;
292 	struct stat st;
293 	int error;
294 
295 
296 	error = kern_fstat(td, uap->fd, &st);
297 	if (error)
298 		return (error);
299 	bsd_to_svr4_xstat(&st, &svr4_st);
300 	return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
301 }
302 
303 int
svr4_sys_stat64(td,uap)304 svr4_sys_stat64(td, uap)
305 	struct thread *td;
306 	struct svr4_sys_stat64_args *uap;
307 {
308 	struct svr4_stat64 svr4_st;
309 	struct stat st;
310 	char *path;
311 	int error;
312 
313 	CHECKALTEXIST(td, uap->path, &path);
314 
315 	error = kern_statat(td, 0, AT_FDCWD, path, UIO_SYSSPACE, &st, NULL);
316 	free(path, M_TEMP);
317 	if (error)
318 		return (error);
319 
320 	bsd_to_svr4_stat64(&st, &svr4_st);
321 
322 	if (S_ISSOCK(st.st_mode))
323 		(void) svr4_add_socket(td, uap->path, &st);
324 
325 	return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
326 }
327 
328 
329 int
svr4_sys_lstat64(td,uap)330 svr4_sys_lstat64(td, uap)
331 	struct thread *td;
332 	struct svr4_sys_lstat64_args *uap;
333 {
334 	struct svr4_stat64 svr4_st;
335 	struct stat st;
336 	char *path;
337 	int error;
338 
339 	CHECKALTEXIST(td, uap->path, &path);
340 
341 	error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, path,
342 	    UIO_SYSSPACE, &st, NULL);
343 	free(path, M_TEMP);
344 	if (error)
345 		return (error);
346 
347 	bsd_to_svr4_stat64(&st, &svr4_st);
348 
349 	if (S_ISSOCK(st.st_mode))
350 		(void) svr4_add_socket(td, uap->path, &st);
351 
352 	return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
353 }
354 
355 
356 int
svr4_sys_fstat64(td,uap)357 svr4_sys_fstat64(td, uap)
358 	struct thread *td;
359 	struct svr4_sys_fstat64_args *uap;
360 {
361 	struct svr4_stat64 svr4_st;
362 	struct stat st;
363 	int error;
364 
365 	error = kern_fstat(td, uap->fd, &st);
366 	if (error)
367 		return (error);
368 	bsd_to_svr4_stat64(&st, &svr4_st);
369 	return (copyout(&svr4_st, uap->sb, sizeof svr4_st));
370 }
371 
372 
373 int
svr4_ustat(td,uap)374 svr4_ustat(td, uap)
375 	struct thread *td;
376 	struct svr4_ustat_args *uap;
377 {
378 	struct svr4_ustat	us;
379 	int			error;
380 
381 	memset(&us, 0, sizeof us);
382 
383 	/*
384          * XXX: should set f_tfree and f_tinode at least
385          * How do we translate dev -> fstat? (and then to svr4_ustat)
386          */
387 	if ((error = copyout(&us, uap->name, sizeof us)) != 0)
388 		return (error);
389 
390 	return 0;
391 }
392 
393 /*extern char ostype[], osrelease[], version[], machine[];*/
394 
395 int
svr4_sys_uname(td,uap)396 svr4_sys_uname(td, uap)
397 	struct thread *td;
398 	struct svr4_sys_uname_args *uap;
399 {
400 	struct svr4_utsname	sut;
401 
402 	memset(&sut, 0, sizeof(sut));
403 
404 	strlcpy(sut.sysname, ostype, sizeof(sut.sysname));
405 	getcredhostname(td->td_ucred, sut.nodename, sizeof(sut.nodename));
406 	strlcpy(sut.release, osrelease, sizeof(sut.release));
407 	strlcpy(sut.version, version, sizeof(sut.version));
408 	strlcpy(sut.machine, machine, sizeof(sut.machine));
409 
410 	return copyout((caddr_t) &sut, (caddr_t) uap->name,
411 		       sizeof(struct svr4_utsname));
412 }
413 
414 int
svr4_sys_systeminfo(td,uap)415 svr4_sys_systeminfo(td, uap)
416 	struct thread *td;
417 	struct svr4_sys_systeminfo_args *uap;
418 {
419 	char		*str = NULL;
420 	int		error = 0;
421 	register_t	*retval = td->td_retval;
422 	u_long		hostid;
423 	size_t		len = 0;
424 	char		buf[MAXHOSTNAMELEN];
425 	u_int		rlen = uap->len;
426 
427 	switch (uap->what) {
428 	case SVR4_SI_SYSNAME:
429 		str = ostype;
430 		break;
431 
432 	case SVR4_SI_HOSTNAME:
433 		getcredhostname(td->td_ucred, buf, sizeof(buf));
434 		str = buf;
435 		break;
436 
437 	case SVR4_SI_RELEASE:
438 		str = osrelease;
439 		break;
440 
441 	case SVR4_SI_VERSION:
442 		str = version;
443 		break;
444 
445 	case SVR4_SI_MACHINE:
446 		str = machine;
447 		break;
448 
449 	case SVR4_SI_ARCHITECTURE:
450 		str = machine;
451 		break;
452 
453 	case SVR4_SI_ISALIST:
454 #if defined(__sparc__)
455 		str = "sparcv9 sparcv9-fsmuld sparcv8 sparcv8-fsmuld sparcv7 sparc";
456 #elif defined(__i386__)
457 		str = "i386";
458 #elif defined(__amd64__)
459 		str = "amd64";
460 #else
461 		str = "unknown";
462 #endif
463 		break;
464 
465 	case SVR4_SI_HW_SERIAL:
466 		getcredhostid(td->td_ucred, &hostid);
467 		snprintf(buf, sizeof(buf), "%lu", hostid);
468 		str = buf;
469 		break;
470 
471 	case SVR4_SI_HW_PROVIDER:
472 		str = ostype;
473 		break;
474 
475 	case SVR4_SI_SRPC_DOMAIN:
476 		getcreddomainname(td->td_ucred, buf, sizeof(buf));
477 		str = buf;
478 		break;
479 
480 	case SVR4_SI_PLATFORM:
481 #if defined(__i386__)
482 		str = "i86pc";
483 #else
484 		str = "unknown";
485 #endif
486 		break;
487 
488 	case SVR4_SI_KERB_REALM:
489 		str = "unsupported";
490 		break;
491 #if defined(WHY_DOES_AN_EMULATOR_WANT_TO_SET_HOSTNAMES)
492 	case SVR4_SI_SET_HOSTNAME:
493 		name = KERN_HOSTNAME;
494 		return kern_sysctl(&name, 1, 0, 0, uap->buf, rlen, td);
495 
496 	case SVR4_SI_SET_SRPC_DOMAIN:
497 		name = KERN_NISDOMAINNAME;
498 		return kern_sysctl(&name, 1, 0, 0, uap->buf, rlen, td);
499 #else
500 	case SVR4_SI_SET_HOSTNAME:
501         case SVR4_SI_SET_SRPC_DOMAIN:
502 		/* FALLTHROUGH */
503 #endif
504 	case SVR4_SI_SET_KERB_REALM:
505 		return 0;
506 
507 	default:
508 		DPRINTF(("Bad systeminfo command %d\n", uap->what));
509 		return ENOSYS;
510 	}
511 
512 	if (str) {
513 		len = strlen(str) + 1;
514 		if (len > rlen)
515 			len = rlen;
516 
517 		if (uap->buf) {
518 			error = copyout(str, uap->buf, len);
519 			if (error)
520 				return error;
521 			/* make sure we are NULL terminated */
522 			buf[0] = '\0';
523 			error = copyout(buf, &(uap->buf[len - 1]), 1);
524 		}
525 		else
526 			error = 0;
527 	}
528 	/* XXX NetBSD has hostname setting stuff here.  Why would an emulator
529 	   want to do that? */
530 
531 	*retval = len;
532 	return error;
533 }
534 
535 int
svr4_sys_utssys(td,uap)536 svr4_sys_utssys(td, uap)
537 	struct thread *td;
538 	struct svr4_sys_utssys_args *uap;
539 {
540 	switch (uap->sel) {
541 	case 0:		/* uname(2)  */
542 		{
543 			struct svr4_sys_uname_args ua;
544 			ua.name = uap->a1;
545 			return svr4_sys_uname(td, &ua);
546 		}
547 
548 	case 2:		/* ustat(2)  */
549 		{
550 			struct svr4_ustat_args ua;
551 			ua.dev = (svr4_dev_t) uap->a2;
552 			ua.name = uap->a1;
553 			return svr4_ustat(td, &ua);
554 		}
555 
556 	case 3:		/* fusers(2) */
557 		return ENOSYS;
558 
559 	default:
560 		return ENOSYS;
561 	}
562 	return ENOSYS;
563 }
564 
565 
566 int
svr4_sys_utime(td,uap)567 svr4_sys_utime(td, uap)
568 	struct thread *td;
569 	struct svr4_sys_utime_args *uap;
570 {
571 	struct svr4_utimbuf ub;
572 	struct timeval tbuf[2], *tp;
573 	char *path;
574 	int error;
575 
576 	if (uap->ubuf != NULL) {
577 		error = copyin(uap->ubuf, &ub, sizeof(ub));
578 		if (error)
579 			return (error);
580 		tbuf[0].tv_sec = ub.actime;
581 		tbuf[0].tv_usec = 0;
582 		tbuf[1].tv_sec = ub.modtime;
583 		tbuf[1].tv_usec = 0;
584 		tp = tbuf;
585 	} else
586 		tp = NULL;
587 
588 	CHECKALTEXIST(td, uap->path, &path);
589 	error = kern_utimesat(td, AT_FDCWD, path, UIO_SYSSPACE,
590 	    tp, UIO_SYSSPACE);
591 	free(path, M_TEMP);
592 	return (error);
593 }
594 
595 
596 int
svr4_sys_utimes(td,uap)597 svr4_sys_utimes(td, uap)
598 	struct thread *td;
599 	struct svr4_sys_utimes_args *uap;
600 {
601 	char *path;
602 	int error;
603 
604 	CHECKALTEXIST(td, uap->path, &path);
605 	error = kern_utimesat(td, AT_FDCWD, path, UIO_SYSSPACE,
606 	    uap->tptr, UIO_USERSPACE);
607 	free(path, M_TEMP);
608 	return (error);
609 }
610 
611 static int
svr4_to_bsd_pathconf(name)612 svr4_to_bsd_pathconf(name)
613 	int name;
614 {
615 	switch (name) {
616 	case SVR4_PC_LINK_MAX:
617 	    	return _PC_LINK_MAX;
618 
619 	case SVR4_PC_MAX_CANON:
620 		return _PC_MAX_CANON;
621 
622 	case SVR4_PC_MAX_INPUT:
623 		return _PC_MAX_INPUT;
624 
625 	case SVR4_PC_NAME_MAX:
626 		return _PC_NAME_MAX;
627 
628 	case SVR4_PC_PATH_MAX:
629 		return _PC_PATH_MAX;
630 
631 	case SVR4_PC_PIPE_BUF:
632 		return _PC_PIPE_BUF;
633 
634 	case SVR4_PC_NO_TRUNC:
635 		return _PC_NO_TRUNC;
636 
637 	case SVR4_PC_VDISABLE:
638 		return _PC_VDISABLE;
639 
640 	case SVR4_PC_CHOWN_RESTRICTED:
641 		return _PC_CHOWN_RESTRICTED;
642 	case SVR4_PC_SYNC_IO:
643 #if defined(_PC_SYNC_IO)
644 		return _PC_SYNC_IO;
645 #else
646 		return 0;
647 #endif
648 	case SVR4_PC_ASYNC_IO:
649 	case SVR4_PC_PRIO_IO:
650 		/* Not supported */
651 		return 0;
652 
653 	default:
654 		/* Invalid */
655 		return -1;
656 	}
657 }
658 
659 
660 int
svr4_sys_pathconf(td,uap)661 svr4_sys_pathconf(td, uap)
662 	struct thread *td;
663 	struct svr4_sys_pathconf_args *uap;
664 {
665 	char *path;
666 	int error, name;
667 
668 	name = svr4_to_bsd_pathconf(uap->name);
669 
670 	switch (name) {
671 	case -1:
672 		td->td_retval[0] = -1;
673 		return (EINVAL);
674 	case 0:
675 		td->td_retval[0] = 0;
676 		return (0);
677 	default:
678 		CHECKALTEXIST(td, uap->path, &path);
679 		error = kern_pathconf(td, path, UIO_SYSSPACE, name, FOLLOW);
680 		free(path, M_TEMP);
681 		return (error);
682 	}
683 }
684 
685 
686 int
svr4_sys_fpathconf(td,uap)687 svr4_sys_fpathconf(td, uap)
688 	struct thread *td;
689 	struct svr4_sys_fpathconf_args *uap;
690 {
691         register_t	*retval = td->td_retval;
692 
693 	uap->name = svr4_to_bsd_pathconf(uap->name);
694 
695 	switch (uap->name) {
696 	case -1:
697 		*retval = -1;
698 		return EINVAL;
699 	case 0:
700 		*retval = 0;
701 		return 0;
702 	default:
703 		return sys_fpathconf(td, (struct fpathconf_args *)uap);
704 	}
705 }
706