1/*	$NetBSD: ibcs2_stat.c,v 1.46 2008/06/24 11:18:15 ad Exp $	*/
2/*
3 * Copyright (c) 1995, 1998 Scott Bartram
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__KERNEL_RCSID(0, "$NetBSD: ibcs2_stat.c,v 1.46 2008/06/24 11:18:15 ad Exp $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/namei.h>
35#include <sys/proc.h>
36#include <sys/file.h>
37#include <sys/stat.h>
38#include <sys/filedesc.h>
39#include <sys/ioctl.h>
40#include <sys/kernel.h>
41#include <sys/mount.h>
42#include <sys/vnode.h>
43#include <sys/syscallargs.h>
44#include <sys/vfs_syscalls.h>
45
46#include <compat/ibcs2/ibcs2_types.h>
47#include <compat/ibcs2/ibcs2_fcntl.h>
48#include <compat/ibcs2/ibcs2_signal.h>
49#include <compat/ibcs2/ibcs2_stat.h>
50#include <compat/ibcs2/ibcs2_statfs.h>
51#include <compat/ibcs2/ibcs2_syscallargs.h>
52#include <compat/ibcs2/ibcs2_ustat.h>
53#include <compat/ibcs2/ibcs2_util.h>
54#include <compat/ibcs2/ibcs2_utsname.h>
55
56static void bsd_stat2ibcs_stat(struct stat *, struct ibcs2_stat *);
57static int cvt_statfs(struct statvfs *, void *, int);
58static int cvt_statvfs(struct statvfs *, void *, int);
59
60static void
61bsd_stat2ibcs_stat(struct stat *st, struct ibcs2_stat *st4)
62{
63	memset(st4, 0, sizeof(*st4));
64	st4->st_dev = (ibcs2_dev_t)st->st_dev;
65	st4->st_ino = (ibcs2_ino_t)st->st_ino;
66	st4->st_mode = (ibcs2_mode_t)st->st_mode;
67	if (st->st_nlink >= (1 << 15))
68		st4->st_nlink = (1 << 15) - 1;
69	else
70		st4->st_nlink = (ibcs2_nlink_t)st->st_nlink;
71	st4->st_uid = (ibcs2_uid_t)st->st_uid;
72	st4->st_gid = (ibcs2_gid_t)st->st_gid;
73	st4->st_rdev = (ibcs2_dev_t)st->st_rdev;
74	st4->st_size = (ibcs2_off_t)st->st_size;
75	st4->st_atim = (ibcs2_time_t)st->st_atime;
76	st4->st_mtim = (ibcs2_time_t)st->st_mtime;
77	st4->st_ctim = (ibcs2_time_t)st->st_ctime;
78}
79
80static int
81cvt_statfs(struct statvfs *sp, void *tbuf, int len)
82{
83	struct ibcs2_statfs ssfs;
84
85	if (len < 0)
86		return (EINVAL);
87	if (len > sizeof(ssfs))
88		len = sizeof(ssfs);
89
90	memset(&ssfs, 0, sizeof ssfs);
91	ssfs.f_fstyp = 0;
92	ssfs.f_bsize = sp->f_bsize;
93	ssfs.f_frsize = sp->f_frsize;
94	ssfs.f_blocks = sp->f_blocks;
95	ssfs.f_bfree = sp->f_bfree;
96	ssfs.f_files = sp->f_files;
97	ssfs.f_ffree = sp->f_ffree;
98	ssfs.f_fname[0] = 0;
99	ssfs.f_fpack[0] = 0;
100	return copyout((void *)&ssfs, tbuf, len);
101}
102
103static int
104cvt_statvfs(struct statvfs *sp, void *tbuf, int len)
105{
106	struct ibcs2_statvfs ssvfs;
107
108	if (len < 0)
109		return (EINVAL);
110	if (len > sizeof(ssvfs))
111		len = sizeof(ssvfs);
112
113	memset(&ssvfs, 0, sizeof ssvfs);
114	ssvfs.f_bsize = sp->f_bsize;
115	ssvfs.f_frsize = sp->f_frsize;
116	ssvfs.f_blocks = sp->f_blocks;
117	ssvfs.f_bfree = sp->f_bfree;
118	ssvfs.f_bavail = sp->f_bavail;
119	ssvfs.f_files = sp->f_files;
120	ssvfs.f_ffree = sp->f_ffree;
121	ssvfs.f_favail = sp->f_favail;
122	ssvfs.f_fsid = sp->f_fsidx.__fsid_val[0];
123	strncpy(ssvfs.f_basetype, sp->f_fstypename, 15);
124	ssvfs.f_flag = 0;
125	ssvfs.f_namemax = PATH_MAX;
126	ssvfs.f_fstr[0] = 0;
127	return copyout((void *)&ssvfs, tbuf, len);
128}
129
130int
131ibcs2_sys_statfs(struct lwp *l, const struct ibcs2_sys_statfs_args *uap, register_t *retval)
132{
133	/* {
134		syscallarg(const char *) path;
135		syscallarg(struct ibcs2_statfs *) buf;
136		syscallarg(int) len;
137		syscallarg(int) fstype;
138	} */
139	struct mount *mp;
140	struct statvfs *sp;
141	int error;
142	struct vnode *vp;
143
144	error = namei_simple_user(SCARG(uap, path),
145				NSM_FOLLOW_TRYEMULROOT, &vp);
146	if (error != 0)
147		return (error);
148	mp = vp->v_mount;
149	sp = &mp->mnt_stat;
150	vrele(vp);
151	if ((error = VFS_STATVFS(mp, sp)) != 0)
152		return (error);
153	sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
154	return cvt_statfs(sp, (void *)SCARG(uap, buf), SCARG(uap, len));
155}
156
157int
158ibcs2_sys_fstatfs(struct lwp *l, const struct ibcs2_sys_fstatfs_args *uap, register_t *retval)
159{
160	/* {
161		syscallarg(int) fd;
162		syscallarg(struct ibcs2_statfs *) buf;
163		syscallarg(int) len;
164		syscallarg(int) fstype;
165	} */
166	file_t *fp;
167	struct mount *mp;
168	struct statvfs *sp;
169	int error;
170
171	/* fd_getvnode() will use the descriptor for us */
172	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
173		return (error);
174	mp = ((struct vnode *)fp->f_data)->v_mount;
175	sp = &mp->mnt_stat;
176	if ((error = VFS_STATVFS(mp, sp)) != 0)
177		goto out;
178	sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
179	error = cvt_statfs(sp, (void *)SCARG(uap, buf), SCARG(uap, len));
180 out:
181 	fd_putfile(SCARG(uap, fd));
182	return (error);
183}
184
185int
186ibcs2_sys_statvfs(struct lwp *l, const struct ibcs2_sys_statvfs_args *uap, register_t *retval)
187{
188	/* {
189		syscallarg(const char *) path;
190		syscallarg(struct ibcs2_statvfs *) buf;
191	} */
192	struct mount *mp;
193	struct statvfs *sp;
194	int error;
195	struct vnode *vp;
196
197	error = namei_simple_user(SCARG(uap, path),
198				NSM_FOLLOW_TRYEMULROOT, &vp);
199	if (error != 0)
200		return (error);
201	mp = vp->v_mount;
202	sp = &mp->mnt_stat;
203	vrele(vp);
204	if ((error = VFS_STATVFS(mp, sp)) != 0)
205		return (error);
206	sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
207	return cvt_statvfs(sp, (void *)SCARG(uap, buf),
208			   sizeof(struct ibcs2_statvfs));
209}
210
211int
212ibcs2_sys_fstatvfs(struct lwp *l, const struct ibcs2_sys_fstatvfs_args *uap, register_t *retval)
213{
214	/* {
215		syscallarg(int) fd;
216		syscallarg(struct ibcs2_statvfs *) buf;
217	} */
218	file_t *fp;
219	struct mount *mp;
220	struct statvfs *sp;
221	int error;
222
223	/* fd_getvnode() will use the descriptor for us */
224	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
225		return (error);
226	mp = ((struct vnode *)fp->f_data)->v_mount;
227	sp = &mp->mnt_stat;
228	if ((error = VFS_STATVFS(mp, sp)) != 0)
229		goto out;
230	sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
231	error = cvt_statvfs(sp, SCARG(uap, buf), sizeof(struct ibcs2_statvfs));
232 out:
233 	fd_putfile(SCARG(uap, fd));
234	return (error);
235}
236
237int
238ibcs2_sys_stat(struct lwp *l, const struct ibcs2_sys_stat_args *uap, register_t *retval)
239{
240	/* {
241		syscallarg(const char *) path;
242		syscallarg(struct ibcs2_stat *) st;
243	} */
244	struct stat sb;
245	struct ibcs2_stat ibcs2_st;
246	int error;
247
248	error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
249	if (error != 0)
250		return error;
251
252	bsd_stat2ibcs_stat(&sb, &ibcs2_st);
253	return copyout(&ibcs2_st, SCARG(uap, st), sizeof (ibcs2_st));
254}
255
256int
257ibcs2_sys_lstat(struct lwp *l, const struct ibcs2_sys_lstat_args *uap, register_t *retval)
258{
259	/* {
260		syscallarg(const char *) path;
261		syscallarg(struct ibcs2_stat *) st;
262	} */
263	struct stat sb;
264	struct ibcs2_stat ibcs2_st;
265	int error;
266
267	error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
268	if (error != 0)
269		return error;
270
271	bsd_stat2ibcs_stat(&sb, &ibcs2_st);
272	return copyout((void *)&ibcs2_st, (void *)SCARG(uap, st),
273		       sizeof (ibcs2_st));
274}
275
276int
277ibcs2_sys_fstat(struct lwp *l, const struct ibcs2_sys_fstat_args *uap, register_t *retval)
278{
279	/* {
280		syscallarg(int) fd;
281		syscallarg(struct ibcs2_stat *) st;
282	} */
283	struct stat sb;
284	struct ibcs2_stat ibcs2_st;
285	int error;
286
287	error = do_sys_fstat(SCARG(uap, fd), &sb);
288	if (error != 0)
289		return error;
290
291	bsd_stat2ibcs_stat(&sb, &ibcs2_st);
292	return copyout(&ibcs2_st, SCARG(uap, st), sizeof (ibcs2_st));
293}
294
295int
296ibcs2_sys_utssys(struct lwp *l, const struct ibcs2_sys_utssys_args *uap, register_t *retval)
297{
298	/* {
299		syscallarg(int) a1;
300		syscallarg(int) a2;
301		syscallarg(int) flag;
302	} */
303
304	switch (SCARG(uap, flag)) {
305	case 0:			/* uname(struct utsname *) */
306	{
307		struct ibcs2_utsname sut;
308
309		memset(&sut, 0, ibcs2_utsname_len);
310		memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1);
311		memcpy(sut.nodename, hostname, sizeof(sut.nodename));
312		sut.nodename[sizeof(sut.nodename)-1] = '\0';
313		memcpy(sut.release, osrelease, sizeof(sut.release) - 1);
314		strlcpy(sut.version, "1", sizeof(sut.version));
315		memcpy(sut.machine, machine, sizeof(sut.machine) - 1);
316
317		return copyout((void *)&sut, (void *)SCARG(uap, a1),
318			       ibcs2_utsname_len);
319	}
320
321	case 2:			/* ustat(dev_t, struct ustat *) */
322	{
323		struct ibcs2_ustat xu;
324
325		xu.f_tfree = 20000; /* XXX fixme */
326		xu.f_tinode = 32000;
327		xu.f_fname[0] = 0;
328		xu.f_fpack[0] = 0;
329		return copyout((void *)&xu, (void *)SCARG(uap, a2),
330                               ibcs2_ustat_len);
331	}
332
333	default:
334		return ENOSYS;
335	}
336}
337