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