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