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/conf.h> 36 #include <sys/dirent.h> 37 #include <sys/fcntl.h> 38 #include <sys/file.h> 39 #include <sys/filedesc.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/mount.h> 43 #include <sys/mutex.h> 44 #include <sys/proc.h> 45 #include <sys/sysproto.h> 46 #include <sys/tty.h> 47 #include <sys/vnode.h> 48 49 #include <ufs/ufs/extattr.h> 50 #include <ufs/ufs/quota.h> 51 #include <ufs/ufs/ufsmount.h> 52 53 #include <machine/../linux/linux.h> 54 #include <machine/../linux/linux_proto.h> 55 #include <compat/linux/linux_util.h> 56 57 #ifndef __alpha__ 58 int 59 linux_creat(struct thread *td, struct linux_creat_args *args) 60 { 61 struct open_args /* { 62 char *path; 63 int flags; 64 int mode; 65 } */ bsd_open_args; 66 caddr_t sg; 67 68 sg = stackgap_init(); 69 CHECKALTCREAT(td, &sg, args->path); 70 71 #ifdef DEBUG 72 if (ldebug(creat)) 73 printf(ARGS(creat, "%s, %d"), args->path, args->mode); 74 #endif 75 bsd_open_args.path = args->path; 76 bsd_open_args.mode = args->mode; 77 bsd_open_args.flags = O_WRONLY | O_CREAT | O_TRUNC; 78 return open(td, &bsd_open_args); 79 } 80 #endif /*!__alpha__*/ 81 82 int 83 linux_open(struct thread *td, struct linux_open_args *args) 84 { 85 struct open_args /* { 86 char *path; 87 int flags; 88 int mode; 89 } */ bsd_open_args; 90 struct proc *p = td->td_proc; 91 int error; 92 caddr_t sg; 93 94 sg = stackgap_init(); 95 96 if (args->flags & LINUX_O_CREAT) 97 CHECKALTCREAT(td, &sg, args->path); 98 else 99 CHECKALTEXIST(td, &sg, args->path); 100 101 #ifdef DEBUG 102 if (ldebug(open)) 103 printf(ARGS(open, "%s, 0x%x, 0x%x"), 104 args->path, args->flags, args->mode); 105 #endif 106 bsd_open_args.flags = 0; 107 if (args->flags & LINUX_O_RDONLY) 108 bsd_open_args.flags |= O_RDONLY; 109 if (args->flags & LINUX_O_WRONLY) 110 bsd_open_args.flags |= O_WRONLY; 111 if (args->flags & LINUX_O_RDWR) 112 bsd_open_args.flags |= O_RDWR; 113 if (args->flags & LINUX_O_NDELAY) 114 bsd_open_args.flags |= O_NONBLOCK; 115 if (args->flags & LINUX_O_APPEND) 116 bsd_open_args.flags |= O_APPEND; 117 if (args->flags & LINUX_O_SYNC) 118 bsd_open_args.flags |= O_FSYNC; 119 if (args->flags & LINUX_O_NONBLOCK) 120 bsd_open_args.flags |= O_NONBLOCK; 121 if (args->flags & LINUX_FASYNC) 122 bsd_open_args.flags |= O_ASYNC; 123 if (args->flags & LINUX_O_CREAT) 124 bsd_open_args.flags |= O_CREAT; 125 if (args->flags & LINUX_O_TRUNC) 126 bsd_open_args.flags |= O_TRUNC; 127 if (args->flags & LINUX_O_EXCL) 128 bsd_open_args.flags |= O_EXCL; 129 if (args->flags & LINUX_O_NOCTTY) 130 bsd_open_args.flags |= O_NOCTTY; 131 bsd_open_args.path = args->path; 132 bsd_open_args.mode = args->mode; 133 134 error = open(td, &bsd_open_args); 135 PROC_LOCK(p); 136 if (!error && !(bsd_open_args.flags & O_NOCTTY) && 137 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 138 struct file *fp; 139 140 error = fget(td, td->td_retval[0], &fp); 141 PROC_UNLOCK(p); 142 if (!error) { 143 if (fp->f_type == DTYPE_VNODE) 144 fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td); 145 fdrop(fp, td); 146 } 147 } else { 148 PROC_UNLOCK(p); 149 #ifdef DEBUG 150 if (ldebug(open)) 151 printf(LMSG("open returns error %d"), error); 152 #endif 153 } 154 return error; 155 } 156 157 int 158 linux_lseek(struct thread *td, struct linux_lseek_args *args) 159 { 160 161 struct lseek_args /* { 162 int fd; 163 int pad; 164 off_t offset; 165 int whence; 166 } */ tmp_args; 167 int error; 168 169 #ifdef DEBUG 170 if (ldebug(lseek)) 171 printf(ARGS(lseek, "%d, %ld, %d"), 172 args->fdes, (long)args->off, args->whence); 173 #endif 174 tmp_args.fd = args->fdes; 175 tmp_args.offset = (off_t)args->off; 176 tmp_args.whence = args->whence; 177 error = lseek(td, &tmp_args); 178 return error; 179 } 180 181 #ifndef __alpha__ 182 int 183 linux_llseek(struct thread *td, struct linux_llseek_args *args) 184 { 185 struct lseek_args bsd_args; 186 int error; 187 off_t off; 188 189 #ifdef DEBUG 190 if (ldebug(llseek)) 191 printf(ARGS(llseek, "%d, %d:%d, %d"), 192 args->fd, args->ohigh, args->olow, args->whence); 193 #endif 194 off = (args->olow) | (((off_t) args->ohigh) << 32); 195 196 bsd_args.fd = args->fd; 197 bsd_args.offset = off; 198 bsd_args.whence = args->whence; 199 200 if ((error = lseek(td, &bsd_args))) 201 return error; 202 203 if ((error = copyout(td->td_retval, (caddr_t)args->res, sizeof (off_t)))) 204 return error; 205 206 td->td_retval[0] = 0; 207 return 0; 208 } 209 #endif /*!__alpha__*/ 210 211 #ifndef __alpha__ 212 int 213 linux_readdir(struct thread *td, struct linux_readdir_args *args) 214 { 215 struct linux_getdents_args lda; 216 217 lda.fd = args->fd; 218 lda.dent = args->dent; 219 lda.count = 1; 220 return linux_getdents(td, &lda); 221 } 222 #endif /*!__alpha__*/ 223 224 /* 225 * Note that linux_getdents(2) and linux_getdents64(2) have the same 226 * arguments. They only differ in the definition of struct dirent they 227 * operate on. We use this to common the code, with the exception of 228 * accessing struct dirent. Note that linux_readdir(2) is implemented 229 * by means of linux_getdents(2). In this case we never operate on 230 * struct dirent64 and thus don't need to handle it... 231 */ 232 233 struct l_dirent { 234 l_long d_ino; 235 l_off_t d_off; 236 l_ushort d_reclen; 237 char d_name[LINUX_NAME_MAX + 1]; 238 }; 239 240 struct l_dirent64 { 241 uint64_t d_ino; 242 int64_t d_off; 243 l_ushort d_reclen; 244 u_char d_type; 245 char d_name[LINUX_NAME_MAX + 1]; 246 }; 247 248 #define LINUX_RECLEN(de,namlen) \ 249 ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) 250 251 #define LINUX_DIRBLKSIZ 512 252 253 static int 254 getdents_common(struct thread *td, struct linux_getdents64_args *args, 255 int is64bit) 256 { 257 register struct dirent *bdp; 258 struct vnode *vp; 259 caddr_t inp, buf; /* BSD-format */ 260 int len, reclen; /* BSD-format */ 261 caddr_t outp; /* Linux-format */ 262 int resid, linuxreclen=0; /* Linux-format */ 263 struct file *fp; 264 struct uio auio; 265 struct iovec aiov; 266 struct vattr va; 267 off_t off; 268 struct l_dirent linux_dirent; 269 struct l_dirent64 linux_dirent64; 270 int buflen, error, eofflag, nbytes, justone; 271 u_long *cookies = NULL, *cookiep; 272 int ncookies; 273 274 if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 275 return (error); 276 277 if ((fp->f_flag & FREAD) == 0) { 278 fdrop(fp, td); 279 return (EBADF); 280 } 281 282 vp = (struct vnode *) fp->f_data; 283 if (vp->v_type != VDIR) { 284 fdrop(fp, td); 285 return (EINVAL); 286 } 287 288 if ((error = VOP_GETATTR(vp, &va, td->td_ucred, td))) { 289 fdrop(fp, td); 290 return (error); 291 } 292 293 nbytes = args->count; 294 if (nbytes == 1) { 295 /* readdir(2) case. Always struct dirent. */ 296 if (is64bit) { 297 fdrop(fp, td); 298 return (EINVAL); 299 } 300 nbytes = sizeof(linux_dirent); 301 justone = 1; 302 } else 303 justone = 0; 304 305 off = fp->f_offset; 306 307 buflen = max(LINUX_DIRBLKSIZ, nbytes); 308 buflen = min(buflen, MAXBSIZE); 309 buf = malloc(buflen, M_TEMP, M_WAITOK); 310 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 311 312 again: 313 aiov.iov_base = buf; 314 aiov.iov_len = buflen; 315 auio.uio_iov = &aiov; 316 auio.uio_iovcnt = 1; 317 auio.uio_rw = UIO_READ; 318 auio.uio_segflg = UIO_SYSSPACE; 319 auio.uio_td = td; 320 auio.uio_resid = buflen; 321 auio.uio_offset = off; 322 323 if (cookies) { 324 free(cookies, M_TEMP); 325 cookies = NULL; 326 } 327 328 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 329 &cookies))) 330 goto out; 331 332 inp = buf; 333 outp = (caddr_t)args->dirent; 334 resid = nbytes; 335 if ((len = buflen - auio.uio_resid) <= 0) 336 goto eof; 337 338 cookiep = cookies; 339 340 if (cookies) { 341 /* 342 * When using cookies, the vfs has the option of reading from 343 * a different offset than that supplied (UFS truncates the 344 * offset to a block boundary to make sure that it never reads 345 * partway through a directory entry, even if the directory 346 * has been compacted). 347 */ 348 while (len > 0 && ncookies > 0 && *cookiep <= off) { 349 bdp = (struct dirent *) inp; 350 len -= bdp->d_reclen; 351 inp += bdp->d_reclen; 352 cookiep++; 353 ncookies--; 354 } 355 } 356 357 while (len > 0) { 358 if (cookiep && ncookies == 0) 359 break; 360 bdp = (struct dirent *) inp; 361 reclen = bdp->d_reclen; 362 if (reclen & 3) { 363 error = EFAULT; 364 goto out; 365 } 366 367 if (bdp->d_fileno == 0) { 368 inp += reclen; 369 if (cookiep) { 370 off = *cookiep++; 371 ncookies--; 372 } else 373 off += reclen; 374 375 len -= reclen; 376 continue; 377 } 378 379 linuxreclen = (is64bit) 380 ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 381 : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 382 383 if (reclen > len || resid < linuxreclen) { 384 outp++; 385 break; 386 } 387 388 if (justone) { 389 /* readdir(2) case. */ 390 linux_dirent.d_ino = (l_long)bdp->d_fileno; 391 linux_dirent.d_off = (l_off_t)linuxreclen; 392 linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 393 strcpy(linux_dirent.d_name, bdp->d_name); 394 error = copyout(&linux_dirent, outp, linuxreclen); 395 } else { 396 if (is64bit) { 397 linux_dirent64.d_ino = bdp->d_fileno; 398 linux_dirent64.d_off = (cookiep) 399 ? (l_off_t)*cookiep 400 : (l_off_t)(off + reclen); 401 linux_dirent64.d_reclen = 402 (l_ushort)linuxreclen; 403 linux_dirent64.d_type = bdp->d_type; 404 strcpy(linux_dirent64.d_name, bdp->d_name); 405 error = copyout(&linux_dirent64, outp, 406 linuxreclen); 407 } else { 408 linux_dirent.d_ino = bdp->d_fileno; 409 linux_dirent.d_off = (cookiep) 410 ? (l_off_t)*cookiep 411 : (l_off_t)(off + reclen); 412 linux_dirent.d_reclen = (l_ushort)linuxreclen; 413 strcpy(linux_dirent.d_name, bdp->d_name); 414 error = copyout(&linux_dirent, outp, 415 linuxreclen); 416 } 417 } 418 if (error) 419 goto out; 420 421 inp += reclen; 422 if (cookiep) { 423 off = *cookiep++; 424 ncookies--; 425 } else 426 off += reclen; 427 428 outp += linuxreclen; 429 resid -= linuxreclen; 430 len -= reclen; 431 if (justone) 432 break; 433 } 434 435 if (outp == (caddr_t)args->dirent) 436 goto again; 437 438 fp->f_offset = off; 439 if (justone) 440 nbytes = resid + linuxreclen; 441 442 eof: 443 td->td_retval[0] = nbytes - resid; 444 445 out: 446 if (cookies) 447 free(cookies, M_TEMP); 448 449 VOP_UNLOCK(vp, 0, td); 450 fdrop(fp, td); 451 free(buf, M_TEMP); 452 return (error); 453 } 454 455 int 456 linux_getdents(struct thread *td, struct linux_getdents_args *args) 457 { 458 459 #ifdef DEBUG 460 if (ldebug(getdents)) 461 printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 462 #endif 463 464 return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 465 } 466 467 int 468 linux_getdents64(struct thread *td, struct linux_getdents64_args *args) 469 { 470 471 #ifdef DEBUG 472 if (ldebug(getdents64)) 473 printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 474 #endif 475 476 return (getdents_common(td, args, 1)); 477 } 478 479 /* 480 * These exist mainly for hooks for doing /compat/linux translation. 481 */ 482 483 int 484 linux_access(struct thread *td, struct linux_access_args *args) 485 { 486 struct access_args bsd; 487 caddr_t sg; 488 489 sg = stackgap_init(); 490 CHECKALTEXIST(td, &sg, args->path); 491 492 #ifdef DEBUG 493 if (ldebug(access)) 494 printf(ARGS(access, "%s, %d"), args->path, args->flags); 495 #endif 496 bsd.path = args->path; 497 bsd.flags = args->flags; 498 499 return access(td, &bsd); 500 } 501 502 int 503 linux_unlink(struct thread *td, struct linux_unlink_args *args) 504 { 505 struct unlink_args bsd; 506 caddr_t sg; 507 508 sg = stackgap_init(); 509 CHECKALTEXIST(td, &sg, args->path); 510 511 #ifdef DEBUG 512 if (ldebug(unlink)) 513 printf(ARGS(unlink, "%s"), args->path); 514 #endif 515 bsd.path = args->path; 516 517 return unlink(td, &bsd); 518 } 519 520 int 521 linux_chdir(struct thread *td, struct linux_chdir_args *args) 522 { 523 struct chdir_args bsd; 524 caddr_t sg; 525 526 sg = stackgap_init(); 527 CHECKALTEXIST(td, &sg, args->path); 528 529 #ifdef DEBUG 530 if (ldebug(chdir)) 531 printf(ARGS(chdir, "%s"), args->path); 532 #endif 533 bsd.path = args->path; 534 535 return chdir(td, &bsd); 536 } 537 538 int 539 linux_chmod(struct thread *td, struct linux_chmod_args *args) 540 { 541 struct chmod_args bsd; 542 caddr_t sg; 543 544 sg = stackgap_init(); 545 CHECKALTEXIST(td, &sg, args->path); 546 547 #ifdef DEBUG 548 if (ldebug(chmod)) 549 printf(ARGS(chmod, "%s, %d"), args->path, args->mode); 550 #endif 551 bsd.path = args->path; 552 bsd.mode = args->mode; 553 554 return chmod(td, &bsd); 555 } 556 557 int 558 linux_mkdir(struct thread *td, struct linux_mkdir_args *args) 559 { 560 struct mkdir_args bsd; 561 caddr_t sg; 562 563 sg = stackgap_init(); 564 CHECKALTCREAT(td, &sg, args->path); 565 566 #ifdef DEBUG 567 if (ldebug(mkdir)) 568 printf(ARGS(mkdir, "%s, %d"), args->path, args->mode); 569 #endif 570 bsd.path = args->path; 571 bsd.mode = args->mode; 572 573 return mkdir(td, &bsd); 574 } 575 576 int 577 linux_rmdir(struct thread *td, struct linux_rmdir_args *args) 578 { 579 struct rmdir_args bsd; 580 caddr_t sg; 581 582 sg = stackgap_init(); 583 CHECKALTEXIST(td, &sg, args->path); 584 585 #ifdef DEBUG 586 if (ldebug(rmdir)) 587 printf(ARGS(rmdir, "%s"), args->path); 588 #endif 589 bsd.path = args->path; 590 591 return rmdir(td, &bsd); 592 } 593 594 int 595 linux_rename(struct thread *td, struct linux_rename_args *args) 596 { 597 struct rename_args bsd; 598 caddr_t sg; 599 600 sg = stackgap_init(); 601 CHECKALTEXIST(td, &sg, args->from); 602 CHECKALTCREAT(td, &sg, args->to); 603 604 #ifdef DEBUG 605 if (ldebug(rename)) 606 printf(ARGS(rename, "%s, %s"), args->from, args->to); 607 #endif 608 bsd.from = args->from; 609 bsd.to = args->to; 610 611 return rename(td, &bsd); 612 } 613 614 int 615 linux_symlink(struct thread *td, struct linux_symlink_args *args) 616 { 617 struct symlink_args bsd; 618 caddr_t sg; 619 620 sg = stackgap_init(); 621 CHECKALTEXIST(td, &sg, args->path); 622 CHECKALTCREAT(td, &sg, args->to); 623 624 #ifdef DEBUG 625 if (ldebug(symlink)) 626 printf(ARGS(symlink, "%s, %s"), args->path, args->to); 627 #endif 628 bsd.path = args->path; 629 bsd.link = args->to; 630 631 return symlink(td, &bsd); 632 } 633 634 int 635 linux_readlink(struct thread *td, struct linux_readlink_args *args) 636 { 637 struct readlink_args bsd; 638 caddr_t sg; 639 640 sg = stackgap_init(); 641 CHECKALTEXIST(td, &sg, args->name); 642 643 #ifdef DEBUG 644 if (ldebug(readlink)) 645 printf(ARGS(readlink, "%s, %p, %d"), 646 args->name, (void *)args->buf, args->count); 647 #endif 648 bsd.path = args->name; 649 bsd.buf = args->buf; 650 bsd.count = args->count; 651 652 return readlink(td, &bsd); 653 } 654 655 int 656 linux_truncate(struct thread *td, struct linux_truncate_args *args) 657 { 658 struct truncate_args bsd; 659 caddr_t sg; 660 661 sg = stackgap_init(); 662 CHECKALTEXIST(td, &sg, args->path); 663 664 #ifdef DEBUG 665 if (ldebug(truncate)) 666 printf(ARGS(truncate, "%s, %ld"), args->path, 667 (long)args->length); 668 #endif 669 bsd.path = args->path; 670 bsd.length = args->length; 671 672 return truncate(td, &bsd); 673 } 674 675 int 676 linux_link(struct thread *td, struct linux_link_args *args) 677 { 678 struct link_args bsd; 679 caddr_t sg; 680 681 sg = stackgap_init(); 682 CHECKALTEXIST(td, &sg, args->path); 683 CHECKALTCREAT(td, &sg, args->to); 684 685 #ifdef DEBUG 686 if (ldebug(link)) 687 printf(ARGS(link, "%s, %s"), args->path, args->to); 688 #endif 689 690 bsd.path = args->path; 691 bsd.link = args->to; 692 693 return link(td, &bsd); 694 } 695 696 #ifndef __alpha__ 697 int 698 linux_fdatasync(td, uap) 699 struct thread *td; 700 struct linux_fdatasync_args *uap; 701 { 702 struct fsync_args bsd; 703 704 bsd.fd = uap->fd; 705 return fsync(td, &bsd); 706 } 707 #endif /*!__alpha__*/ 708 709 int 710 linux_pread(td, uap) 711 struct thread *td; 712 struct linux_pread_args *uap; 713 { 714 struct pread_args bsd; 715 716 bsd.fd = uap->fd; 717 bsd.buf = uap->buf; 718 bsd.nbyte = uap->nbyte; 719 bsd.offset = uap->offset; 720 return pread(td, &bsd); 721 } 722 723 int 724 linux_pwrite(td, uap) 725 struct thread *td; 726 struct linux_pwrite_args *uap; 727 { 728 struct pwrite_args bsd; 729 730 bsd.fd = uap->fd; 731 bsd.buf = uap->buf; 732 bsd.nbyte = uap->nbyte; 733 bsd.offset = uap->offset; 734 return pwrite(td, &bsd); 735 } 736 737 int 738 linux_mount(struct thread *td, struct linux_mount_args *args) 739 { 740 struct ufs_args ufs; 741 char fstypename[MFSNAMELEN]; 742 char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 743 int error; 744 int fsflags; 745 const char *fstype; 746 void *fsdata; 747 748 error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 749 NULL); 750 if (error) 751 return (error); 752 error = copyinstr(args->specialfile, mntfromname, MFSNAMELEN - 1, NULL); 753 if (error) 754 return (error); 755 error = copyinstr(args->dir, mntonname, MFSNAMELEN - 1, NULL); 756 if (error) 757 return (error); 758 759 #ifdef DEBUG 760 if (ldebug(mount)) 761 printf(ARGS(mount, "%s, %s, %s"), 762 fstypename, mntfromname, mntonname); 763 #endif 764 765 if (strcmp(fstypename, "ext2") == 0) { 766 fstype = "ext2fs"; 767 fsdata = &ufs; 768 ufs.fspec = mntfromname; 769 #define DEFAULT_ROOTID -2 770 ufs.export.ex_root = DEFAULT_ROOTID; 771 ufs.export.ex_flags = 772 args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 773 } else if (strcmp(fstypename, "proc") == 0) { 774 fstype = "linprocfs"; 775 fsdata = NULL; 776 } else { 777 return (ENODEV); 778 } 779 780 fsflags = 0; 781 782 if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 783 /* 784 * Linux SYNC flag is not included; the closest equivalent 785 * FreeBSD has is !ASYNC, which is our default. 786 */ 787 if (args->rwflag & LINUX_MS_RDONLY) 788 fsflags |= MNT_RDONLY; 789 if (args->rwflag & LINUX_MS_NOSUID) 790 fsflags |= MNT_NOSUID; 791 if (args->rwflag & LINUX_MS_NODEV) 792 fsflags |= MNT_NODEV; 793 if (args->rwflag & LINUX_MS_NOEXEC) 794 fsflags |= MNT_NOEXEC; 795 if (args->rwflag & LINUX_MS_REMOUNT) 796 fsflags |= MNT_UPDATE; 797 } 798 799 return (vfs_mount(td, fstype, mntonname, fsflags, fsdata)); 800 } 801 802 int 803 linux_oldumount(struct thread *td, struct linux_oldumount_args *args) 804 { 805 struct linux_umount_args args2; 806 807 args2.path = args->path; 808 args2.flags = 0; 809 return (linux_umount(td, &args2)); 810 } 811 812 int 813 linux_umount(struct thread *td, struct linux_umount_args *args) 814 { 815 struct unmount_args bsd; 816 817 bsd.path = args->path; 818 bsd.flags = args->flags; /* XXX correct? */ 819 return (unmount(td, &bsd)); 820 } 821 822 /* 823 * fcntl family of syscalls 824 */ 825 826 struct l_flock { 827 l_short l_type; 828 l_short l_whence; 829 l_off_t l_start; 830 l_off_t l_len; 831 l_pid_t l_pid; 832 }; 833 834 static void 835 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 836 { 837 switch (linux_flock->l_type) { 838 case LINUX_F_RDLCK: 839 bsd_flock->l_type = F_RDLCK; 840 break; 841 case LINUX_F_WRLCK: 842 bsd_flock->l_type = F_WRLCK; 843 break; 844 case LINUX_F_UNLCK: 845 bsd_flock->l_type = F_UNLCK; 846 break; 847 default: 848 bsd_flock->l_type = -1; 849 break; 850 } 851 bsd_flock->l_whence = linux_flock->l_whence; 852 bsd_flock->l_start = (off_t)linux_flock->l_start; 853 bsd_flock->l_len = (off_t)linux_flock->l_len; 854 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 855 } 856 857 static void 858 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 859 { 860 switch (bsd_flock->l_type) { 861 case F_RDLCK: 862 linux_flock->l_type = LINUX_F_RDLCK; 863 break; 864 case F_WRLCK: 865 linux_flock->l_type = LINUX_F_WRLCK; 866 break; 867 case F_UNLCK: 868 linux_flock->l_type = LINUX_F_UNLCK; 869 break; 870 } 871 linux_flock->l_whence = bsd_flock->l_whence; 872 linux_flock->l_start = (l_off_t)bsd_flock->l_start; 873 linux_flock->l_len = (l_off_t)bsd_flock->l_len; 874 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 875 } 876 877 #if defined(__i386__) 878 struct l_flock64 { 879 l_short l_type; 880 l_short l_whence; 881 l_loff_t l_start; 882 l_loff_t l_len; 883 l_pid_t l_pid; 884 }; 885 886 static void 887 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 888 { 889 switch (linux_flock->l_type) { 890 case LINUX_F_RDLCK: 891 bsd_flock->l_type = F_RDLCK; 892 break; 893 case LINUX_F_WRLCK: 894 bsd_flock->l_type = F_WRLCK; 895 break; 896 case LINUX_F_UNLCK: 897 bsd_flock->l_type = F_UNLCK; 898 break; 899 default: 900 bsd_flock->l_type = -1; 901 break; 902 } 903 bsd_flock->l_whence = linux_flock->l_whence; 904 bsd_flock->l_start = (off_t)linux_flock->l_start; 905 bsd_flock->l_len = (off_t)linux_flock->l_len; 906 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 907 } 908 909 static void 910 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 911 { 912 switch (bsd_flock->l_type) { 913 case F_RDLCK: 914 linux_flock->l_type = LINUX_F_RDLCK; 915 break; 916 case F_WRLCK: 917 linux_flock->l_type = LINUX_F_WRLCK; 918 break; 919 case F_UNLCK: 920 linux_flock->l_type = LINUX_F_UNLCK; 921 break; 922 } 923 linux_flock->l_whence = bsd_flock->l_whence; 924 linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 925 linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 926 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 927 } 928 #endif /* __i386__ */ 929 930 #if defined(__alpha__) 931 #define linux_fcntl64_args linux_fcntl_args 932 #endif 933 934 static int 935 fcntl_common(struct thread *td, struct linux_fcntl64_args *args) 936 { 937 struct fcntl_args fcntl_args; 938 struct file *fp; 939 int error, result; 940 941 fcntl_args.fd = args->fd; 942 943 switch (args->cmd) { 944 case LINUX_F_DUPFD: 945 fcntl_args.cmd = F_DUPFD; 946 fcntl_args.arg = args->arg; 947 return (fcntl(td, &fcntl_args)); 948 949 case LINUX_F_GETFD: 950 fcntl_args.cmd = F_GETFD; 951 return (fcntl(td, &fcntl_args)); 952 953 case LINUX_F_SETFD: 954 fcntl_args.cmd = F_SETFD; 955 fcntl_args.arg = args->arg; 956 return (fcntl(td, &fcntl_args)); 957 958 case LINUX_F_GETFL: 959 fcntl_args.cmd = F_GETFL; 960 error = fcntl(td, &fcntl_args); 961 result = td->td_retval[0]; 962 td->td_retval[0] = 0; 963 if (result & O_RDONLY) 964 td->td_retval[0] |= LINUX_O_RDONLY; 965 if (result & O_WRONLY) 966 td->td_retval[0] |= LINUX_O_WRONLY; 967 if (result & O_RDWR) 968 td->td_retval[0] |= LINUX_O_RDWR; 969 if (result & O_NDELAY) 970 td->td_retval[0] |= LINUX_O_NONBLOCK; 971 if (result & O_APPEND) 972 td->td_retval[0] |= LINUX_O_APPEND; 973 if (result & O_FSYNC) 974 td->td_retval[0] |= LINUX_O_SYNC; 975 if (result & O_ASYNC) 976 td->td_retval[0] |= LINUX_FASYNC; 977 return (error); 978 979 case LINUX_F_SETFL: 980 fcntl_args.arg = 0; 981 if (args->arg & LINUX_O_NDELAY) 982 fcntl_args.arg |= O_NONBLOCK; 983 if (args->arg & LINUX_O_APPEND) 984 fcntl_args.arg |= O_APPEND; 985 if (args->arg & LINUX_O_SYNC) 986 fcntl_args.arg |= O_FSYNC; 987 if (args->arg & LINUX_FASYNC) 988 fcntl_args.arg |= O_ASYNC; 989 fcntl_args.cmd = F_SETFL; 990 return (fcntl(td, &fcntl_args)); 991 992 case LINUX_F_GETOWN: 993 fcntl_args.cmd = F_GETOWN; 994 return (fcntl(td, &fcntl_args)); 995 996 case LINUX_F_SETOWN: 997 /* 998 * XXX some Linux applications depend on F_SETOWN having no 999 * significant effect for pipes (SIGIO is not delivered for 1000 * pipes under Linux-2.2.35 at least). 1001 */ 1002 error = fget(td, args->fd, &fp); 1003 if (error) 1004 return (error); 1005 if (fp->f_type == DTYPE_PIPE) { 1006 fdrop(fp, td); 1007 return (EINVAL); 1008 } 1009 fdrop(fp, td); 1010 1011 fcntl_args.cmd = F_SETOWN; 1012 fcntl_args.arg = args->arg; 1013 return (fcntl(td, &fcntl_args)); 1014 } 1015 1016 return (EINVAL); 1017 } 1018 1019 int 1020 linux_fcntl(struct thread *td, struct linux_fcntl_args *args) 1021 { 1022 struct linux_fcntl64_args args64; 1023 struct fcntl_args fcntl_args; 1024 struct l_flock linux_flock; 1025 struct flock *bsd_flock; 1026 int error; 1027 caddr_t sg; 1028 1029 sg = stackgap_init(); 1030 bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 1031 1032 #ifdef DEBUG 1033 if (ldebug(fcntl)) 1034 printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 1035 #endif 1036 1037 switch (args->cmd) { 1038 case LINUX_F_GETLK: 1039 error = copyin((caddr_t)args->arg, &linux_flock, 1040 sizeof(linux_flock)); 1041 if (error) 1042 return (error); 1043 linux_to_bsd_flock(&linux_flock, bsd_flock); 1044 fcntl_args.fd = args->fd; 1045 fcntl_args.cmd = F_GETLK; 1046 fcntl_args.arg = (long)bsd_flock; 1047 error = fcntl(td, &fcntl_args); 1048 if (error) 1049 return (error); 1050 bsd_to_linux_flock(bsd_flock, &linux_flock); 1051 return (copyout(&linux_flock, (caddr_t)args->arg, 1052 sizeof(linux_flock))); 1053 1054 case LINUX_F_SETLK: 1055 error = copyin((caddr_t)args->arg, &linux_flock, 1056 sizeof(linux_flock)); 1057 if (error) 1058 return (error); 1059 linux_to_bsd_flock(&linux_flock, bsd_flock); 1060 fcntl_args.fd = args->fd; 1061 fcntl_args.cmd = F_SETLK; 1062 fcntl_args.arg = (long)bsd_flock; 1063 return (fcntl(td, &fcntl_args)); 1064 1065 case LINUX_F_SETLKW: 1066 error = copyin((caddr_t)args->arg, &linux_flock, 1067 sizeof(linux_flock)); 1068 if (error) 1069 return (error); 1070 linux_to_bsd_flock(&linux_flock, bsd_flock); 1071 fcntl_args.fd = args->fd; 1072 fcntl_args.cmd = F_SETLKW; 1073 fcntl_args.arg = (long)bsd_flock; 1074 return (fcntl(td, &fcntl_args)); 1075 } 1076 1077 args64.fd = args->fd; 1078 args64.cmd = args->cmd; 1079 args64.arg = args->arg; 1080 return (fcntl_common(td, &args64)); 1081 } 1082 1083 #if defined(__i386__) 1084 int 1085 linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 1086 { 1087 struct fcntl_args fcntl_args; 1088 struct l_flock64 linux_flock; 1089 struct flock *bsd_flock; 1090 int error; 1091 caddr_t sg; 1092 1093 sg = stackgap_init(); 1094 bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); 1095 1096 #ifdef DEBUG 1097 if (ldebug(fcntl64)) 1098 printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 1099 #endif 1100 1101 switch (args->cmd) { 1102 case LINUX_F_GETLK: 1103 error = copyin((caddr_t)args->arg, &linux_flock, 1104 sizeof(linux_flock)); 1105 if (error) 1106 return (error); 1107 linux_to_bsd_flock64(&linux_flock, bsd_flock); 1108 fcntl_args.fd = args->fd; 1109 fcntl_args.cmd = F_GETLK; 1110 fcntl_args.arg = (long)bsd_flock; 1111 error = fcntl(td, &fcntl_args); 1112 if (error) 1113 return (error); 1114 bsd_to_linux_flock64(bsd_flock, &linux_flock); 1115 return (copyout(&linux_flock, (caddr_t)args->arg, 1116 sizeof(linux_flock))); 1117 1118 case LINUX_F_SETLK: 1119 error = copyin((caddr_t)args->arg, &linux_flock, 1120 sizeof(linux_flock)); 1121 if (error) 1122 return (error); 1123 linux_to_bsd_flock64(&linux_flock, bsd_flock); 1124 fcntl_args.fd = args->fd; 1125 fcntl_args.cmd = F_SETLK; 1126 fcntl_args.arg = (long)bsd_flock; 1127 return (fcntl(td, &fcntl_args)); 1128 1129 case LINUX_F_SETLKW: 1130 error = copyin((caddr_t)args->arg, &linux_flock, 1131 sizeof(linux_flock)); 1132 if (error) 1133 return (error); 1134 linux_to_bsd_flock64(&linux_flock, bsd_flock); 1135 fcntl_args.fd = args->fd; 1136 fcntl_args.cmd = F_SETLKW; 1137 fcntl_args.arg = (long)bsd_flock; 1138 return (fcntl(td, &fcntl_args)); 1139 } 1140 1141 return (fcntl_common(td, args)); 1142 } 1143 #endif /* __i386__ */ 1144 1145 int 1146 linux_chown(struct thread *td, struct linux_chown_args *args) 1147 { 1148 struct chown_args bsd; 1149 caddr_t sg; 1150 1151 sg = stackgap_init(); 1152 CHECKALTEXIST(td, &sg, args->path); 1153 1154 #ifdef DEBUG 1155 if (ldebug(chown)) 1156 printf(ARGS(chown, "%s, %d, %d"), args->path, args->uid, 1157 args->gid); 1158 #endif 1159 1160 bsd.path = args->path; 1161 bsd.uid = args->uid; 1162 bsd.gid = args->gid; 1163 return (chown(td, &bsd)); 1164 } 1165 1166 int 1167 linux_lchown(struct thread *td, struct linux_lchown_args *args) 1168 { 1169 struct lchown_args bsd; 1170 caddr_t sg; 1171 1172 sg = stackgap_init(); 1173 CHECKALTEXIST(td, &sg, args->path); 1174 1175 #ifdef DEBUG 1176 if (ldebug(lchown)) 1177 printf(ARGS(lchown, "%s, %d, %d"), args->path, args->uid, 1178 args->gid); 1179 #endif 1180 1181 bsd.path = args->path; 1182 bsd.uid = args->uid; 1183 bsd.gid = args->gid; 1184 return (lchown(td, &bsd)); 1185 } 1186