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