rump_sunos_compat.c revision 1.1 1 /* $NetBSD: rump_sunos_compat.c,v 1.1 2013/04/09 13:08:33 pooka 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 panic("sunos_getdents");
318 if ((*cookie >> 32) != 0) {
319 printf("rump_sunos_sys_getdents: offset too large\n");
320 error = EINVAL;
321 goto out;
322 }
323 if (bdp->d_fileno == 0) {
324 inp += reclen; /* it is a hole; squish it out */
325 if (cookie)
326 off = *cookie++;
327 else
328 off += reclen;
329 continue;
330 }
331 sunos_reclen = SUNOS_RECLEN(&idb, bdp->d_namlen);
332 if (reclen > len || resid < sunos_reclen) {
333 /* entry too big for buffer, so just stop */
334 outp++;
335 break;
336 }
337 if (cookie)
338 off = *cookie++; /* each entry points to next */
339 else
340 off += reclen;
341 /*
342 * Massage in place to make a Sun-shaped dirent (otherwise
343 * we have to worry about touching user memory outside of
344 * the copyout() call).
345 */
346 idb.d_fileno = bdp->d_fileno;
347 idb.d_off = off;
348 idb.d_reclen = sunos_reclen;
349 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
350 if ((error = copyout((void *)&idb, outp, sunos_reclen)) != 0)
351 goto out;
352 /* advance past this real entry */
353 inp += reclen;
354 /* advance output past Sun-shaped entry */
355 outp += sunos_reclen;
356 resid -= sunos_reclen;
357 }
358
359 /* if we squished out the whole block, try again */
360 if (outp == SCARG(uap, buf)) {
361 if (cookiebuf)
362 free(cookiebuf, M_TEMP);
363 cookiebuf = NULL;
364 goto again;
365 }
366 fp->f_offset = off; /* update the vnode offset */
367
368 eof:
369 *retval = SCARG(uap, nbytes) - resid;
370 out:
371 VOP_UNLOCK(vp);
372 free(cookiebuf, M_TEMP);
373 free(buf, M_TEMP);
374 out1:
375 fd_putfile(SCARG(uap, fd));
376 return (error);
377 }
378