1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 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 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 *
| 1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 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 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 *
|
28 * $Id: linux_file.c,v 1.2 1995/06/07 21:27:57 sos Exp $
| 28 * $Id: linux_file.c,v 1.1 1995/06/25 17:32:34 sos Exp $
|
29 */ 30 31#include <i386/linux/linux.h> 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/fcntl.h> 35#include <sys/file.h> 36#include <sys/filedesc.h> 37#include <sys/proc.h> 38#include <sys/ioctl.h> 39#include <sys/stat.h> 40#include <sys/vnode.h> 41#include <sys/malloc.h> 42#include <sys/exec.h> 43#include <sys/dirent.h> 44#include <vm/vm.h> 45#include <ufs/ufs/dir.h> 46 47 48struct linux_creat_args { 49 char *path; 50 int mode; 51}; 52 53int 54linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) 55{ 56 struct { 57 char *path; 58 int flags; 59 int mode; 60 } bsd_open_args; 61 62#ifdef DEBUG 63 printf("Linux-emul(%d): creat(%s, %d)\n", 64 p->p_pid, args->path, args->mode); 65#endif 66 bsd_open_args.path = args->path; 67 bsd_open_args.mode = args->mode; 68 bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 69 return open(p, &bsd_open_args, retval); 70} 71 72struct linux_open_args { 73 char *path; 74 int flags; 75 int mode; 76}; 77 78int 79linux_open(struct proc *p, struct linux_open_args *args, int *retval) 80{ 81 struct { 82 char *path; 83 int flags; 84 int mode; 85 } bsd_open_args; 86 int error; 87 88#ifdef DEBUG 89 printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n", 90 p->p_pid, args->path, args->flags, args->mode); 91#endif 92 bsd_open_args.flags = 0; 93 if (args->flags & LINUX_O_RDONLY) 94 bsd_open_args.flags |= O_RDONLY; 95 if (args->flags & LINUX_O_WRONLY) 96 bsd_open_args.flags |= O_WRONLY; 97 if (args->flags & LINUX_O_RDWR) 98 bsd_open_args.flags |= O_RDWR; 99 if (args->flags & LINUX_O_NDELAY) 100 bsd_open_args.flags |= O_NONBLOCK; 101 if (args->flags & LINUX_O_APPEND) 102 bsd_open_args.flags |= O_APPEND; 103 if (args->flags & LINUX_O_SYNC) 104 bsd_open_args.flags |= O_FSYNC; 105 if (args->flags & LINUX_O_NONBLOCK) 106 bsd_open_args.flags |= O_NONBLOCK; 107 if (args->flags & LINUX_FASYNC) 108 bsd_open_args.flags |= O_ASYNC; 109 if (args->flags & LINUX_O_CREAT) 110 bsd_open_args.flags |= O_CREAT; 111 if (args->flags & LINUX_O_TRUNC) 112 bsd_open_args.flags |= O_TRUNC; 113 if (args->flags & LINUX_O_EXCL) 114 bsd_open_args.flags |= O_EXCL; 115 if (args->flags & LINUX_O_NOCTTY) 116 bsd_open_args.flags |= O_NOCTTY; 117 bsd_open_args.path = args->path; 118 bsd_open_args.mode = args->mode; 119 120 error = open(p, &bsd_open_args, retval); 121 if (!error && !(bsd_open_args.flags & O_NOCTTY) && 122 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 123 struct filedesc *fdp = p->p_fd; 124 struct file *fp = fdp->fd_ofiles[*retval]; 125 126 if (fp->f_type == DTYPE_VNODE) 127 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); 128 } 129 return error; 130} 131 132struct linux_flock { 133 short l_type; 134 short l_whence; 135 linux_off_t l_start; 136 linux_off_t l_len; 137 linux_pid_t l_pid; 138}; 139 140static void 141linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) 142{ 143 switch (linux_flock->l_type) { 144 case LINUX_F_RDLCK: 145 bsd_flock->l_type = F_RDLCK; 146 break; 147 case LINUX_F_WRLCK: 148 bsd_flock->l_type = F_WRLCK; 149 break; 150 case LINUX_F_UNLCK: 151 bsd_flock->l_type = F_UNLCK; 152 break; 153 } 154 bsd_flock->l_whence = linux_flock->l_whence; 155 bsd_flock->l_start = (off_t)linux_flock->l_start; 156 bsd_flock->l_len = (off_t)linux_flock->l_len; 157 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 158} 159 160static void 161bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) 162{ 163 switch (bsd_flock->l_type) { 164 case F_RDLCK: 165 linux_flock->l_type = LINUX_F_RDLCK; 166 break; 167 case F_WRLCK: 168 linux_flock->l_type = LINUX_F_WRLCK; 169 break; 170 case F_UNLCK: 171 linux_flock->l_type = LINUX_F_UNLCK; 172 break; 173 } 174 linux_flock->l_whence = bsd_flock->l_whence; 175 linux_flock->l_start = (linux_off_t)bsd_flock->l_start; 176 linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 177 linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; 178} 179 180struct linux_fcntl_args { 181 int fd; 182 int cmd; 183 int arg; 184}; 185 186int 187linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval) 188{ 189 int error, result; 190 struct fcntl_args { 191 int fd; 192 int cmd; 193 int arg; 194 } fcntl_args; 195 struct linux_flock linux_flock; 196 struct flock *bsd_flock = 197 (struct flock *)ua_alloc_init(sizeof(struct flock)); 198 199#ifdef DEBUG 200 printf("Linux-emul(%d): fcntl(%d, %08x, *)\n", 201 p->p_pid, args->fd, args->cmd); 202#endif 203 fcntl_args.fd = args->fd; 204 fcntl_args.arg = 0; 205 206 switch (args->cmd) { 207 case LINUX_F_DUPFD: 208 fcntl_args.cmd = F_DUPFD; 209 return fcntl(p, &fcntl_args, retval); 210 211 case LINUX_F_GETFD: 212 fcntl_args.cmd = F_GETFD; 213 return fcntl(p, &fcntl_args, retval); 214 215 case LINUX_F_SETFD: 216 fcntl_args.cmd = F_SETFD; 217 return fcntl(p, &fcntl_args, retval); 218 219 case LINUX_F_GETFL: 220 fcntl_args.cmd = F_GETFL; 221 error = fcntl(p, &fcntl_args, &result); 222 *retval = 0; 223 if (result & O_RDONLY) *retval |= LINUX_O_RDONLY; 224 if (result & O_WRONLY) *retval |= LINUX_O_WRONLY; 225 if (result & O_RDWR) *retval |= LINUX_O_RDWR; 226 if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK; 227 if (result & O_APPEND) *retval |= LINUX_O_APPEND; 228 if (result & O_FSYNC) *retval |= LINUX_O_SYNC; 229 return error; 230 231 case LINUX_F_SETFL: 232 if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; 233 if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; 234 if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; 235 fcntl_args.cmd = F_SETFL; 236 return fcntl(p, &fcntl_args, retval); 237 238 case LINUX_F_GETLK: 239 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 240 sizeof(struct linux_flock)))) 241 return error; 242 linux_to_bsd_flock(&linux_flock, bsd_flock); 243 fcntl_args.cmd = F_GETLK; 244 fcntl_args.arg = (int)bsd_flock; 245 if (error = fcntl(p, &fcntl_args, retval)) 246 return error; 247 bsd_to_linux_flock(bsd_flock, &linux_flock); 248 return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, 249 sizeof(struct linux_flock)); 250 251 case LINUX_F_SETLK: 252 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 253 sizeof(struct linux_flock)))) 254 return error; 255 linux_to_bsd_flock(&linux_flock, bsd_flock); 256 fcntl_args.cmd = F_SETLK; 257 fcntl_args.arg = (int)bsd_flock; 258 return fcntl(p, &fcntl_args, retval); 259 260 case LINUX_F_SETLKW: 261 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 262 sizeof(struct linux_flock)))) 263 return error; 264 linux_to_bsd_flock(&linux_flock, bsd_flock); 265 fcntl_args.cmd = F_SETLKW; 266 fcntl_args.arg = (int)bsd_flock; 267 return fcntl(p, &fcntl_args, retval); 268 269 case LINUX_F_SETOWN: 270 fcntl_args.cmd = F_SETOWN; 271 return fcntl(p, &fcntl_args, retval); 272 273 case LINUX_F_GETOWN: 274 fcntl_args.cmd = F_GETOWN; 275 return fcntl(p, &fcntl_args, retval); 276 } 277 return EINVAL; 278} 279 280struct linux_lseek_args { 281 int fdes; 282 unsigned long off; 283 int whence; 284}; 285 286int 287linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval) 288{ 289 290 struct lseek_args { 291 int fdes; 292 int pad; 293 off_t off; 294 int whence; 295 } tmp_args; 296 off_t tmp_retval; 297 int error; 298 299#ifdef DEBUG 300 printf("Linux-emul(%d): lseek(%d, %d, %d)\n", 301 p->p_pid, args->fdes, args->off, args->whence); 302#endif 303 tmp_args.fdes = args->fdes; 304 tmp_args.off = (off_t)args->off; 305 tmp_args.whence = args->whence; 306 error = lseek(p, &tmp_args, &tmp_retval); 307 *retval = (int)tmp_retval; 308 return error; 309} 310 311struct linux_dirent { 312 long dino; 313 linux_off_t doff; 314 unsigned short dreclen; 315 char dname[LINUX_NAME_MAX + 1]; 316}; 317 318#define LINUX_RECLEN(de,namlen) \ 319 ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) 320 321struct linux_readdir_args { 322 int fd; 323 struct linux_dirent *dent; 324 unsigned int count; 325}; 326 327int 328linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval) 329{ 330 register struct dirent *bdp; 331 struct vnode *vp; 332 caddr_t inp, buf; /* BSD-format */ 333 int len, reclen; /* BSD-format */ 334 caddr_t outp; /* Linux-format */ 335 int resid, linuxreclen=0; /* Linux-format */ 336 struct file *fp; 337 struct uio auio; 338 struct iovec aiov; 339 struct vattr va; 340 off_t off; 341 struct linux_dirent linux_dirent;
| 29 */ 30 31#include <i386/linux/linux.h> 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/fcntl.h> 35#include <sys/file.h> 36#include <sys/filedesc.h> 37#include <sys/proc.h> 38#include <sys/ioctl.h> 39#include <sys/stat.h> 40#include <sys/vnode.h> 41#include <sys/malloc.h> 42#include <sys/exec.h> 43#include <sys/dirent.h> 44#include <vm/vm.h> 45#include <ufs/ufs/dir.h> 46 47 48struct linux_creat_args { 49 char *path; 50 int mode; 51}; 52 53int 54linux_creat(struct proc *p, struct linux_creat_args *args, int *retval) 55{ 56 struct { 57 char *path; 58 int flags; 59 int mode; 60 } bsd_open_args; 61 62#ifdef DEBUG 63 printf("Linux-emul(%d): creat(%s, %d)\n", 64 p->p_pid, args->path, args->mode); 65#endif 66 bsd_open_args.path = args->path; 67 bsd_open_args.mode = args->mode; 68 bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 69 return open(p, &bsd_open_args, retval); 70} 71 72struct linux_open_args { 73 char *path; 74 int flags; 75 int mode; 76}; 77 78int 79linux_open(struct proc *p, struct linux_open_args *args, int *retval) 80{ 81 struct { 82 char *path; 83 int flags; 84 int mode; 85 } bsd_open_args; 86 int error; 87 88#ifdef DEBUG 89 printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n", 90 p->p_pid, args->path, args->flags, args->mode); 91#endif 92 bsd_open_args.flags = 0; 93 if (args->flags & LINUX_O_RDONLY) 94 bsd_open_args.flags |= O_RDONLY; 95 if (args->flags & LINUX_O_WRONLY) 96 bsd_open_args.flags |= O_WRONLY; 97 if (args->flags & LINUX_O_RDWR) 98 bsd_open_args.flags |= O_RDWR; 99 if (args->flags & LINUX_O_NDELAY) 100 bsd_open_args.flags |= O_NONBLOCK; 101 if (args->flags & LINUX_O_APPEND) 102 bsd_open_args.flags |= O_APPEND; 103 if (args->flags & LINUX_O_SYNC) 104 bsd_open_args.flags |= O_FSYNC; 105 if (args->flags & LINUX_O_NONBLOCK) 106 bsd_open_args.flags |= O_NONBLOCK; 107 if (args->flags & LINUX_FASYNC) 108 bsd_open_args.flags |= O_ASYNC; 109 if (args->flags & LINUX_O_CREAT) 110 bsd_open_args.flags |= O_CREAT; 111 if (args->flags & LINUX_O_TRUNC) 112 bsd_open_args.flags |= O_TRUNC; 113 if (args->flags & LINUX_O_EXCL) 114 bsd_open_args.flags |= O_EXCL; 115 if (args->flags & LINUX_O_NOCTTY) 116 bsd_open_args.flags |= O_NOCTTY; 117 bsd_open_args.path = args->path; 118 bsd_open_args.mode = args->mode; 119 120 error = open(p, &bsd_open_args, retval); 121 if (!error && !(bsd_open_args.flags & O_NOCTTY) && 122 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 123 struct filedesc *fdp = p->p_fd; 124 struct file *fp = fdp->fd_ofiles[*retval]; 125 126 if (fp->f_type == DTYPE_VNODE) 127 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p); 128 } 129 return error; 130} 131 132struct linux_flock { 133 short l_type; 134 short l_whence; 135 linux_off_t l_start; 136 linux_off_t l_len; 137 linux_pid_t l_pid; 138}; 139 140static void 141linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) 142{ 143 switch (linux_flock->l_type) { 144 case LINUX_F_RDLCK: 145 bsd_flock->l_type = F_RDLCK; 146 break; 147 case LINUX_F_WRLCK: 148 bsd_flock->l_type = F_WRLCK; 149 break; 150 case LINUX_F_UNLCK: 151 bsd_flock->l_type = F_UNLCK; 152 break; 153 } 154 bsd_flock->l_whence = linux_flock->l_whence; 155 bsd_flock->l_start = (off_t)linux_flock->l_start; 156 bsd_flock->l_len = (off_t)linux_flock->l_len; 157 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 158} 159 160static void 161bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) 162{ 163 switch (bsd_flock->l_type) { 164 case F_RDLCK: 165 linux_flock->l_type = LINUX_F_RDLCK; 166 break; 167 case F_WRLCK: 168 linux_flock->l_type = LINUX_F_WRLCK; 169 break; 170 case F_UNLCK: 171 linux_flock->l_type = LINUX_F_UNLCK; 172 break; 173 } 174 linux_flock->l_whence = bsd_flock->l_whence; 175 linux_flock->l_start = (linux_off_t)bsd_flock->l_start; 176 linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 177 linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; 178} 179 180struct linux_fcntl_args { 181 int fd; 182 int cmd; 183 int arg; 184}; 185 186int 187linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval) 188{ 189 int error, result; 190 struct fcntl_args { 191 int fd; 192 int cmd; 193 int arg; 194 } fcntl_args; 195 struct linux_flock linux_flock; 196 struct flock *bsd_flock = 197 (struct flock *)ua_alloc_init(sizeof(struct flock)); 198 199#ifdef DEBUG 200 printf("Linux-emul(%d): fcntl(%d, %08x, *)\n", 201 p->p_pid, args->fd, args->cmd); 202#endif 203 fcntl_args.fd = args->fd; 204 fcntl_args.arg = 0; 205 206 switch (args->cmd) { 207 case LINUX_F_DUPFD: 208 fcntl_args.cmd = F_DUPFD; 209 return fcntl(p, &fcntl_args, retval); 210 211 case LINUX_F_GETFD: 212 fcntl_args.cmd = F_GETFD; 213 return fcntl(p, &fcntl_args, retval); 214 215 case LINUX_F_SETFD: 216 fcntl_args.cmd = F_SETFD; 217 return fcntl(p, &fcntl_args, retval); 218 219 case LINUX_F_GETFL: 220 fcntl_args.cmd = F_GETFL; 221 error = fcntl(p, &fcntl_args, &result); 222 *retval = 0; 223 if (result & O_RDONLY) *retval |= LINUX_O_RDONLY; 224 if (result & O_WRONLY) *retval |= LINUX_O_WRONLY; 225 if (result & O_RDWR) *retval |= LINUX_O_RDWR; 226 if (result & O_NDELAY) *retval |= LINUX_O_NONBLOCK; 227 if (result & O_APPEND) *retval |= LINUX_O_APPEND; 228 if (result & O_FSYNC) *retval |= LINUX_O_SYNC; 229 return error; 230 231 case LINUX_F_SETFL: 232 if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; 233 if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; 234 if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; 235 fcntl_args.cmd = F_SETFL; 236 return fcntl(p, &fcntl_args, retval); 237 238 case LINUX_F_GETLK: 239 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 240 sizeof(struct linux_flock)))) 241 return error; 242 linux_to_bsd_flock(&linux_flock, bsd_flock); 243 fcntl_args.cmd = F_GETLK; 244 fcntl_args.arg = (int)bsd_flock; 245 if (error = fcntl(p, &fcntl_args, retval)) 246 return error; 247 bsd_to_linux_flock(bsd_flock, &linux_flock); 248 return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, 249 sizeof(struct linux_flock)); 250 251 case LINUX_F_SETLK: 252 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 253 sizeof(struct linux_flock)))) 254 return error; 255 linux_to_bsd_flock(&linux_flock, bsd_flock); 256 fcntl_args.cmd = F_SETLK; 257 fcntl_args.arg = (int)bsd_flock; 258 return fcntl(p, &fcntl_args, retval); 259 260 case LINUX_F_SETLKW: 261 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 262 sizeof(struct linux_flock)))) 263 return error; 264 linux_to_bsd_flock(&linux_flock, bsd_flock); 265 fcntl_args.cmd = F_SETLKW; 266 fcntl_args.arg = (int)bsd_flock; 267 return fcntl(p, &fcntl_args, retval); 268 269 case LINUX_F_SETOWN: 270 fcntl_args.cmd = F_SETOWN; 271 return fcntl(p, &fcntl_args, retval); 272 273 case LINUX_F_GETOWN: 274 fcntl_args.cmd = F_GETOWN; 275 return fcntl(p, &fcntl_args, retval); 276 } 277 return EINVAL; 278} 279 280struct linux_lseek_args { 281 int fdes; 282 unsigned long off; 283 int whence; 284}; 285 286int 287linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval) 288{ 289 290 struct lseek_args { 291 int fdes; 292 int pad; 293 off_t off; 294 int whence; 295 } tmp_args; 296 off_t tmp_retval; 297 int error; 298 299#ifdef DEBUG 300 printf("Linux-emul(%d): lseek(%d, %d, %d)\n", 301 p->p_pid, args->fdes, args->off, args->whence); 302#endif 303 tmp_args.fdes = args->fdes; 304 tmp_args.off = (off_t)args->off; 305 tmp_args.whence = args->whence; 306 error = lseek(p, &tmp_args, &tmp_retval); 307 *retval = (int)tmp_retval; 308 return error; 309} 310 311struct linux_dirent { 312 long dino; 313 linux_off_t doff; 314 unsigned short dreclen; 315 char dname[LINUX_NAME_MAX + 1]; 316}; 317 318#define LINUX_RECLEN(de,namlen) \ 319 ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) 320 321struct linux_readdir_args { 322 int fd; 323 struct linux_dirent *dent; 324 unsigned int count; 325}; 326 327int 328linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval) 329{ 330 register struct dirent *bdp; 331 struct vnode *vp; 332 caddr_t inp, buf; /* BSD-format */ 333 int len, reclen; /* BSD-format */ 334 caddr_t outp; /* Linux-format */ 335 int resid, linuxreclen=0; /* Linux-format */ 336 struct file *fp; 337 struct uio auio; 338 struct iovec aiov; 339 struct vattr va; 340 off_t off; 341 struct linux_dirent linux_dirent;
|
342 int buflen, error, eofflag, nbytes, justone;
| 342 int buflen, error, eofflag, nbytes, justone, blockoff;
|
343 344#ifdef DEBUG 345 printf("Linux-emul(%d): readdir(%d, *, %d)\n", 346 p->p_pid, args->fd, args->count); 347#endif
| 343 344#ifdef DEBUG 345 printf("Linux-emul(%d): readdir(%d, *, %d)\n", 346 p->p_pid, args->fd, args->count); 347#endif
|
348 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0)
| 348 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) {
|
349 return (error);
| 349 return (error);
|
| 350}
|
350 351 if ((fp->f_flag & FREAD) == 0) 352 return (EBADF); 353 354 vp = (struct vnode *) fp->f_data; 355 356 if (vp->v_type != VDIR) 357 return (EINVAL); 358
| 351 352 if ((fp->f_flag & FREAD) == 0) 353 return (EBADF); 354 355 vp = (struct vnode *) fp->f_data; 356 357 if (vp->v_type != VDIR) 358 return (EINVAL); 359
|
359 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
| 360 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) {
|
360 return error;
| 361 return error;
|
| 362 }
|
361 362 nbytes = args->count; 363 if (nbytes == 1) { 364 nbytes = sizeof (struct linux_dirent); 365 justone = 1; 366 } 367 else 368 justone = 0; 369
| 363 364 nbytes = args->count; 365 if (nbytes == 1) { 366 nbytes = sizeof (struct linux_dirent); 367 justone = 1; 368 } 369 else 370 justone = 0; 371
|
370 buflen = max(va.va_blocksize, nbytes);
| 372 off = fp->f_offset; 373 blockoff = off % va.va_blocksize; 374 buflen = max(va.va_blocksize, (nbytes + blockoff));
|
371 buf = malloc(buflen, M_TEMP, M_WAITOK); 372 VOP_LOCK(vp);
| 375 buf = malloc(buflen, M_TEMP, M_WAITOK); 376 VOP_LOCK(vp);
|
373 off = fp->f_offset;
| |
374again: 375 aiov.iov_base = buf; 376 aiov.iov_len = buflen; 377 auio.uio_iov = &aiov; 378 auio.uio_iovcnt = 1; 379 auio.uio_rw = UIO_READ; 380 auio.uio_segflg = UIO_SYSSPACE; 381 auio.uio_procp = p; 382 auio.uio_resid = buflen;
| 377again: 378 aiov.iov_base = buf; 379 aiov.iov_len = buflen; 380 auio.uio_iov = &aiov; 381 auio.uio_iovcnt = 1; 382 auio.uio_rw = UIO_READ; 383 auio.uio_segflg = UIO_SYSSPACE; 384 auio.uio_procp = p; 385 auio.uio_resid = buflen;
|
383 auio.uio_offset = off;
| 386 auio.uio_offset = off - (off_t)blockoff;
|
384 385 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0);
| 387 388 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0);
|
386 if (error)
| 389 if (error) {
|
387 goto out;
| 390 goto out;
|
| 391}
|
388 389 inp = buf;
| 392 393 inp = buf;
|
| 394 inp += blockoff;
|
390 outp = (caddr_t) args->dent; 391 resid = nbytes;
| 395 outp = (caddr_t) args->dent; 396 resid = nbytes;
|
392 if ((len = buflen - auio.uio_resid) == 0)
| 397 if ((len = buflen - auio.uio_resid - blockoff) == 0) {
|
393 goto eof;
| 398 goto eof;
|
| 399 }
|
394 395 while (len > 0) {
| 400 401 while (len > 0) {
|
396 reclen = ((struct dirent *) inp)->d_reclen; 397 if (reclen & 3) 398 panic("linux_readdir"); 399 off += reclen;
| |
400 bdp = (struct dirent *) inp;
| 402 bdp = (struct dirent *) inp;
|
| 403 reclen = bdp->d_reclen; 404 if (reclen & 3) { 405 printf("linux_readdir: reclen=%d\n", reclen); 406 error = EFAULT; 407 goto out; 408 } 409 410 off += reclen;
|
401 if (bdp->d_fileno == 0) { 402 inp += reclen;
| 411 if (bdp->d_fileno == 0) { 412 inp += reclen;
|
| 413 len -= reclen;
|
403 continue; 404 } 405 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 406 if (reclen > len || resid < linuxreclen) { 407 outp++; 408 break; 409 } 410 linux_dirent.dino = (long) bdp->d_fileno; 411 linux_dirent.doff = (linux_off_t) linuxreclen; 412 linux_dirent.dreclen = (u_short) bdp->d_namlen; 413 strcpy(linux_dirent.dname, bdp->d_name);
| 414 continue; 415 } 416 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 417 if (reclen > len || resid < linuxreclen) { 418 outp++; 419 break; 420 } 421 linux_dirent.dino = (long) bdp->d_fileno; 422 linux_dirent.doff = (linux_off_t) linuxreclen; 423 linux_dirent.dreclen = (u_short) bdp->d_namlen; 424 strcpy(linux_dirent.dname, bdp->d_name);
|
414 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen)))
| 425 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
|
415 goto out;
| 426 goto out;
|
| 427 }
|
416 inp += reclen; 417 outp += linuxreclen; 418 resid -= linuxreclen; 419 len -= reclen; 420 if (justone) 421 break; 422 } 423 424 if (outp == (caddr_t) args->dent) 425 goto again; 426 fp->f_offset = off; 427 428 if (justone) 429 nbytes = resid + linuxreclen;
| 428 inp += reclen; 429 outp += linuxreclen; 430 resid -= linuxreclen; 431 len -= reclen; 432 if (justone) 433 break; 434 } 435 436 if (outp == (caddr_t) args->dent) 437 goto again; 438 fp->f_offset = off; 439 440 if (justone) 441 nbytes = resid + linuxreclen;
|
| 442
|
430eof: 431 *retval = nbytes - resid; 432out: 433 VOP_UNLOCK(vp); 434 free(buf, M_TEMP); 435 return error; 436}
| 443eof: 444 *retval = nbytes - resid; 445out: 446 VOP_UNLOCK(vp); 447 free(buf, M_TEMP); 448 return error; 449}
|