linux_file.c revision 63285
177218Sphk/*- 277218Sphk * Copyright (c) 1994-1995 S�ren Schmidt 377218Sphk * All rights reserved. 477218Sphk * 577218Sphk * Redistribution and use in source and binary forms, with or without 677218Sphk * modification, are permitted provided that the following conditions 777218Sphk * are met: 877218Sphk * 1. Redistributions of source code must retain the above copyright 977218Sphk * notice, this list of conditions and the following disclaimer 1077218Sphk * in this position and unchanged. 1177218Sphk * 2. Redistributions in binary form must reproduce the above copyright 1291454Sbrooks * notice, this list of conditions and the following disclaimer in the 1391454Sbrooks * documentation and/or other materials provided with the distribution. 1477218Sphk * 3. The name of the author may not be used to endorse or promote products 1577218Sphk * derived from this software withough specific prior written permission 1677218Sphk * 1777218Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1877218Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1977218Sphk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2077218Sphk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2177218Sphk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2277218Sphk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2377218Sphk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2477218Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2577218Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2677218Sphk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2777218Sphk * 2877218Sphk * $FreeBSD: head/sys/compat/linux/linux_file.c 63285 2000-07-17 00:17:07Z marcel $ 2977218Sphk */ 3077218Sphk 3177218Sphk#include "opt_compat.h" 3277218Sphk 3377218Sphk#include <sys/param.h> 3477218Sphk#include <sys/systm.h> 3577218Sphk#include <sys/sysproto.h> 3677218Sphk#include <sys/fcntl.h> 3777218Sphk#include <sys/file.h> 3877218Sphk#include <sys/filedesc.h> 3977218Sphk#include <sys/lock.h> 4077218Sphk#include <sys/proc.h> 4177218Sphk#include <sys/vnode.h> 4277218Sphk#include <sys/malloc.h> 4377218Sphk#include <sys/dirent.h> 4477218Sphk#include <sys/conf.h> 4577218Sphk#include <sys/tty.h> 4677218Sphk 4777218Sphk#include <i386/linux/linux.h> 4877218Sphk#include <i386/linux/linux_proto.h> 4977218Sphk#include <i386/linux/linux_util.h> 5077218Sphk 5177218Sphkint 5277218Sphklinux_creat(struct proc *p, struct linux_creat_args *args) 5377218Sphk{ 5477218Sphk struct open_args /* { 5577218Sphk char *path; 5677218Sphk int flags; 5777218Sphk int mode; 5877218Sphk } */ bsd_open_args; 5977218Sphk caddr_t sg; 6077218Sphk 6177218Sphk sg = stackgap_init(); 6277218Sphk CHECKALTCREAT(p, &sg, args->path); 6377218Sphk 6477218Sphk#ifdef DEBUG 6577218Sphk printf("Linux-emul(%d): creat(%s, %d)\n", 6677218Sphk p->p_pid, args->path, args->mode); 6777218Sphk#endif 6877218Sphk bsd_open_args.path = args->path; 6977218Sphk bsd_open_args.mode = args->mode; 70138593Ssam bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 7177218Sphk return open(p, &bsd_open_args); 72138593Ssam} 73116957Ssam 74190456Ssamint 75190456Ssamlinux_open(struct proc *p, struct linux_open_args *args) 76190456Ssam{ 77195618Srpaulo struct open_args /* { 7877218Sphk char *path; 79187801Ssam int flags; 8077218Sphk int mode; 8177218Sphk } */ bsd_open_args; 8277218Sphk int error; 8377218Sphk caddr_t sg; 84146873Sjhb 8577218Sphk sg = stackgap_init(); 8677218Sphk 8777218Sphk if (args->flags & LINUX_O_CREAT) 8877218Sphk CHECKALTCREAT(p, &sg, args->path); 89155931Ssam else 90173275Ssam CHECKALTEXIST(p, &sg, args->path); 9177218Sphk 9277218Sphk#ifdef DEBUG 93178354Ssam printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n", 9477218Sphk p->p_pid, args->path, args->flags, args->mode); 95178354Ssam#endif 96178354Ssam bsd_open_args.flags = 0; 97178354Ssam if (args->flags & LINUX_O_RDONLY) 98178354Ssam bsd_open_args.flags |= O_RDONLY; 99178354Ssam if (args->flags & LINUX_O_WRONLY) 100178354Ssam bsd_open_args.flags |= O_WRONLY; 101194136Ssam if (args->flags & LINUX_O_RDWR) 102194136Ssam bsd_open_args.flags |= O_RDWR; 103194136Ssam if (args->flags & LINUX_O_NDELAY) 104194136Ssam bsd_open_args.flags |= O_NONBLOCK; 105194136Ssam if (args->flags & LINUX_O_APPEND) 106194136Ssam bsd_open_args.flags |= O_APPEND; 107194136Ssam if (args->flags & LINUX_O_SYNC) 108194136Ssam bsd_open_args.flags |= O_FSYNC; 109194136Ssam if (args->flags & LINUX_O_NONBLOCK) 110194136Ssam bsd_open_args.flags |= O_NONBLOCK; 111194136Ssam if (args->flags & LINUX_FASYNC) 112194136Ssam bsd_open_args.flags |= O_ASYNC; 113194136Ssam if (args->flags & LINUX_O_CREAT) 114194136Ssam bsd_open_args.flags |= O_CREAT; 115194136Ssam if (args->flags & LINUX_O_TRUNC) 116194136Ssam bsd_open_args.flags |= O_TRUNC; 117194136Ssam if (args->flags & LINUX_O_EXCL) 118194136Ssam bsd_open_args.flags |= O_EXCL; 119194136Ssam if (args->flags & LINUX_O_NOCTTY) 120178354Ssam bsd_open_args.flags |= O_NOCTTY; 121178354Ssam bsd_open_args.path = args->path; 122187801Ssam bsd_open_args.mode = args->mode; 123187801Ssam 124173275Ssam error = open(p, &bsd_open_args); 125173275Ssam if (!error && !(bsd_open_args.flags & O_NOCTTY) && 126173275Ssam SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 127173275Ssam struct filedesc *fdp = p->p_fd; 128173275Ssam struct file *fp = fdp->fd_ofiles[p->p_retval[0]]; 129173275Ssam 130173275Ssam if (fp->f_type == DTYPE_VNODE) 131173275Ssam fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, p); 132188784Ssam } 133188784Ssam#ifdef DEBUG 134188784Ssam printf("Linux-emul(%d): open returns error %d\n", 135188784Ssam p->p_pid, error); 136188784Ssam#endif 137188784Ssam return error; 138188784Ssam} 139188784Ssam 140188784Ssamstruct linux_flock { 141188784Ssam short l_type; 142188784Ssam short l_whence; 143188784Ssam linux_off_t l_start; 144188784Ssam linux_off_t l_len; 145173275Ssam linux_pid_t l_pid; 146173275Ssam}; 147178354Ssam 148173275Ssamstatic void 149173275Ssamlinux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) 150173275Ssam{ 15177218Sphk switch (linux_flock->l_type) { 15277218Sphk case LINUX_F_RDLCK: 15377218Sphk bsd_flock->l_type = F_RDLCK; 154178354Ssam break; 155178354Ssam case LINUX_F_WRLCK: 156178354Ssam bsd_flock->l_type = F_WRLCK; 157178354Ssam break; 158178354Ssam case LINUX_F_UNLCK: 159195618Srpaulo bsd_flock->l_type = F_UNLCK; 16077218Sphk break; 161187801Ssam default: 162178354Ssam bsd_flock->l_type = -1; 163178354Ssam break; 164178354Ssam } 165178354Ssam bsd_flock->l_whence = linux_flock->l_whence; 166178354Ssam bsd_flock->l_start = (off_t)linux_flock->l_start; 167178354Ssam bsd_flock->l_len = (off_t)linux_flock->l_len; 168173275Ssam bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 169173275Ssam} 170178354Ssam 171173275Ssamstatic void 172173275Ssambsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) 173170531Ssam{ 174173275Ssam switch (bsd_flock->l_type) { 175173275Ssam case F_RDLCK: 176173275Ssam linux_flock->l_type = LINUX_F_RDLCK; 177173275Ssam break; 178173275Ssam case F_WRLCK: 179173275Ssam linux_flock->l_type = LINUX_F_WRLCK; 180173275Ssam break; 181173275Ssam case F_UNLCK: 182173275Ssam linux_flock->l_type = LINUX_F_UNLCK; 183173275Ssam break; 184170531Ssam } 185170531Ssam linux_flock->l_whence = bsd_flock->l_whence; 186170531Ssam linux_flock->l_start = (linux_off_t)bsd_flock->l_start; 187170531Ssam linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 188170531Ssam linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; 189170531Ssam} 190170531Ssam 191187801Ssamint 192170531Ssamlinux_fcntl(struct proc *p, struct linux_fcntl_args *args) 193187801Ssam{ 194187801Ssam int error, result; 195187801Ssam struct fcntl_args /* { 196187801Ssam int fd; 197187801Ssam int cmd; 198187801Ssam int arg; 199170531Ssam } */ fcntl_args; 200173275Ssam struct linux_flock linux_flock; 201170531Ssam struct flock *bsd_flock; 202170531Ssam caddr_t sg; 203178354Ssam 204178354Ssam sg = stackgap_init(); 205178354Ssam bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock)); 206178354Ssam 207178354Ssam#ifdef DEBUG 208178354Ssam printf("Linux-emul(%d): fcntl(%d, %08x, *)\n", 209178354Ssam p->p_pid, args->fd, args->cmd); 210181198Ssam#endif 211178354Ssam fcntl_args.fd = args->fd; 212178354Ssam 213178354Ssam switch (args->cmd) { 214178354Ssam case LINUX_F_DUPFD: 215170531Ssam fcntl_args.cmd = F_DUPFD; 216170531Ssam fcntl_args.arg = args->arg; 217170531Ssam return fcntl(p, &fcntl_args); 218170531Ssam 219170531Ssam case LINUX_F_GETFD: 220170531Ssam fcntl_args.cmd = F_GETFD; 221170531Ssam return fcntl(p, &fcntl_args); 222138593Ssam 223170531Ssam case LINUX_F_SETFD: 224170531Ssam fcntl_args.cmd = F_SETFD; 225187801Ssam fcntl_args.arg = args->arg; 226170531Ssam return fcntl(p, &fcntl_args); 227170531Ssam 228170531Ssam case LINUX_F_GETFL: 229170531Ssam fcntl_args.cmd = F_GETFL; 230170531Ssam error = fcntl(p, &fcntl_args); 231187801Ssam result = p->p_retval[0]; 232187801Ssam p->p_retval[0] = 0; 233187801Ssam if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY; 234170531Ssam if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY; 235170531Ssam if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR; 236187801Ssam if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK; 237187801Ssam if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND; 238170531Ssam if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC; 239170531Ssam if (result & O_ASYNC) p->p_retval[0] |= LINUX_FASYNC; 240170531Ssam return error; 241170531Ssam 242170531Ssam case LINUX_F_SETFL: 243170531Ssam fcntl_args.arg = 0; 244170531Ssam if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; 245170531Ssam if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; 246170531Ssam if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; 247170531Ssam if (args->arg & LINUX_FASYNC) fcntl_args.arg |= O_ASYNC; 248170531Ssam fcntl_args.cmd = F_SETFL; 249170531Ssam return fcntl(p, &fcntl_args); 250170531Ssam 251170531Ssam case LINUX_F_GETLK: 252170531Ssam if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 253170531Ssam sizeof(struct linux_flock)))) 254170531Ssam return error; 255170531Ssam linux_to_bsd_flock(&linux_flock, bsd_flock); 256170531Ssam fcntl_args.cmd = F_GETLK; 257170531Ssam fcntl_args.arg = (int)bsd_flock; 258170531Ssam error = fcntl(p, &fcntl_args); 259170531Ssam if (error) 260170531Ssam return error; 261170531Ssam bsd_to_linux_flock(bsd_flock, &linux_flock); 262170531Ssam return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, 263170531Ssam sizeof(struct linux_flock)); 264170531Ssam 265170531Ssam case LINUX_F_SETLK: 266170531Ssam if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 267170531Ssam sizeof(struct linux_flock)))) 268170531Ssam return error; 269170531Ssam linux_to_bsd_flock(&linux_flock, bsd_flock); 270170531Ssam fcntl_args.cmd = F_SETLK; 271170531Ssam fcntl_args.arg = (int)bsd_flock; 272170531Ssam return fcntl(p, &fcntl_args); 273170531Ssam 274170531Ssam case LINUX_F_SETLKW: 275170531Ssam if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 276170531Ssam sizeof(struct linux_flock)))) 277170531Ssam return error; 278170531Ssam linux_to_bsd_flock(&linux_flock, bsd_flock); 279173275Ssam fcntl_args.cmd = F_SETLKW; 280170531Ssam fcntl_args.arg = (int)bsd_flock; 281170531Ssam return fcntl(p, &fcntl_args); 282173275Ssam 283173275Ssam case LINUX_F_GETOWN: 284173275Ssam fcntl_args.cmd = F_GETOWN; 285173275Ssam return fcntl(p, &fcntl_args); 286173275Ssam 287173275Ssam case LINUX_F_SETOWN: 288170531Ssam fcntl_args.cmd = F_SETOWN; 289173275Ssam fcntl_args.arg = args->arg; 290170531Ssam return fcntl(p, &fcntl_args); 291170531Ssam } 292173275Ssam return EINVAL; 293173275Ssam} 294173275Ssam 295173275Ssamint 296173275Ssamlinux_lseek(struct proc *p, struct linux_lseek_args *args) 297173275Ssam{ 298170531Ssam 299170531Ssam struct lseek_args /* { 300170531Ssam int fd; 301170531Ssam int pad; 302170531Ssam off_t offset; 303170531Ssam int whence; 304170531Ssam } */ tmp_args; 305170531Ssam int error; 306170531Ssam 307187801Ssam#ifdef DEBUG 308187801Ssam printf("Linux-emul(%ld): lseek(%d, %ld, %d)\n", 309170531Ssam (long)p->p_pid, args->fdes, args->off, args->whence); 310170531Ssam#endif 311170531Ssam tmp_args.fd = args->fdes; 312170531Ssam tmp_args.offset = (off_t)args->off; 313187801Ssam tmp_args.whence = args->whence; 314170531Ssam error = lseek(p, &tmp_args); 315170531Ssam return error; 316170531Ssam} 317170531Ssam 318170531Ssamint 319170531Ssamlinux_llseek(struct proc *p, struct linux_llseek_args *args) 320170531Ssam{ 321170531Ssam struct lseek_args bsd_args; 322170531Ssam int error; 323170531Ssam off_t off; 324170531Ssam 325170531Ssam#ifdef DEBUG 326170531Ssam printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n", 327187801Ssam p->p_pid, args->fd, args->ohigh, args->olow, args->whence); 328187801Ssam#endif 329170531Ssam off = (args->olow) | (((off_t) args->ohigh) << 32); 330170531Ssam 331170531Ssam bsd_args.fd = args->fd; 332170531Ssam bsd_args.offset = off; 333187801Ssam bsd_args.whence = args->whence; 334170531Ssam 335170531Ssam if ((error = lseek(p, &bsd_args))) 336170531Ssam return error; 337170531Ssam 338170531Ssam if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t)))) 339173275Ssam return error; 340170531Ssam 341170531Ssam p->p_retval[0] = 0; 342173275Ssam return 0; 343173275Ssam} 344173275Ssam 345173275Ssam 346173275Ssamstruct linux_dirent { 347173275Ssam long dino; 348173275Ssam linux_off_t doff; 349173275Ssam unsigned short dreclen; 350173275Ssam char dname[LINUX_NAME_MAX + 1]; 351187801Ssam}; 352173275Ssam 353173275Ssam#define LINUX_RECLEN(de,namlen) \ 354173275Ssam ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) 355173275Ssam 356173275Ssamint 357173275Ssamlinux_readdir(struct proc *p, struct linux_readdir_args *args) 358173275Ssam{ 359178354Ssam struct linux_getdents_args lda; 360178354Ssam 361178354Ssam lda.fd = args->fd; 362178354Ssam lda.dent = args->dent; 363178354Ssam lda.count = 1; 364178354Ssam return linux_getdents(p, &lda); 365178354Ssam} 366178354Ssam 367178354Ssamint 368178354Ssamlinux_getdents(struct proc *p, struct linux_getdents_args *args) 369178354Ssam{ 370178354Ssam register struct dirent *bdp; 371178354Ssam struct vnode *vp; 372178354Ssam caddr_t inp, buf; /* BSD-format */ 373178354Ssam int len, reclen; /* BSD-format */ 374188784Ssam caddr_t outp; /* Linux-format */ 375188784Ssam int resid, linuxreclen=0; /* Linux-format */ 376188784Ssam struct file *fp; 377188784Ssam struct uio auio; 378178354Ssam struct iovec aiov; 379178354Ssam struct vattr va; 380178354Ssam off_t off; 381178354Ssam struct linux_dirent linux_dirent; 382178354Ssam int buflen, error, eofflag, nbytes, justone; 383178354Ssam u_long *cookies = NULL, *cookiep; 384178354Ssam int ncookies; 385178354Ssam 386178354Ssam#ifdef DEBUG 387178354Ssam printf("Linux-emul(%d): getdents(%d, *, %d)\n", 388178354Ssam p->p_pid, args->fd, args->count); 389178354Ssam#endif 390178354Ssam if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) { 391178354Ssam return (error); 392178354Ssam } 393178354Ssam 394187801Ssam if ((fp->f_flag & FREAD) == 0) 395178354Ssam return (EBADF); 396178354Ssam 397178354Ssam vp = (struct vnode *) fp->f_data; 398178354Ssam 399178354Ssam if (vp->v_type != VDIR) 400178354Ssam return (EINVAL); 401178354Ssam 402178354Ssam if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { 403178354Ssam return error; 404178354Ssam } 405178354Ssam 406178354Ssam nbytes = args->count; 407178354Ssam if (nbytes == 1) { 408178354Ssam nbytes = sizeof (struct linux_dirent); 409178354Ssam justone = 1; 410178354Ssam } 411178354Ssam else 412187801Ssam justone = 0; 413178354Ssam 414178354Ssam off = fp->f_offset; 415178354Ssam#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 416178354Ssam buflen = max(DIRBLKSIZ, nbytes); 417178354Ssam buflen = min(buflen, MAXBSIZE); 418178354Ssam buf = malloc(buflen, M_TEMP, M_WAITOK); 419178354Ssam vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 420178354Ssamagain: 421178354Ssam aiov.iov_base = buf; 422178354Ssam aiov.iov_len = buflen; 423178354Ssam auio.uio_iov = &aiov; 424178354Ssam auio.uio_iovcnt = 1; 425178354Ssam auio.uio_rw = UIO_READ; 426178354Ssam auio.uio_segflg = UIO_SYSSPACE; 427178354Ssam auio.uio_procp = p; 428178354Ssam auio.uio_resid = buflen; 429178354Ssam auio.uio_offset = off; 430187801Ssam 431178354Ssam if (cookies) { 432178354Ssam free(cookies, M_TEMP); 433178354Ssam cookies = NULL; 434178354Ssam } 435178354Ssam 436178354Ssam error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies); 437187801Ssam if (error) { 438187801Ssam goto out; 439187801Ssam } 440178354Ssam 441178354Ssam inp = buf; 442178354Ssam outp = (caddr_t) args->dent; 443178354Ssam resid = nbytes; 444178354Ssam if ((len = buflen - auio.uio_resid) <= 0) { 445187801Ssam goto eof; 446178354Ssam } 447187801Ssam 448178354Ssam cookiep = cookies; 449178354Ssam 450186102Ssam if (cookies) { 451178354Ssam /* 452178354Ssam * When using cookies, the vfs has the option of reading from 453178354Ssam * a different offset than that supplied (UFS truncates the 454178354Ssam * offset to a block boundary to make sure that it never reads 455178354Ssam * partway through a directory entry, even if the directory 456178354Ssam * has been compacted). 457178354Ssam */ 458178354Ssam while (len > 0 && ncookies > 0 && *cookiep <= off) { 459178354Ssam bdp = (struct dirent *) inp; 460178354Ssam len -= bdp->d_reclen; 461178354Ssam inp += bdp->d_reclen; 462178354Ssam cookiep++; 463178354Ssam ncookies--; 464178354Ssam } 465178354Ssam } 466178354Ssam 467178354Ssam while (len > 0) { 468178354Ssam if (cookiep && ncookies == 0) 469178354Ssam break; 470178354Ssam bdp = (struct dirent *) inp; 471178354Ssam reclen = bdp->d_reclen; 472178354Ssam if (reclen & 3) { 473178354Ssam printf("linux_readdir: reclen=%d\n", reclen); 474178354Ssam error = EFAULT; 475178354Ssam goto out; 476178354Ssam } 477178354Ssam 478178354Ssam if (bdp->d_fileno == 0) { 479178354Ssam inp += reclen; 480178354Ssam if (cookiep) { 481186102Ssam off = *cookiep++; 482178354Ssam ncookies--; 483178354Ssam } else 484178354Ssam off += reclen; 485178354Ssam len -= reclen; 486178354Ssam continue; 487178354Ssam } 488178354Ssam linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 489178354Ssam if (reclen > len || resid < linuxreclen) { 490178354Ssam outp++; 491178354Ssam break; 492178354Ssam } 493187801Ssam linux_dirent.dino = (long) bdp->d_fileno; 494187801Ssam if (justone) { 495187801Ssam /* 496187801Ssam * old linux-style readdir usage. 497187801Ssam */ 498178354Ssam linux_dirent.doff = (linux_off_t) linuxreclen; 499178354Ssam linux_dirent.dreclen = (u_short) bdp->d_namlen; 500187801Ssam } else { 501187801Ssam linux_dirent.doff = (linux_off_t)(off + reclen); 502187801Ssam linux_dirent.dreclen = (u_short) linuxreclen; 503187801Ssam } 504187801Ssam strcpy(linux_dirent.dname, bdp->d_name); 505187801Ssam if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { 506178354Ssam goto out; 507178354Ssam } 508187801Ssam inp += reclen; 509187801Ssam if (cookiep) { 510187801Ssam off = *cookiep++; 511187801Ssam ncookies--; 512187801Ssam } else 513178354Ssam off += reclen; 514178354Ssam outp += linuxreclen; 515178354Ssam resid -= linuxreclen; 516178354Ssam len -= reclen; 517187801Ssam if (justone) 518187801Ssam break; 519187801Ssam } 520187801Ssam 521187801Ssam if (outp == (caddr_t) args->dent) 522187801Ssam goto again; 523187801Ssam fp->f_offset = off; 524187801Ssam 525187801Ssam if (justone) 526178354Ssam nbytes = resid + linuxreclen; 527187801Ssam 528178354Ssameof: 529187801Ssam p->p_retval[0] = nbytes - resid; 530187801Ssamout: 531187801Ssam if (cookies) 532187801Ssam free(cookies, M_TEMP); 533178354Ssam VOP_UNLOCK(vp, 0, p); 534178354Ssam free(buf, M_TEMP); 535170531Ssam return error; 536170531Ssam} 537170531Ssam 538170531Ssam/* 539170531Ssam * These exist mainly for hooks for doing /compat/linux translation. 540170531Ssam */ 541170531Ssam 542170531Ssamint 543170531Ssamlinux_access(struct proc *p, struct linux_access_args *args) 544138593Ssam{ 545138593Ssam struct access_args bsd; 546173275Ssam caddr_t sg; 547173275Ssam 548138593Ssam sg = stackgap_init(); 549138593Ssam CHECKALTEXIST(p, &sg, args->path); 550138593Ssam 55177218Sphk#ifdef DEBUG 55277218Sphk printf("Linux-emul(%d): access(%s, %d)\n", 55377218Sphk p->p_pid, args->path, args->flags); 55477218Sphk#endif 555151883Sbrooks bsd.path = args->path; 55677218Sphk bsd.flags = args->flags; 55777218Sphk 558121827Sbrooks return access(p, &bsd); 559178354Ssam} 56088748Sambrisko 56188748Sambriskoint 56288748Sambriskolinux_unlink(struct proc *p, struct linux_unlink_args *args) 56377218Sphk{ 56477218Sphk struct unlink_args bsd; 56577218Sphk caddr_t sg; 566151883Sbrooks 567151883Sbrooks sg = stackgap_init(); 56877218Sphk CHECKALTEXIST(p, &sg, args->path); 56977218Sphk 57077218Sphk#ifdef DEBUG 57177218Sphk printf("Linux-emul(%d): unlink(%s)\n", 572138593Ssam p->p_pid, args->path); 573195618Srpaulo#endif 574195618Srpaulo bsd.path = args->path; 575195618Srpaulo 576195618Srpaulo return unlink(p, &bsd); 577195618Srpaulo} 578195618Srpaulo 579195618Srpauloint 580195618Srpaulolinux_chdir(struct proc *p, struct linux_chdir_args *args) 581195618Srpaulo{ 582195618Srpaulo struct chdir_args bsd; 583195618Srpaulo caddr_t sg; 584195618Srpaulo 585195618Srpaulo sg = stackgap_init(); 586195618Srpaulo CHECKALTEXIST(p, &sg, args->path); 58777218Sphk 58877218Sphk#ifdef DEBUG 58977218Sphk printf("Linux-emul(%d): chdir(%s)\n", 59077218Sphk p->p_pid, args->path); 59177218Sphk#endif 59277218Sphk bsd.path = args->path; 59377218Sphk 59477218Sphk return chdir(p, &bsd); 59577218Sphk} 59677218Sphk 59777218Sphkint 59877218Sphklinux_chmod(struct proc *p, struct linux_chmod_args *args) 599138593Ssam{ 600170531Ssam struct chmod_args bsd; 601170531Ssam caddr_t sg; 602170531Ssam 603170531Ssam sg = stackgap_init(); 604170531Ssam CHECKALTEXIST(p, &sg, args->path); 605170531Ssam 606170531Ssam#ifdef DEBUG 607170531Ssam printf("Linux-emul(%d): chmod(%s, %d)\n", 608170531Ssam p->p_pid, args->path, args->mode); 609170531Ssam#endif 610170531Ssam bsd.path = args->path; 611170531Ssam bsd.mode = args->mode; 612173275Ssam 613138593Ssam return chmod(p, &bsd); 614170531Ssam} 615170531Ssam 616170531Ssamint 617138593Ssamlinux_chown(struct proc *p, struct linux_chown_args *args) 618170531Ssam{ 619166015Ssam struct chown_args bsd; 620170531Ssam caddr_t sg; 621170531Ssam 622170531Ssam sg = stackgap_init(); 623170531Ssam CHECKALTEXIST(p, &sg, args->path); 624170531Ssam 625170531Ssam#ifdef DEBUG 626170531Ssam printf("Linux-emul(%d): chown(%s, %d, %d)\n", 627170531Ssam p->p_pid, args->path, args->uid, args->gid); 628170531Ssam#endif 629170531Ssam bsd.path = args->path; 630170531Ssam /* XXX size casts here */ 631170531Ssam bsd.uid = args->uid; 632170531Ssam bsd.gid = args->gid; 633170531Ssam 634170531Ssam return chown(p, &bsd); 635170531Ssam} 636170531Ssam 637170531Ssamint 638170531Ssamlinux_lchown(struct proc *p, struct linux_lchown_args *args) 639170531Ssam{ 640170531Ssam struct lchown_args bsd; 641170531Ssam caddr_t sg; 642170531Ssam 643170531Ssam sg = stackgap_init(); 644170531Ssam CHECKALTEXIST(p, &sg, args->path); 645170531Ssam 646170531Ssam#ifdef DEBUG 647170531Ssam printf("Linux-emul(%d): lchown(%s, %d, %d)\n", 648170531Ssam p->p_pid, args->path, args->uid, args->gid); 649170531Ssam#endif 650170531Ssam bsd.path = args->path; 651170531Ssam /* XXX size casts here */ 652170531Ssam bsd.uid = args->uid; 653173275Ssam bsd.gid = args->gid; 654170531Ssam 655170531Ssam return lchown(p, &bsd); 656170531Ssam} 657170531Ssam 658170531Ssamint 659170531Ssamlinux_mkdir(struct proc *p, struct linux_mkdir_args *args) 660170531Ssam{ 661170531Ssam struct mkdir_args bsd; 662166015Ssam caddr_t sg; 663170531Ssam 664170531Ssam sg = stackgap_init(); 665170531Ssam CHECKALTCREAT(p, &sg, args->path); 666170531Ssam 667170531Ssam#ifdef DEBUG 668170531Ssam printf("Linux-emul(%d): mkdir(%s, %d)\n", 669170531Ssam p->p_pid, args->path, args->mode); 670170531Ssam#endif 671170531Ssam bsd.path = args->path; 672170531Ssam bsd.mode = args->mode; 673170531Ssam 674170531Ssam return mkdir(p, &bsd); 675170531Ssam} 676170531Ssam 677170531Ssamint 678170531Ssamlinux_rmdir(struct proc *p, struct linux_rmdir_args *args) 679170531Ssam{ 680170531Ssam struct rmdir_args bsd; 681173275Ssam caddr_t sg; 682170531Ssam 683165570Ssam sg = stackgap_init(); 684170531Ssam CHECKALTEXIST(p, &sg, args->path); 685170531Ssam 686170531Ssam#ifdef DEBUG 687170531Ssam printf("Linux-emul(%d): rmdir(%s)\n", 688170531Ssam p->p_pid, args->path); 689170531Ssam#endif 690170531Ssam bsd.path = args->path; 691170531Ssam 692170531Ssam return rmdir(p, &bsd); 693170531Ssam} 694170531Ssam 695170531Ssamint 696170531Ssamlinux_rename(struct proc *p, struct linux_rename_args *args) 697170531Ssam{ 698170531Ssam struct rename_args bsd; 699170531Ssam caddr_t sg; 700170531Ssam 701170531Ssam sg = stackgap_init(); 702170531Ssam CHECKALTEXIST(p, &sg, args->from); 703173275Ssam CHECKALTCREAT(p, &sg, args->to); 704173275Ssam 705173275Ssam#ifdef DEBUG 706173275Ssam printf("Linux-emul(%d): rename(%s, %s)\n", 707173275Ssam p->p_pid, args->from, args->to); 708173275Ssam#endif 709173275Ssam bsd.from = args->from; 710173275Ssam bsd.to = args->to; 711173275Ssam 712173275Ssam return rename(p, &bsd); 713173275Ssam} 714173275Ssam 715170531Ssamint 716170531Ssamlinux_symlink(struct proc *p, struct linux_symlink_args *args) 717170531Ssam{ 718138593Ssam struct symlink_args bsd; 719138593Ssam caddr_t sg; 720138593Ssam 721186105Ssam sg = stackgap_init(); 722186105Ssam CHECKALTEXIST(p, &sg, args->path); 723186105Ssam CHECKALTCREAT(p, &sg, args->to); 724186105Ssam 725186105Ssam#ifdef DEBUG 726186105Ssam printf("Linux-emul(%d): symlink(%s, %s)\n", 727186105Ssam p->p_pid, args->path, args->to); 728186105Ssam#endif 729186105Ssam bsd.path = args->path; 730186105Ssam bsd.link = args->to; 731186105Ssam 732186105Ssam return symlink(p, &bsd); 733186105Ssam} 734186105Ssam 735186105Ssamint 736186105Ssamlinux_execve(struct proc *p, struct linux_execve_args *args) 737186105Ssam{ 738186105Ssam struct execve_args bsd; 739186105Ssam caddr_t sg; 740186105Ssam 741186105Ssam sg = stackgap_init(); 742186105Ssam CHECKALTEXIST(p, &sg, args->path); 743186105Ssam 744186105Ssam#ifdef DEBUG 745186105Ssam printf("Linux-emul(%d): execve(%s)\n", 746186105Ssam p->p_pid, args->path); 747186105Ssam#endif 74877218Sphk bsd.fname = args->path; 74977218Sphk bsd.argv = args->argp; 750170531Ssam bsd.envv = args->envp; 751170531Ssam 752186105Ssam return execve(p, &bsd); 753170531Ssam} 75477218Sphk 75577218Sphkint 756138593Ssamlinux_readlink(struct proc *p, struct linux_readlink_args *args) 757178354Ssam{ 758178354Ssam struct readlink_args bsd; 759178354Ssam caddr_t sg; 760178354Ssam 761186105Ssam sg = stackgap_init(); 762178354Ssam CHECKALTEXIST(p, &sg, args->name); 763178354Ssam 764178354Ssam#ifdef DEBUG 765178354Ssam printf("Linux-emul(%ld): readlink(%s, %p, %d)\n", 766178354Ssam (long)p->p_pid, args->name, (void *)args->buf, args->count); 767178354Ssam#endif 76877218Sphk bsd.path = args->name; 76977218Sphk bsd.buf = args->buf; 77077218Sphk bsd.count = args->count; 77177218Sphk 77291454Sbrooks return readlink(p, &bsd); 77377218Sphk} 77491454Sbrooks 77577218Sphkint 77691454Sbrookslinux_truncate(struct proc *p, struct linux_truncate_args *args) 77777218Sphk{ 778138593Ssam struct truncate_args bsd; 779138593Ssam caddr_t sg; 780138593Ssam 781138593Ssam sg = stackgap_init(); 78277218Sphk CHECKALTEXIST(p, &sg, args->path); 783150708Sru 78477218Sphk#ifdef DEBUG 78577218Sphk printf("Linux-emul(%d): truncate(%s, %ld)\n", 78677218Sphk p->p_pid, args->path, args->length); 78777218Sphk#endif 78877218Sphk bsd.path = args->path; 789138593Ssam bsd.length = args->length; 79077218Sphk 79177218Sphk return truncate(p, &bsd); 79277218Sphk} 79377218Sphk 79491454Sbrooksint 79577218Sphklinux_link(struct proc *p, struct linux_link_args *args) 79691454Sbrooks{ 79777218Sphk struct link_args bsd; 79891454Sbrooks caddr_t sg; 79977218Sphk 80091454Sbrooks sg = stackgap_init(); 80177218Sphk CHECKALTEXIST(p, &sg, args->path); 80291454Sbrooks CHECKALTCREAT(p, &sg, args->to); 80377218Sphk 80477218Sphk#ifdef DEBUG 805150708Sru printf("Linux-emul(%d): link(%s, %s)\n", p->p_pid, args->path, args->to); 80677218Sphk#endif 80777218Sphk 80877218Sphk bsd.path = args->path; 80977218Sphk bsd.link = args->to; 81077218Sphk 811138593Ssam return link(p, &bsd); 81277218Sphk} 81377218Sphk 81477218Sphkint 81577218Sphklinux_getcwd(struct proc *p, struct linux_getcwd_args *args) 81677218Sphk{ 81777218Sphk struct __getcwd_args bsd; 81877218Sphk caddr_t sg; 81977218Sphk int error, len; 82077218Sphk 82177218Sphk#ifdef DEBUG 822138593Ssam printf("Linux-emul(%ld): getcwd(%p, %ld)\n", (long)p->p_pid, 82377218Sphk args->buf, args->bufsize); 82477218Sphk#endif 82577218Sphk 82677218Sphk sg = stackgap_init(); 82777218Sphk bsd.buf = stackgap_alloc(&sg, SPARE_USRSPACE); 828138593Ssam bsd.buflen = SPARE_USRSPACE; 82977218Sphk error = __getcwd(p, &bsd); 83077218Sphk if (!error) { 83177218Sphk len = strlen(bsd.buf) + 1; 83277218Sphk if (len <= args->bufsize) { 83391454Sbrooks p->p_retval[0] = len; 83477218Sphk error = copyout(bsd.buf, args->buf, len); 83591454Sbrooks } 83677218Sphk else 83791454Sbrooks error = ERANGE; 83877218Sphk } 83977218Sphk return (error); 840150708Sru} 84177218Sphk 84277218Sphkint 84377218Sphklinux_fdatasync(p, uap) 84477218Sphk struct proc *p; 84577218Sphk struct linux_fdatasync_args *uap; 846138593Ssam{ 84777218Sphk struct fsync_args bsd; 84877218Sphk 84977218Sphk bsd.fd = uap->fd; 85077218Sphk return fsync(p, &bsd); 85177218Sphk} 852139493Ssam 853139493Ssamint 854139493Ssamlinux_pread(p, uap) 855139493Ssam struct proc *p; 856139493Ssam struct linux_pread_args *uap; 857139493Ssam{ 858138593Ssam struct pread_args bsd; 85977218Sphk 86077218Sphk bsd.fd = uap->fd; 861139493Ssam bsd.buf = uap->buf; 862139493Ssam bsd.nbyte = uap->nbyte; 863139493Ssam bsd.offset = uap->offset; 864139493Ssam return pread(p, &bsd); 86577218Sphk} 86677218Sphk 867138593Ssamint 86877218Sphklinux_pwrite(p, uap) 86977218Sphk struct proc *p; 87077218Sphk struct linux_pwrite_args *uap; 87177218Sphk{ 872120178Ssam struct pwrite_args bsd; 87377218Sphk 874178354Ssam bsd.fd = uap->fd; 87577218Sphk bsd.buf = uap->buf; 87677218Sphk bsd.nbyte = uap->nbyte; 87777218Sphk bsd.offset = uap->offset; 87877218Sphk return pwrite(p, &bsd); 87977218Sphk} 88077218Sphk