xref: /netbsd-src/sys/rump/kern/lib/libsys_sunos/rump_sunos_compat.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: rump_sunos_compat.c,v 1.2 2017/07/28 15:34:07 riastradh Exp $	*/
2 
3 /*
4  * Copyright (c) 2013 Antti Kantee.  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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/param.h>
29 #include <sys/dirent.h>
30 #include <sys/fcntl.h>
31 #include <sys/file.h>
32 #include <sys/filedesc.h>
33 #include <sys/malloc.h>
34 #include <sys/namei.h>
35 #include <sys/stat.h>
36 #include <sys/syscallargs.h>
37 #include <sys/vnode.h>
38 #include <sys/vfs_syscalls.h>
39 
40 #include <compat/sys/time_types.h>
41 
42 #include "rump_sunos_syscallargs.h"
43 
44 #define SUNOS_MAXNAMLEN 255
45 
46 struct sunos_dirent {
47 	uint64_t	d_fileno;
48 	int64_t		d_off;
49 	unsigned short	d_reclen;
50 	char		d_name[SUNOS_MAXNAMLEN + 1];
51 };
52 
53 #define SUNOS_NAMEOFF(dp)	((char *)&(dp)->d_name - (char *)dp)
54 #define SUNOS_RECLEN(de,namlen)	ALIGN((SUNOS_NAMEOFF(de) + (namlen) + 1))
55 
56 /*
57  * Rump kernels always use the _FILE_OFFSET_BITS=64 API.
58  */
59 #ifdef __LP64__
60 struct sunos_stat {
61         unsigned long	st_dev;
62         uint64_t	st_ino;
63         unsigned int	st_mode;
64         unsigned int	st_nlink;
65         unsigned int	st_uid;
66         unsigned int	st_gid;
67         unsigned long	st_rdev;
68         off_t		st_size;
69 
70         struct timespec	st_atim;
71         struct timespec	st_mtim;
72         struct timespec	st_ctim;
73         int		st_blksize;
74         uint64_t	st_blocks;
75         char		st_fstype[16];
76 };
77 #else
78 struct sunos_stat {
79         unsigned long	st_dev;
80 	long		st_pad1[3];
81         uint64_t	st_ino;
82         unsigned int	st_mode;
83         unsigned int	st_nlink;
84         unsigned int	st_uid;
85         unsigned int	st_gid;
86         unsigned long	st_rdev;
87 	long		st_pad2[2];
88         off_t		st_size;
89 
90         struct timespec50 st_atim;
91         struct timespec50 st_mtim;
92         struct timespec50 st_ctim;
93 
94         int		st_blksize;
95         uint64_t	st_blocks;
96         char            st_fstype[16];
97 	long		st_pad4[8];
98 };
99 #endif
100 
101 #define PARCOPY(a) ssb->a = sb->a
102 static void
103 bsd_to_sunos_stat(const struct stat *sb, struct sunos_stat *ssb)
104 {
105 
106 	memset(ssb, 0, sizeof(*ssb));
107 	PARCOPY(st_dev);
108 	PARCOPY(st_ino);
109 	PARCOPY(st_mode);
110 	PARCOPY(st_nlink);
111 	PARCOPY(st_uid);
112 	PARCOPY(st_gid);
113 	PARCOPY(st_rdev);
114 	PARCOPY(st_size);
115 	PARCOPY(st_blksize);
116 	PARCOPY(st_blocks);
117 
118 #ifdef __LP64__
119 	ssb->st_atim = sb->st_atimespec;
120 	ssb->st_mtim = sb->st_mtimespec;
121 	ssb->st_ctim = sb->st_ctimespec;
122 #else
123 	timespec_to_timespec50(&sb->st_atimespec, &ssb->st_atim);
124 	timespec_to_timespec50(&sb->st_mtimespec, &ssb->st_mtim);
125 	timespec_to_timespec50(&sb->st_ctimespec, &ssb->st_ctim);
126 #endif
127 }
128 
129 int
130 rump_sunos_sys_stat(struct lwp *l, const struct rump_sunos_sys_stat_args *uap,
131 	register_t *retval)
132 {
133 	struct sunos_stat ssb;
134 	struct stat sb;
135 	int error;
136 
137 	error = do_sys_stat(SCARG(uap, path), FOLLOW, &sb);
138 	if (error)
139 		return error;
140 
141 	bsd_to_sunos_stat(&sb, &ssb);
142 
143 	return copyout(&ssb, SCARG(uap, sp), sizeof(ssb));
144 }
145 
146 int
147 rump_sunos_sys_fstat(struct lwp *l, const struct rump_sunos_sys_fstat_args *uap,
148 	register_t *retval)
149 {
150 	struct sunos_stat ssb;
151 	struct stat sb;
152 	int error;
153 
154 	error = do_sys_fstat(SCARG(uap, fd), &sb);
155 	if (error)
156 		return error;
157 
158 	bsd_to_sunos_stat(&sb, &ssb);
159 
160 	return copyout(&ssb, SCARG(uap, sp), sizeof(ssb));
161 }
162 
163 int
164 rump_sunos_sys_lstat(struct lwp *l, const struct rump_sunos_sys_lstat_args *uap,
165 	register_t *retval)
166 {
167 	struct sunos_stat ssb;
168 	struct stat sb;
169 	int error;
170 
171 	error = do_sys_stat(SCARG(uap, path), NOFOLLOW, &sb);
172 	if (error)
173 		return error;
174 
175 	bsd_to_sunos_stat(&sb, &ssb);
176 
177 	return copyout(&ssb, SCARG(uap, sp), sizeof(ssb));
178 }
179 
180 int
181 rump_sunos_sys_open(struct lwp *l, const struct rump_sunos_sys_open_args *uap,
182 	register_t *retval)
183 {
184 	/* {
185 		syscallarg(const char *) path;
186 		syscallarg(int) flags;
187 		syscallarg(int) mode;
188 	} */
189 	struct sys_open_args ua;
190 	int sflags, flags;
191 
192 	sflags = SCARG(uap, flags);
193 	flags =  (sflags & (0x8 | 0x4 | 0x3)); /* nonblock/append/rw */
194 	flags |= (sflags & 0x10)	? O_SYNC : 0;
195 	flags |= (sflags & 0x40)	? O_DSYNC : 0;
196 	flags |= (sflags & 0x8000)	? O_RSYNC : 0;
197 	flags |= (sflags & 0x80)	? O_NONBLOCK : 0;
198 	flags |= (sflags & 0x100)	? O_CREAT : 0;
199 	flags |= (sflags & 0x200)	? O_TRUNC : 0;
200 	flags |= (sflags & 0x400)	? O_EXCL : 0;
201 	flags |= (sflags & 0x20000)	? O_NOFOLLOW : 0;
202 
203 	SCARG(&ua, path) = SCARG(uap, path);
204 	SCARG(&ua, flags) = flags;
205 	SCARG(&ua, mode) = SCARG(uap, mode);
206 
207 	return sys_open(l, &ua, retval);
208 }
209 
210 /*-
211  * Copyright (c) 1992, 1993
212  *      The Regents of the University of California.  All rights reserved.
213  *
214  * This software was developed by the Computer Systems Engineering group
215  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
216  * contributed to Berkeley.
217  *
218  * All advertising materials mentioning features or use of this software
219  * must display the following acknowledgement:
220  *      This product includes software developed by the University of
221  *      California, Lawrence Berkeley Laboratory.
222  *
223  * Redistribution and use in source and binary forms, with or without
224  * modification, are permitted provided that the following conditions
225  * are met:
226  * 1. Redistributions of source code must retain the above copyright
227  *    notice, this list of conditions and the following disclaimer.
228  * 2. Redistributions in binary form must reproduce the above copyright
229  *    notice, this list of conditions and the following disclaimer in the
230  *    documentation and/or other materials provided with the distribution.
231  * 3. Neither the name of the University nor the names of its contributors
232  *    may be used to endorse or promote products derived from this software
233  *    without specific prior written permission.
234  *
235  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
236  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
237  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
242  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
243  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
244  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
245  * SUCH DAMAGE.
246  *
247  *      @(#)sunos_misc.c        8.1 (Berkeley) 6/18/93
248  *
249  *      Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
250  */
251 
252 int
253 rump_sunos_sys_getdents(struct lwp *l,
254 	const struct rump_sunos_sys_getdents_args *uap, register_t *retval)
255 {
256 	struct dirent *bdp;
257 	struct vnode *vp;
258 	char *inp, *buf;	/* BSD-format */
259 	int len, reclen;	/* BSD-format */
260 	char *outp;		/* Sun-format */
261 	int resid, sunos_reclen;/* Sun-format */
262 	struct file *fp;
263 	struct uio auio;
264 	struct iovec aiov;
265 	struct sunos_dirent idb;
266 	off_t off;			/* true file offset */
267 	int buflen, error, eofflag;
268 	off_t *cookiebuf, *cookie;
269 	int ncookies;
270 
271 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
272 		return (error);
273 
274 	if ((fp->f_flag & FREAD) == 0) {
275 		error = EBADF;
276 		goto out1;
277 	}
278 
279 	vp = fp->f_data;
280 	if (vp->v_type != VDIR) {
281 		error = EINVAL;
282 		goto out1;
283 	}
284 
285 	buflen = min(MAXBSIZE, SCARG(uap, nbytes));
286 	buf = malloc(buflen, M_TEMP, M_WAITOK);
287 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
288 	off = fp->f_offset;
289 again:
290 	aiov.iov_base = buf;
291 	aiov.iov_len = buflen;
292 	auio.uio_iov = &aiov;
293 	auio.uio_iovcnt = 1;
294 	auio.uio_rw = UIO_READ;
295 	auio.uio_resid = buflen;
296 	auio.uio_offset = off;
297 	UIO_SETUP_SYSSPACE(&auio);
298 	/*
299 	 * First we read into the malloc'ed buffer, then
300 	 * we massage it into user space, one record at a time.
301 	 */
302 	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
303 	    &ncookies);
304 	if (error)
305 		goto out;
306 
307 	inp = buf;
308 	outp = SCARG(uap, buf);
309 	resid = SCARG(uap, nbytes);
310 	if ((len = buflen - auio.uio_resid) == 0)
311 		goto eof;
312 
313 	for (cookie = cookiebuf; len > 0; len -= reclen) {
314 		bdp = (struct dirent *)inp;
315 		reclen = bdp->d_reclen;
316 		if (reclen & 3) {
317 			error = EIO;
318 			goto out;
319 		}
320 		if ((*cookie >> 32) != 0) {
321 			printf("rump_sunos_sys_getdents: offset too large\n");
322 			error = EINVAL;
323 			goto out;
324 		}
325 		if (bdp->d_fileno == 0) {
326 			inp += reclen;	/* it is a hole; squish it out */
327 			if (cookie)
328 				off = *cookie++;
329 			else
330 				off += reclen;
331 			continue;
332 		}
333 		sunos_reclen = SUNOS_RECLEN(&idb, bdp->d_namlen);
334 		if (reclen > len || resid < sunos_reclen) {
335 			/* entry too big for buffer, so just stop */
336 			outp++;
337 			break;
338 		}
339 		if (cookie)
340 			off = *cookie++;	/* each entry points to next */
341 		else
342 			off += reclen;
343 		/*
344 		 * Massage in place to make a Sun-shaped dirent (otherwise
345 		 * we have to worry about touching user memory outside of
346 		 * the copyout() call).
347 		 */
348 		idb.d_fileno = bdp->d_fileno;
349 		idb.d_off = off;
350 		idb.d_reclen = sunos_reclen;
351 		strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
352 		if ((error = copyout((void *)&idb, outp, sunos_reclen)) != 0)
353 			goto out;
354 		/* advance past this real entry */
355 		inp += reclen;
356 		/* advance output past Sun-shaped entry */
357 		outp += sunos_reclen;
358 		resid -= sunos_reclen;
359 	}
360 
361 	/* if we squished out the whole block, try again */
362 	if (outp == SCARG(uap, buf)) {
363 		if (cookiebuf)
364 			free(cookiebuf, M_TEMP);
365 		cookiebuf = NULL;
366 		goto again;
367 	}
368 	fp->f_offset = off;		/* update the vnode offset */
369 
370 eof:
371 	*retval = SCARG(uap, nbytes) - resid;
372 out:
373 	VOP_UNLOCK(vp);
374 	free(cookiebuf, M_TEMP);
375 	free(buf, M_TEMP);
376  out1:
377  	fd_putfile(SCARG(uap, fd));
378 	return (error);
379 }
380