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