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