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