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 * $FreeBSD$ 29 */ 30 31 #include "opt_compat.h" 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/sysproto.h> 36 #include <sys/fcntl.h> 37 #include <sys/file.h> 38 #include <sys/filedesc.h> 39 #include <sys/lock.h> 40 #include <sys/proc.h> 41 #include <sys/vnode.h> 42 #include <sys/malloc.h> 43 #include <sys/dirent.h> 44 #include <sys/conf.h> 45 #include <sys/tty.h> 46 47 #include <machine/../linux/linux.h> 48 #include <machine/../linux/linux_proto.h> 49 #include <compat/linux/linux_util.h> 50 51 #ifndef __alpha__ 52 int 53 linux_creat(struct proc *p, struct linux_creat_args *args) 54 { 55 struct open_args /* { 56 char *path; 57 int flags; 58 int mode; 59 } */ bsd_open_args; 60 caddr_t sg; 61 62 sg = stackgap_init(); 63 CHECKALTCREAT(p, &sg, args->path); 64 65 #ifdef DEBUG 66 printf("Linux-emul(%d): creat(%s, %d)\n", 67 p->p_pid, args->path, args->mode); 68 #endif 69 bsd_open_args.path = args->path; 70 bsd_open_args.mode = args->mode; 71 bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 72 return open(p, &bsd_open_args); 73 } 74 #endif /*!__alpha__*/ 75 76 int 77 linux_open(struct proc *p, struct linux_open_args *args) 78 { 79 struct open_args /* { 80 char *path; 81 int flags; 82 int mode; 83 } */ bsd_open_args; 84 int error; 85 caddr_t sg; 86 87 sg = stackgap_init(); 88 89 if (args->flags & LINUX_O_CREAT) 90 CHECKALTCREAT(p, &sg, args->path); 91 else 92 CHECKALTEXIST(p, &sg, args->path); 93 94 #ifdef DEBUG 95 printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n", 96 p->p_pid, args->path, args->flags, args->mode); 97 #endif 98 bsd_open_args.flags = 0; 99 if (args->flags & LINUX_O_RDONLY) 100 bsd_open_args.flags |= O_RDONLY; 101 if (args->flags & LINUX_O_WRONLY) 102 bsd_open_args.flags |= O_WRONLY; 103 if (args->flags & LINUX_O_RDWR) 104 bsd_open_args.flags |= O_RDWR; 105 if (args->flags & LINUX_O_NDELAY) 106 bsd_open_args.flags |= O_NONBLOCK; 107 if (args->flags & LINUX_O_APPEND) 108 bsd_open_args.flags |= O_APPEND; 109 if (args->flags & LINUX_O_SYNC) 110 bsd_open_args.flags |= O_FSYNC; 111 if (args->flags & LINUX_O_NONBLOCK) 112 bsd_open_args.flags |= O_NONBLOCK; 113 if (args->flags & LINUX_FASYNC) 114 bsd_open_args.flags |= O_ASYNC; 115 if (args->flags & LINUX_O_CREAT) 116 bsd_open_args.flags |= O_CREAT; 117 if (args->flags & LINUX_O_TRUNC) 118 bsd_open_args.flags |= O_TRUNC; 119 if (args->flags & LINUX_O_EXCL) 120 bsd_open_args.flags |= O_EXCL; 121 if (args->flags & LINUX_O_NOCTTY) 122 bsd_open_args.flags |= O_NOCTTY; 123 bsd_open_args.path = args->path; 124 bsd_open_args.mode = args->mode; 125 126 error = open(p, &bsd_open_args); 127 if (!error && !(bsd_open_args.flags & O_NOCTTY) && 128 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 129 struct filedesc *fdp = p->p_fd; 130 struct file *fp = fdp->fd_ofiles[p->p_retval[0]]; 131 132 if (fp->f_type == DTYPE_VNODE) 133 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, p); 134 } 135 #ifdef DEBUG 136 printf("Linux-emul(%d): open returns error %d\n", 137 p->p_pid, error); 138 #endif 139 return error; 140 } 141 142 struct linux_flock { 143 short l_type; 144 short l_whence; 145 linux_off_t l_start; 146 linux_off_t l_len; 147 linux_pid_t l_pid; 148 }; 149 150 static void 151 linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) 152 { 153 switch (linux_flock->l_type) { 154 case LINUX_F_RDLCK: 155 bsd_flock->l_type = F_RDLCK; 156 break; 157 case LINUX_F_WRLCK: 158 bsd_flock->l_type = F_WRLCK; 159 break; 160 case LINUX_F_UNLCK: 161 bsd_flock->l_type = F_UNLCK; 162 break; 163 default: 164 bsd_flock->l_type = -1; 165 break; 166 } 167 bsd_flock->l_whence = linux_flock->l_whence; 168 bsd_flock->l_start = (off_t)linux_flock->l_start; 169 bsd_flock->l_len = (off_t)linux_flock->l_len; 170 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 171 } 172 173 static void 174 bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) 175 { 176 switch (bsd_flock->l_type) { 177 case F_RDLCK: 178 linux_flock->l_type = LINUX_F_RDLCK; 179 break; 180 case F_WRLCK: 181 linux_flock->l_type = LINUX_F_WRLCK; 182 break; 183 case F_UNLCK: 184 linux_flock->l_type = LINUX_F_UNLCK; 185 break; 186 } 187 linux_flock->l_whence = bsd_flock->l_whence; 188 linux_flock->l_start = (linux_off_t)bsd_flock->l_start; 189 linux_flock->l_len = (linux_off_t)bsd_flock->l_len; 190 linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; 191 } 192 193 int 194 linux_fcntl(struct proc *p, struct linux_fcntl_args *args) 195 { 196 int error, result; 197 struct fcntl_args /* { 198 int fd; 199 int cmd; 200 long arg; 201 } */ fcntl_args; 202 struct linux_flock linux_flock; 203 struct flock *bsd_flock; 204 struct filedesc *fdp; 205 struct file *fp; 206 caddr_t sg; 207 208 sg = stackgap_init(); 209 bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock)); 210 211 #ifdef DEBUG 212 printf("Linux-emul(%ld): fcntl(%d, %08x, *)\n", (long)p->p_pid, 213 args->fd, args->cmd); 214 #endif 215 fcntl_args.fd = args->fd; 216 217 switch (args->cmd) { 218 case LINUX_F_DUPFD: 219 fcntl_args.cmd = F_DUPFD; 220 fcntl_args.arg = args->arg; 221 return fcntl(p, &fcntl_args); 222 223 case LINUX_F_GETFD: 224 fcntl_args.cmd = F_GETFD; 225 return fcntl(p, &fcntl_args); 226 227 case LINUX_F_SETFD: 228 fcntl_args.cmd = F_SETFD; 229 fcntl_args.arg = args->arg; 230 return fcntl(p, &fcntl_args); 231 232 case LINUX_F_GETFL: 233 fcntl_args.cmd = F_GETFL; 234 error = fcntl(p, &fcntl_args); 235 result = p->p_retval[0]; 236 p->p_retval[0] = 0; 237 if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY; 238 if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY; 239 if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR; 240 if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK; 241 if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND; 242 if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC; 243 if (result & O_ASYNC) p->p_retval[0] |= LINUX_FASYNC; 244 return error; 245 246 case LINUX_F_SETFL: 247 fcntl_args.arg = 0; 248 if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; 249 if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; 250 if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; 251 if (args->arg & LINUX_FASYNC) fcntl_args.arg |= O_ASYNC; 252 fcntl_args.cmd = F_SETFL; 253 return fcntl(p, &fcntl_args); 254 255 case LINUX_F_GETLK: 256 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 257 sizeof(struct linux_flock)))) 258 return error; 259 linux_to_bsd_flock(&linux_flock, bsd_flock); 260 fcntl_args.cmd = F_GETLK; 261 fcntl_args.arg = (long)bsd_flock; 262 error = fcntl(p, &fcntl_args); 263 if (error) 264 return error; 265 bsd_to_linux_flock(bsd_flock, &linux_flock); 266 return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, 267 sizeof(struct linux_flock)); 268 269 case LINUX_F_SETLK: 270 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 271 sizeof(struct linux_flock)))) 272 return error; 273 linux_to_bsd_flock(&linux_flock, bsd_flock); 274 fcntl_args.cmd = F_SETLK; 275 fcntl_args.arg = (long)bsd_flock; 276 return fcntl(p, &fcntl_args); 277 278 case LINUX_F_SETLKW: 279 if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, 280 sizeof(struct linux_flock)))) 281 return error; 282 linux_to_bsd_flock(&linux_flock, bsd_flock); 283 fcntl_args.cmd = F_SETLKW; 284 fcntl_args.arg = (long)bsd_flock; 285 return fcntl(p, &fcntl_args); 286 287 case LINUX_F_GETOWN: 288 fcntl_args.cmd = F_GETOWN; 289 return fcntl(p, &fcntl_args); 290 291 case LINUX_F_SETOWN: 292 /* 293 * XXX some Linux applications depend on F_SETOWN having no 294 * significant effect for pipes (SIGIO is not delivered for 295 * pipes under Linux-2.2.35 at least). 296 */ 297 fdp = p->p_fd; 298 if ((u_int)args->fd >= fdp->fd_nfiles || 299 (fp = fdp->fd_ofiles[args->fd]) == NULL) 300 return EBADF; 301 if (fp->f_type == DTYPE_PIPE) 302 return EINVAL; 303 304 fcntl_args.cmd = F_SETOWN; 305 fcntl_args.arg = args->arg; 306 return fcntl(p, &fcntl_args); 307 } 308 return EINVAL; 309 } 310 311 int 312 linux_lseek(struct proc *p, struct linux_lseek_args *args) 313 { 314 315 struct lseek_args /* { 316 int fd; 317 int pad; 318 off_t offset; 319 int whence; 320 } */ tmp_args; 321 int error; 322 323 #ifdef DEBUG 324 printf("Linux-emul(%ld): lseek(%d, %ld, %d)\n", 325 (long)p->p_pid, args->fdes, args->off, args->whence); 326 #endif 327 tmp_args.fd = args->fdes; 328 tmp_args.offset = (off_t)args->off; 329 tmp_args.whence = args->whence; 330 error = lseek(p, &tmp_args); 331 return error; 332 } 333 334 #ifndef __alpha__ 335 int 336 linux_llseek(struct proc *p, struct linux_llseek_args *args) 337 { 338 struct lseek_args bsd_args; 339 int error; 340 off_t off; 341 342 #ifdef DEBUG 343 printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n", 344 p->p_pid, args->fd, args->ohigh, args->olow, args->whence); 345 #endif 346 off = (args->olow) | (((off_t) args->ohigh) << 32); 347 348 bsd_args.fd = args->fd; 349 bsd_args.offset = off; 350 bsd_args.whence = args->whence; 351 352 if ((error = lseek(p, &bsd_args))) 353 return error; 354 355 if ((error = copyout(p->p_retval, (caddr_t)args->res, sizeof (off_t)))) 356 return error; 357 358 p->p_retval[0] = 0; 359 return 0; 360 } 361 #endif /*!__alpha__*/ 362 363 364 struct linux_dirent { 365 long dino; 366 linux_off_t doff; 367 unsigned short dreclen; 368 char dname[LINUX_NAME_MAX + 1]; 369 }; 370 371 #define LINUX_RECLEN(de,namlen) \ 372 ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) 373 374 #ifndef __alpha__ 375 int 376 linux_readdir(struct proc *p, struct linux_readdir_args *args) 377 { 378 struct linux_getdents_args lda; 379 380 lda.fd = args->fd; 381 lda.dent = args->dent; 382 lda.count = 1; 383 return linux_getdents(p, &lda); 384 } 385 #endif /*!__alpha__*/ 386 387 int 388 linux_getdents(struct proc *p, struct linux_getdents_args *args) 389 { 390 register struct dirent *bdp; 391 struct vnode *vp; 392 caddr_t inp, buf; /* BSD-format */ 393 int len, reclen; /* BSD-format */ 394 caddr_t outp; /* Linux-format */ 395 int resid, linuxreclen=0; /* Linux-format */ 396 struct file *fp; 397 struct uio auio; 398 struct iovec aiov; 399 struct vattr va; 400 off_t off; 401 struct linux_dirent linux_dirent; 402 int buflen, error, eofflag, nbytes, justone; 403 u_long *cookies = NULL, *cookiep; 404 int ncookies; 405 406 #ifdef DEBUG 407 printf("Linux-emul(%d): getdents(%d, *, %d)\n", 408 p->p_pid, args->fd, args->count); 409 #endif 410 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) { 411 return (error); 412 } 413 414 if ((fp->f_flag & FREAD) == 0) 415 return (EBADF); 416 417 vp = (struct vnode *) fp->f_data; 418 419 if (vp->v_type != VDIR) 420 return (EINVAL); 421 422 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { 423 return error; 424 } 425 426 nbytes = args->count; 427 if (nbytes == 1) { 428 nbytes = sizeof (struct linux_dirent); 429 justone = 1; 430 } 431 else 432 justone = 0; 433 434 off = fp->f_offset; 435 #define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 436 buflen = max(DIRBLKSIZ, nbytes); 437 buflen = min(buflen, MAXBSIZE); 438 buf = malloc(buflen, M_TEMP, M_WAITOK); 439 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 440 again: 441 aiov.iov_base = buf; 442 aiov.iov_len = buflen; 443 auio.uio_iov = &aiov; 444 auio.uio_iovcnt = 1; 445 auio.uio_rw = UIO_READ; 446 auio.uio_segflg = UIO_SYSSPACE; 447 auio.uio_procp = p; 448 auio.uio_resid = buflen; 449 auio.uio_offset = off; 450 451 if (cookies) { 452 free(cookies, M_TEMP); 453 cookies = NULL; 454 } 455 456 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies); 457 if (error) { 458 goto out; 459 } 460 461 inp = buf; 462 outp = (caddr_t) args->dent; 463 resid = nbytes; 464 if ((len = buflen - auio.uio_resid) <= 0) { 465 goto eof; 466 } 467 468 cookiep = cookies; 469 470 if (cookies) { 471 /* 472 * When using cookies, the vfs has the option of reading from 473 * a different offset than that supplied (UFS truncates the 474 * offset to a block boundary to make sure that it never reads 475 * partway through a directory entry, even if the directory 476 * has been compacted). 477 */ 478 while (len > 0 && ncookies > 0 && *cookiep <= off) { 479 bdp = (struct dirent *) inp; 480 len -= bdp->d_reclen; 481 inp += bdp->d_reclen; 482 cookiep++; 483 ncookies--; 484 } 485 } 486 487 while (len > 0) { 488 if (cookiep && ncookies == 0) 489 break; 490 bdp = (struct dirent *) inp; 491 reclen = bdp->d_reclen; 492 if (reclen & 3) { 493 printf("linux_readdir: reclen=%d\n", reclen); 494 error = EFAULT; 495 goto out; 496 } 497 498 if (bdp->d_fileno == 0) { 499 inp += reclen; 500 if (cookiep) { 501 off = *cookiep++; 502 ncookies--; 503 } else 504 off += reclen; 505 len -= reclen; 506 continue; 507 } 508 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 509 if (reclen > len || resid < linuxreclen) { 510 outp++; 511 break; 512 } 513 linux_dirent.dino = (long) bdp->d_fileno; 514 if (justone) { 515 /* 516 * old linux-style readdir usage. 517 */ 518 linux_dirent.doff = (linux_off_t) linuxreclen; 519 linux_dirent.dreclen = (u_short) bdp->d_namlen; 520 } else { 521 if (cookiep) 522 linux_dirent.doff = (linux_off_t)*cookiep; 523 else 524 linux_dirent.doff = (linux_off_t)(off + reclen); 525 linux_dirent.dreclen = (u_short) linuxreclen; 526 } 527 strcpy(linux_dirent.dname, bdp->d_name); 528 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { 529 goto out; 530 } 531 inp += reclen; 532 if (cookiep) { 533 off = *cookiep++; 534 ncookies--; 535 } else 536 off += reclen; 537 outp += linuxreclen; 538 resid -= linuxreclen; 539 len -= reclen; 540 if (justone) 541 break; 542 } 543 544 if (outp == (caddr_t) args->dent) 545 goto again; 546 fp->f_offset = off; 547 548 if (justone) 549 nbytes = resid + linuxreclen; 550 551 eof: 552 p->p_retval[0] = nbytes - resid; 553 out: 554 if (cookies) 555 free(cookies, M_TEMP); 556 VOP_UNLOCK(vp, 0, p); 557 free(buf, M_TEMP); 558 return error; 559 } 560 561 /* 562 * These exist mainly for hooks for doing /compat/linux translation. 563 */ 564 565 int 566 linux_access(struct proc *p, struct linux_access_args *args) 567 { 568 struct access_args bsd; 569 caddr_t sg; 570 571 sg = stackgap_init(); 572 CHECKALTEXIST(p, &sg, args->path); 573 574 #ifdef DEBUG 575 printf("Linux-emul(%d): access(%s, %d)\n", 576 p->p_pid, args->path, args->flags); 577 #endif 578 bsd.path = args->path; 579 bsd.flags = args->flags; 580 581 return access(p, &bsd); 582 } 583 584 int 585 linux_unlink(struct proc *p, struct linux_unlink_args *args) 586 { 587 struct unlink_args bsd; 588 caddr_t sg; 589 590 sg = stackgap_init(); 591 CHECKALTEXIST(p, &sg, args->path); 592 593 #ifdef DEBUG 594 printf("Linux-emul(%d): unlink(%s)\n", 595 p->p_pid, args->path); 596 #endif 597 bsd.path = args->path; 598 599 return unlink(p, &bsd); 600 } 601 602 int 603 linux_chdir(struct proc *p, struct linux_chdir_args *args) 604 { 605 struct chdir_args bsd; 606 caddr_t sg; 607 608 sg = stackgap_init(); 609 CHECKALTEXIST(p, &sg, args->path); 610 611 #ifdef DEBUG 612 printf("Linux-emul(%d): chdir(%s)\n", 613 p->p_pid, args->path); 614 #endif 615 bsd.path = args->path; 616 617 return chdir(p, &bsd); 618 } 619 620 int 621 linux_chmod(struct proc *p, struct linux_chmod_args *args) 622 { 623 struct chmod_args bsd; 624 caddr_t sg; 625 626 sg = stackgap_init(); 627 CHECKALTEXIST(p, &sg, args->path); 628 629 #ifdef DEBUG 630 printf("Linux-emul(%d): chmod(%s, %d)\n", 631 p->p_pid, args->path, args->mode); 632 #endif 633 bsd.path = args->path; 634 bsd.mode = args->mode; 635 636 return chmod(p, &bsd); 637 } 638 639 int 640 linux_chown(struct proc *p, struct linux_chown_args *args) 641 { 642 struct chown_args bsd; 643 caddr_t sg; 644 645 sg = stackgap_init(); 646 CHECKALTEXIST(p, &sg, args->path); 647 648 #ifdef DEBUG 649 printf("Linux-emul(%d): chown(%s, %d, %d)\n", 650 p->p_pid, args->path, args->uid, args->gid); 651 #endif 652 bsd.path = args->path; 653 /* XXX size casts here */ 654 bsd.uid = args->uid; 655 bsd.gid = args->gid; 656 657 return chown(p, &bsd); 658 } 659 660 int 661 linux_lchown(struct proc *p, struct linux_lchown_args *args) 662 { 663 struct lchown_args bsd; 664 caddr_t sg; 665 666 sg = stackgap_init(); 667 CHECKALTEXIST(p, &sg, args->path); 668 669 #ifdef DEBUG 670 printf("Linux-emul(%d): lchown(%s, %d, %d)\n", 671 p->p_pid, args->path, args->uid, args->gid); 672 #endif 673 bsd.path = args->path; 674 /* XXX size casts here */ 675 bsd.uid = args->uid; 676 bsd.gid = args->gid; 677 678 return lchown(p, &bsd); 679 } 680 681 int 682 linux_mkdir(struct proc *p, struct linux_mkdir_args *args) 683 { 684 struct mkdir_args bsd; 685 caddr_t sg; 686 687 sg = stackgap_init(); 688 CHECKALTCREAT(p, &sg, args->path); 689 690 #ifdef DEBUG 691 printf("Linux-emul(%d): mkdir(%s, %d)\n", 692 p->p_pid, args->path, args->mode); 693 #endif 694 bsd.path = args->path; 695 bsd.mode = args->mode; 696 697 return mkdir(p, &bsd); 698 } 699 700 int 701 linux_rmdir(struct proc *p, struct linux_rmdir_args *args) 702 { 703 struct rmdir_args bsd; 704 caddr_t sg; 705 706 sg = stackgap_init(); 707 CHECKALTEXIST(p, &sg, args->path); 708 709 #ifdef DEBUG 710 printf("Linux-emul(%d): rmdir(%s)\n", 711 p->p_pid, args->path); 712 #endif 713 bsd.path = args->path; 714 715 return rmdir(p, &bsd); 716 } 717 718 int 719 linux_rename(struct proc *p, struct linux_rename_args *args) 720 { 721 struct rename_args bsd; 722 caddr_t sg; 723 724 sg = stackgap_init(); 725 CHECKALTEXIST(p, &sg, args->from); 726 CHECKALTCREAT(p, &sg, args->to); 727 728 #ifdef DEBUG 729 printf("Linux-emul(%d): rename(%s, %s)\n", 730 p->p_pid, args->from, args->to); 731 #endif 732 bsd.from = args->from; 733 bsd.to = args->to; 734 735 return rename(p, &bsd); 736 } 737 738 int 739 linux_symlink(struct proc *p, struct linux_symlink_args *args) 740 { 741 struct symlink_args bsd; 742 caddr_t sg; 743 744 sg = stackgap_init(); 745 CHECKALTEXIST(p, &sg, args->path); 746 CHECKALTCREAT(p, &sg, args->to); 747 748 #ifdef DEBUG 749 printf("Linux-emul(%d): symlink(%s, %s)\n", 750 p->p_pid, args->path, args->to); 751 #endif 752 bsd.path = args->path; 753 bsd.link = args->to; 754 755 return symlink(p, &bsd); 756 } 757 758 int 759 linux_readlink(struct proc *p, struct linux_readlink_args *args) 760 { 761 struct readlink_args bsd; 762 caddr_t sg; 763 764 sg = stackgap_init(); 765 CHECKALTEXIST(p, &sg, args->name); 766 767 #ifdef DEBUG 768 printf("Linux-emul(%ld): readlink(%s, %p, %d)\n", 769 (long)p->p_pid, args->name, (void *)args->buf, args->count); 770 #endif 771 bsd.path = args->name; 772 bsd.buf = args->buf; 773 bsd.count = args->count; 774 775 return readlink(p, &bsd); 776 } 777 778 int 779 linux_truncate(struct proc *p, struct linux_truncate_args *args) 780 { 781 struct truncate_args bsd; 782 caddr_t sg; 783 784 sg = stackgap_init(); 785 CHECKALTEXIST(p, &sg, args->path); 786 787 #ifdef DEBUG 788 printf("Linux-emul(%d): truncate(%s, %ld)\n", 789 p->p_pid, args->path, args->length); 790 #endif 791 bsd.path = args->path; 792 bsd.length = args->length; 793 794 return truncate(p, &bsd); 795 } 796 797 int 798 linux_link(struct proc *p, struct linux_link_args *args) 799 { 800 struct link_args bsd; 801 caddr_t sg; 802 803 sg = stackgap_init(); 804 CHECKALTEXIST(p, &sg, args->path); 805 CHECKALTCREAT(p, &sg, args->to); 806 807 #ifdef DEBUG 808 printf("Linux-emul(%d): link(%s, %s)\n", p->p_pid, args->path, args->to); 809 #endif 810 811 bsd.path = args->path; 812 bsd.link = args->to; 813 814 return link(p, &bsd); 815 } 816 817 int 818 linux_getcwd(struct proc *p, struct linux_getcwd_args *args) 819 { 820 struct __getcwd_args bsd; 821 caddr_t sg; 822 int error, len; 823 824 #ifdef DEBUG 825 printf("Linux-emul(%ld): getcwd(%p, %ld)\n", (long)p->p_pid, 826 args->buf, args->bufsize); 827 #endif 828 829 sg = stackgap_init(); 830 bsd.buf = stackgap_alloc(&sg, SPARE_USRSPACE); 831 bsd.buflen = SPARE_USRSPACE; 832 error = __getcwd(p, &bsd); 833 if (!error) { 834 len = strlen(bsd.buf) + 1; 835 if (len <= args->bufsize) { 836 p->p_retval[0] = len; 837 error = copyout(bsd.buf, args->buf, len); 838 } 839 else 840 error = ERANGE; 841 } 842 return (error); 843 } 844 845 #ifndef __alpha__ 846 int 847 linux_fdatasync(p, uap) 848 struct proc *p; 849 struct linux_fdatasync_args *uap; 850 { 851 struct fsync_args bsd; 852 853 bsd.fd = uap->fd; 854 return fsync(p, &bsd); 855 } 856 #endif /*!__alpha__*/ 857 858 int 859 linux_pread(p, uap) 860 struct proc *p; 861 struct linux_pread_args *uap; 862 { 863 struct pread_args bsd; 864 865 bsd.fd = uap->fd; 866 bsd.buf = uap->buf; 867 bsd.nbyte = uap->nbyte; 868 bsd.offset = uap->offset; 869 return pread(p, &bsd); 870 } 871 872 int 873 linux_pwrite(p, uap) 874 struct proc *p; 875 struct linux_pwrite_args *uap; 876 { 877 struct pwrite_args bsd; 878 879 bsd.fd = uap->fd; 880 bsd.buf = uap->buf; 881 bsd.nbyte = uap->nbyte; 882 bsd.offset = uap->offset; 883 return pwrite(p, &bsd); 884 } 885