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 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 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 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 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 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 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