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 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/conf.h> 37 #include <sys/dirent.h> 38 #include <sys/fcntl.h> 39 #include <sys/file.h> 40 #include <sys/filedesc.h> 41 #include <sys/lock.h> 42 #include <sys/malloc.h> 43 #include <sys/mount.h> 44 #include <sys/mutex.h> 45 #include <sys/namei.h> 46 #include <sys/proc.h> 47 #include <sys/stat.h> 48 #include <sys/sx.h> 49 #include <sys/syscallsubr.h> 50 #include <sys/sysproto.h> 51 #include <sys/tty.h> 52 #include <sys/unistd.h> 53 #include <sys/vnode.h> 54 55 #include <security/mac/mac_framework.h> 56 57 #include <ufs/ufs/extattr.h> 58 #include <ufs/ufs/quota.h> 59 #include <ufs/ufs/ufsmount.h> 60 61 #ifdef COMPAT_LINUX32 62 #include <machine/../linux32/linux.h> 63 #include <machine/../linux32/linux32_proto.h> 64 #else 65 #include <machine/../linux/linux.h> 66 #include <machine/../linux/linux_proto.h> 67 #endif 68 #include <compat/linux/linux_util.h> 69 #include <compat/linux/linux_file.h> 70 71 int 72 linux_creat(struct thread *td, struct linux_creat_args *args) 73 { 74 char *path; 75 int error; 76 77 LCONVPATHEXIST(td, args->path, &path); 78 79 #ifdef DEBUG 80 if (ldebug(creat)) 81 printf(ARGS(creat, "%s, %d"), path, args->mode); 82 #endif 83 error = kern_open(td, path, UIO_SYSSPACE, O_WRONLY | O_CREAT | O_TRUNC, 84 args->mode); 85 LFREEPATH(path); 86 return (error); 87 } 88 89 90 static int 91 linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode) 92 { 93 struct proc *p = td->td_proc; 94 struct file *fp; 95 int fd; 96 int bsd_flags, error; 97 98 bsd_flags = 0; 99 switch (l_flags & LINUX_O_ACCMODE) { 100 case LINUX_O_WRONLY: 101 bsd_flags |= O_WRONLY; 102 break; 103 case LINUX_O_RDWR: 104 bsd_flags |= O_RDWR; 105 break; 106 default: 107 bsd_flags |= O_RDONLY; 108 } 109 if (l_flags & LINUX_O_NDELAY) 110 bsd_flags |= O_NONBLOCK; 111 if (l_flags & LINUX_O_APPEND) 112 bsd_flags |= O_APPEND; 113 if (l_flags & LINUX_O_SYNC) 114 bsd_flags |= O_FSYNC; 115 if (l_flags & LINUX_O_NONBLOCK) 116 bsd_flags |= O_NONBLOCK; 117 if (l_flags & LINUX_FASYNC) 118 bsd_flags |= O_ASYNC; 119 if (l_flags & LINUX_O_CREAT) 120 bsd_flags |= O_CREAT; 121 if (l_flags & LINUX_O_TRUNC) 122 bsd_flags |= O_TRUNC; 123 if (l_flags & LINUX_O_EXCL) 124 bsd_flags |= O_EXCL; 125 if (l_flags & LINUX_O_NOCTTY) 126 bsd_flags |= O_NOCTTY; 127 if (l_flags & LINUX_O_DIRECT) 128 bsd_flags |= O_DIRECT; 129 if (l_flags & LINUX_O_NOFOLLOW) 130 bsd_flags |= O_NOFOLLOW; 131 /* XXX LINUX_O_NOATIME: unable to be easily implemented. */ 132 133 error = kern_openat(td, dirfd, path, UIO_SYSSPACE, bsd_flags, mode); 134 135 if (!error) { 136 fd = td->td_retval[0]; 137 /* 138 * XXX In between kern_open() and fget(), another process 139 * having the same filedesc could use that fd without 140 * checking below. 141 */ 142 error = fget(td, fd, &fp); 143 if (!error) { 144 sx_slock(&proctree_lock); 145 PROC_LOCK(p); 146 if (!(bsd_flags & O_NOCTTY) && 147 SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 148 PROC_UNLOCK(p); 149 sx_unlock(&proctree_lock); 150 if (fp->f_type == DTYPE_VNODE) 151 (void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, 152 td->td_ucred, td); 153 } else { 154 PROC_UNLOCK(p); 155 sx_sunlock(&proctree_lock); 156 } 157 if (l_flags & LINUX_O_DIRECTORY) { 158 if (fp->f_type != DTYPE_VNODE || 159 fp->f_vnode->v_type != VDIR) { 160 error = ENOTDIR; 161 } 162 } 163 fdrop(fp, td); 164 /* 165 * XXX as above, fdrop()/kern_close() pair is racy. 166 */ 167 if (error) 168 kern_close(td, fd); 169 } 170 } 171 172 #ifdef DEBUG 173 if (ldebug(open)) 174 printf(LMSG("open returns error %d"), error); 175 #endif 176 LFREEPATH(path); 177 return (error); 178 } 179 180 int 181 linux_openat(struct thread *td, struct linux_openat_args *args) 182 { 183 char *path; 184 int dfd; 185 186 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 187 if (args->flags & LINUX_O_CREAT) 188 LCONVPATH_AT(td, args->filename, &path, 1, dfd); 189 else 190 LCONVPATH_AT(td, args->filename, &path, 0, dfd); 191 #ifdef DEBUG 192 if (ldebug(openat)) 193 printf(ARGS(openat, "%i, %s, 0x%x, 0x%x"), args->dfd, 194 path, args->flags, args->mode); 195 #endif 196 return (linux_common_open(td, dfd, path, args->flags, args->mode)); 197 } 198 199 int 200 linux_open(struct thread *td, struct linux_open_args *args) 201 { 202 char *path; 203 204 if (args->flags & LINUX_O_CREAT) 205 LCONVPATHCREAT(td, args->path, &path); 206 else 207 LCONVPATHEXIST(td, args->path, &path); 208 209 #ifdef DEBUG 210 if (ldebug(open)) 211 printf(ARGS(open, "%s, 0x%x, 0x%x"), 212 path, args->flags, args->mode); 213 #endif 214 215 return (linux_common_open(td, AT_FDCWD, path, args->flags, args->mode)); 216 } 217 218 int 219 linux_lseek(struct thread *td, struct linux_lseek_args *args) 220 { 221 222 struct lseek_args /* { 223 int fd; 224 int pad; 225 off_t offset; 226 int whence; 227 } */ tmp_args; 228 int error; 229 230 #ifdef DEBUG 231 if (ldebug(lseek)) 232 printf(ARGS(lseek, "%d, %ld, %d"), 233 args->fdes, (long)args->off, args->whence); 234 #endif 235 tmp_args.fd = args->fdes; 236 tmp_args.offset = (off_t)args->off; 237 tmp_args.whence = args->whence; 238 error = lseek(td, &tmp_args); 239 return error; 240 } 241 242 int 243 linux_llseek(struct thread *td, struct linux_llseek_args *args) 244 { 245 struct lseek_args bsd_args; 246 int error; 247 off_t off; 248 249 #ifdef DEBUG 250 if (ldebug(llseek)) 251 printf(ARGS(llseek, "%d, %d:%d, %d"), 252 args->fd, args->ohigh, args->olow, args->whence); 253 #endif 254 off = (args->olow) | (((off_t) args->ohigh) << 32); 255 256 bsd_args.fd = args->fd; 257 bsd_args.offset = off; 258 bsd_args.whence = args->whence; 259 260 if ((error = lseek(td, &bsd_args))) 261 return error; 262 263 if ((error = copyout(td->td_retval, args->res, sizeof (off_t)))) 264 return error; 265 266 td->td_retval[0] = 0; 267 return 0; 268 } 269 270 int 271 linux_readdir(struct thread *td, struct linux_readdir_args *args) 272 { 273 struct linux_getdents_args lda; 274 275 lda.fd = args->fd; 276 lda.dent = args->dent; 277 lda.count = 1; 278 return linux_getdents(td, &lda); 279 } 280 281 /* 282 * Note that linux_getdents(2) and linux_getdents64(2) have the same 283 * arguments. They only differ in the definition of struct dirent they 284 * operate on. We use this to common the code, with the exception of 285 * accessing struct dirent. Note that linux_readdir(2) is implemented 286 * by means of linux_getdents(2). In this case we never operate on 287 * struct dirent64 and thus don't need to handle it... 288 */ 289 290 struct l_dirent { 291 l_ulong d_ino; 292 l_off_t d_off; 293 l_ushort d_reclen; 294 char d_name[LINUX_NAME_MAX + 1]; 295 }; 296 297 struct l_dirent64 { 298 uint64_t d_ino; 299 int64_t d_off; 300 l_ushort d_reclen; 301 u_char d_type; 302 char d_name[LINUX_NAME_MAX + 1]; 303 }; 304 305 /* 306 * Linux uses the last byte in the dirent buffer to store d_type, 307 * at least glibc-2.7 requires it. That is why l_dirent is padded with 2 bytes. 308 */ 309 #define LINUX_RECLEN(namlen) \ 310 roundup((offsetof(struct l_dirent, d_name) + (namlen) + 2), \ 311 sizeof(l_ulong)) 312 313 #define LINUX_RECLEN64(namlen) \ 314 roundup((offsetof(struct l_dirent64, d_name) + (namlen) + 1), \ 315 sizeof(uint64_t)) 316 317 #define LINUX_MAXRECLEN max(LINUX_RECLEN(LINUX_NAME_MAX), \ 318 LINUX_RECLEN64(LINUX_NAME_MAX)) 319 #define LINUX_DIRBLKSIZ 512 320 321 static int 322 getdents_common(struct thread *td, struct linux_getdents64_args *args, 323 int is64bit) 324 { 325 struct dirent *bdp; 326 struct vnode *vp; 327 caddr_t inp, buf; /* BSD-format */ 328 int len, reclen; /* BSD-format */ 329 caddr_t outp; /* Linux-format */ 330 int resid, linuxreclen=0; /* Linux-format */ 331 caddr_t lbuf; /* Linux-format */ 332 struct file *fp; 333 struct uio auio; 334 struct iovec aiov; 335 off_t off; 336 struct l_dirent *linux_dirent; 337 struct l_dirent64 *linux_dirent64; 338 int buflen, error, eofflag, nbytes, justone; 339 u_long *cookies = NULL, *cookiep; 340 int ncookies, vfslocked; 341 342 nbytes = args->count; 343 if (nbytes == 1) { 344 /* readdir(2) case. Always struct dirent. */ 345 if (is64bit) 346 return (EINVAL); 347 nbytes = sizeof(*linux_dirent); 348 justone = 1; 349 } else 350 justone = 0; 351 352 if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0) 353 return (error); 354 355 if ((fp->f_flag & FREAD) == 0) { 356 fdrop(fp, td); 357 return (EBADF); 358 } 359 360 vp = fp->f_vnode; 361 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 362 if (vp->v_type != VDIR) { 363 VFS_UNLOCK_GIANT(vfslocked); 364 fdrop(fp, td); 365 return (EINVAL); 366 } 367 368 off = fp->f_offset; 369 370 buflen = max(LINUX_DIRBLKSIZ, nbytes); 371 buflen = min(buflen, MAXBSIZE); 372 buf = malloc(buflen, M_TEMP, M_WAITOK); 373 lbuf = malloc(LINUX_MAXRECLEN, M_TEMP, M_WAITOK | M_ZERO); 374 vn_lock(vp, LK_SHARED | LK_RETRY); 375 376 again: 377 aiov.iov_base = buf; 378 aiov.iov_len = buflen; 379 auio.uio_iov = &aiov; 380 auio.uio_iovcnt = 1; 381 auio.uio_rw = UIO_READ; 382 auio.uio_segflg = UIO_SYSSPACE; 383 auio.uio_td = td; 384 auio.uio_resid = buflen; 385 auio.uio_offset = off; 386 387 if (cookies) { 388 free(cookies, M_TEMP); 389 cookies = NULL; 390 } 391 392 #ifdef MAC 393 /* 394 * Do directory search MAC check using non-cached credentials. 395 */ 396 if ((error = mac_vnode_check_readdir(td->td_ucred, vp))) 397 goto out; 398 #endif /* MAC */ 399 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, 400 &cookies))) 401 goto out; 402 403 inp = buf; 404 outp = (caddr_t)args->dirent; 405 resid = nbytes; 406 if ((len = buflen - auio.uio_resid) <= 0) 407 goto eof; 408 409 cookiep = cookies; 410 411 if (cookies) { 412 /* 413 * When using cookies, the vfs has the option of reading from 414 * a different offset than that supplied (UFS truncates the 415 * offset to a block boundary to make sure that it never reads 416 * partway through a directory entry, even if the directory 417 * has been compacted). 418 */ 419 while (len > 0 && ncookies > 0 && *cookiep <= off) { 420 bdp = (struct dirent *) inp; 421 len -= bdp->d_reclen; 422 inp += bdp->d_reclen; 423 cookiep++; 424 ncookies--; 425 } 426 } 427 428 while (len > 0) { 429 if (cookiep && ncookies == 0) 430 break; 431 bdp = (struct dirent *) inp; 432 reclen = bdp->d_reclen; 433 if (reclen & 3) { 434 error = EFAULT; 435 goto out; 436 } 437 438 if (bdp->d_fileno == 0) { 439 inp += reclen; 440 if (cookiep) { 441 off = *cookiep++; 442 ncookies--; 443 } else 444 off += reclen; 445 446 len -= reclen; 447 continue; 448 } 449 450 linuxreclen = (is64bit) 451 ? LINUX_RECLEN64(bdp->d_namlen) 452 : LINUX_RECLEN(bdp->d_namlen); 453 454 if (reclen > len || resid < linuxreclen) { 455 outp++; 456 break; 457 } 458 459 if (justone) { 460 /* readdir(2) case. */ 461 linux_dirent = (struct l_dirent*)lbuf; 462 linux_dirent->d_ino = bdp->d_fileno; 463 linux_dirent->d_off = (l_off_t)linuxreclen; 464 linux_dirent->d_reclen = (l_ushort)bdp->d_namlen; 465 strlcpy(linux_dirent->d_name, bdp->d_name, 466 linuxreclen - offsetof(struct l_dirent, d_name)); 467 error = copyout(linux_dirent, outp, linuxreclen); 468 } 469 if (is64bit) { 470 linux_dirent64 = (struct l_dirent64*)lbuf; 471 linux_dirent64->d_ino = bdp->d_fileno; 472 linux_dirent64->d_off = (cookiep) 473 ? (l_off_t)*cookiep 474 : (l_off_t)(off + reclen); 475 linux_dirent64->d_reclen = (l_ushort)linuxreclen; 476 linux_dirent64->d_type = bdp->d_type; 477 strlcpy(linux_dirent64->d_name, bdp->d_name, 478 linuxreclen - offsetof(struct l_dirent64, d_name)); 479 error = copyout(linux_dirent64, outp, linuxreclen); 480 } else if (!justone) { 481 linux_dirent = (struct l_dirent*)lbuf; 482 linux_dirent->d_ino = bdp->d_fileno; 483 linux_dirent->d_off = (cookiep) 484 ? (l_off_t)*cookiep 485 : (l_off_t)(off + reclen); 486 linux_dirent->d_reclen = (l_ushort)linuxreclen; 487 /* 488 * Copy d_type to last byte of l_dirent buffer 489 */ 490 lbuf[linuxreclen-1] = bdp->d_type; 491 strlcpy(linux_dirent->d_name, bdp->d_name, 492 linuxreclen - offsetof(struct l_dirent, d_name)-1); 493 error = copyout(linux_dirent, outp, linuxreclen); 494 } 495 496 if (error) 497 goto out; 498 499 inp += reclen; 500 if (cookiep) { 501 off = *cookiep++; 502 ncookies--; 503 } else 504 off += reclen; 505 506 outp += linuxreclen; 507 resid -= linuxreclen; 508 len -= reclen; 509 if (justone) 510 break; 511 } 512 513 if (outp == (caddr_t)args->dirent) 514 goto again; 515 516 fp->f_offset = off; 517 if (justone) 518 nbytes = resid + linuxreclen; 519 520 eof: 521 td->td_retval[0] = nbytes - resid; 522 523 out: 524 if (cookies) 525 free(cookies, M_TEMP); 526 527 VOP_UNLOCK(vp, 0); 528 VFS_UNLOCK_GIANT(vfslocked); 529 fdrop(fp, td); 530 free(buf, M_TEMP); 531 free(lbuf, M_TEMP); 532 return (error); 533 } 534 535 int 536 linux_getdents(struct thread *td, struct linux_getdents_args *args) 537 { 538 539 #ifdef DEBUG 540 if (ldebug(getdents)) 541 printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); 542 #endif 543 544 return (getdents_common(td, (struct linux_getdents64_args*)args, 0)); 545 } 546 547 int 548 linux_getdents64(struct thread *td, struct linux_getdents64_args *args) 549 { 550 551 #ifdef DEBUG 552 if (ldebug(getdents64)) 553 printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); 554 #endif 555 556 return (getdents_common(td, args, 1)); 557 } 558 559 /* 560 * These exist mainly for hooks for doing /compat/linux translation. 561 */ 562 563 int 564 linux_access(struct thread *td, struct linux_access_args *args) 565 { 566 char *path; 567 int error; 568 569 /* linux convention */ 570 if (args->flags & ~(F_OK | X_OK | W_OK | R_OK)) 571 return (EINVAL); 572 573 LCONVPATHEXIST(td, args->path, &path); 574 575 #ifdef DEBUG 576 if (ldebug(access)) 577 printf(ARGS(access, "%s, %d"), path, args->flags); 578 #endif 579 error = kern_access(td, path, UIO_SYSSPACE, args->flags); 580 LFREEPATH(path); 581 582 return (error); 583 } 584 585 int 586 linux_faccessat(struct thread *td, struct linux_faccessat_args *args) 587 { 588 char *path; 589 int error, dfd; 590 591 /* linux convention */ 592 if (args->mode & ~(F_OK | X_OK | W_OK | R_OK)) 593 return (EINVAL); 594 595 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 596 LCONVPATHEXIST_AT(td, args->filename, &path, dfd); 597 598 #ifdef DEBUG 599 if (ldebug(access)) 600 printf(ARGS(access, "%s, %d"), path, args->mode); 601 #endif 602 603 error = kern_accessat(td, dfd, path, UIO_SYSSPACE, 0 /* XXX */, 604 args->mode); 605 LFREEPATH(path); 606 607 return (error); 608 } 609 610 int 611 linux_unlink(struct thread *td, struct linux_unlink_args *args) 612 { 613 char *path; 614 int error; 615 struct stat st; 616 617 LCONVPATHEXIST(td, args->path, &path); 618 619 #ifdef DEBUG 620 if (ldebug(unlink)) 621 printf(ARGS(unlink, "%s"), path); 622 #endif 623 624 error = kern_unlink(td, path, UIO_SYSSPACE); 625 if (error == EPERM) 626 /* Introduce POSIX noncompliant behaviour of Linux */ 627 if (kern_stat(td, path, UIO_SYSSPACE, &st) == 0) 628 if (S_ISDIR(st.st_mode)) 629 error = EISDIR; 630 LFREEPATH(path); 631 return (error); 632 } 633 634 int 635 linux_unlinkat(struct thread *td, struct linux_unlinkat_args *args) 636 { 637 char *path; 638 int error, dfd; 639 struct stat st; 640 641 if (args->flag & ~LINUX_AT_REMOVEDIR) 642 return (EINVAL); 643 644 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 645 LCONVPATHEXIST_AT(td, args->pathname, &path, dfd); 646 647 #ifdef DEBUG 648 if (ldebug(unlinkat)) 649 printf(ARGS(unlinkat, "%s"), path); 650 #endif 651 652 if (args->flag & LINUX_AT_REMOVEDIR) 653 error = kern_rmdirat(td, dfd, path, UIO_SYSSPACE); 654 else 655 error = kern_unlinkat(td, dfd, path, UIO_SYSSPACE, 0); 656 if (error == EPERM && !(args->flag & LINUX_AT_REMOVEDIR)) { 657 /* Introduce POSIX noncompliant behaviour of Linux */ 658 if (kern_statat(td, AT_SYMLINK_NOFOLLOW, dfd, path, 659 UIO_SYSSPACE, &st) == 0 && S_ISDIR(st.st_mode)) 660 error = EISDIR; 661 } 662 LFREEPATH(path); 663 return (error); 664 } 665 int 666 linux_chdir(struct thread *td, struct linux_chdir_args *args) 667 { 668 char *path; 669 int error; 670 671 LCONVPATHEXIST(td, args->path, &path); 672 673 #ifdef DEBUG 674 if (ldebug(chdir)) 675 printf(ARGS(chdir, "%s"), path); 676 #endif 677 error = kern_chdir(td, path, UIO_SYSSPACE); 678 LFREEPATH(path); 679 return (error); 680 } 681 682 int 683 linux_chmod(struct thread *td, struct linux_chmod_args *args) 684 { 685 char *path; 686 int error; 687 688 LCONVPATHEXIST(td, args->path, &path); 689 690 #ifdef DEBUG 691 if (ldebug(chmod)) 692 printf(ARGS(chmod, "%s, %d"), path, args->mode); 693 #endif 694 error = kern_chmod(td, path, UIO_SYSSPACE, args->mode); 695 LFREEPATH(path); 696 return (error); 697 } 698 699 int 700 linux_fchmodat(struct thread *td, struct linux_fchmodat_args *args) 701 { 702 char *path; 703 int error, dfd; 704 705 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 706 LCONVPATHEXIST_AT(td, args->filename, &path, dfd); 707 708 #ifdef DEBUG 709 if (ldebug(fchmodat)) 710 printf(ARGS(fchmodat, "%s, %d"), path, args->mode); 711 #endif 712 713 error = kern_fchmodat(td, dfd, path, UIO_SYSSPACE, args->mode, 0); 714 LFREEPATH(path); 715 return (error); 716 } 717 718 int 719 linux_mkdir(struct thread *td, struct linux_mkdir_args *args) 720 { 721 char *path; 722 int error; 723 724 LCONVPATHCREAT(td, args->path, &path); 725 726 #ifdef DEBUG 727 if (ldebug(mkdir)) 728 printf(ARGS(mkdir, "%s, %d"), path, args->mode); 729 #endif 730 error = kern_mkdir(td, path, UIO_SYSSPACE, args->mode); 731 LFREEPATH(path); 732 return (error); 733 } 734 735 int 736 linux_mkdirat(struct thread *td, struct linux_mkdirat_args *args) 737 { 738 char *path; 739 int error, dfd; 740 741 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 742 LCONVPATHCREAT_AT(td, args->pathname, &path, dfd); 743 744 #ifdef DEBUG 745 if (ldebug(mkdirat)) 746 printf(ARGS(mkdirat, "%s, %d"), path, args->mode); 747 #endif 748 error = kern_mkdirat(td, dfd, path, UIO_SYSSPACE, args->mode); 749 LFREEPATH(path); 750 return (error); 751 } 752 753 int 754 linux_rmdir(struct thread *td, struct linux_rmdir_args *args) 755 { 756 char *path; 757 int error; 758 759 LCONVPATHEXIST(td, args->path, &path); 760 761 #ifdef DEBUG 762 if (ldebug(rmdir)) 763 printf(ARGS(rmdir, "%s"), path); 764 #endif 765 error = kern_rmdir(td, path, UIO_SYSSPACE); 766 LFREEPATH(path); 767 return (error); 768 } 769 770 int 771 linux_rename(struct thread *td, struct linux_rename_args *args) 772 { 773 char *from, *to; 774 int error; 775 776 LCONVPATHEXIST(td, args->from, &from); 777 /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 778 error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); 779 if (to == NULL) { 780 LFREEPATH(from); 781 return (error); 782 } 783 784 #ifdef DEBUG 785 if (ldebug(rename)) 786 printf(ARGS(rename, "%s, %s"), from, to); 787 #endif 788 error = kern_rename(td, from, to, UIO_SYSSPACE); 789 LFREEPATH(from); 790 LFREEPATH(to); 791 return (error); 792 } 793 794 int 795 linux_renameat(struct thread *td, struct linux_renameat_args *args) 796 { 797 char *from, *to; 798 int error, olddfd, newdfd; 799 800 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; 801 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; 802 LCONVPATHEXIST_AT(td, args->oldname, &from, olddfd); 803 /* Expand LCONVPATHCREATE so that `from' can be freed on errors */ 804 error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd); 805 if (to == NULL) { 806 LFREEPATH(from); 807 return (error); 808 } 809 810 #ifdef DEBUG 811 if (ldebug(renameat)) 812 printf(ARGS(renameat, "%s, %s"), from, to); 813 #endif 814 error = kern_renameat(td, olddfd, from, newdfd, to, UIO_SYSSPACE); 815 LFREEPATH(from); 816 LFREEPATH(to); 817 return (error); 818 } 819 820 int 821 linux_symlink(struct thread *td, struct linux_symlink_args *args) 822 { 823 char *path, *to; 824 int error; 825 826 LCONVPATHEXIST(td, args->path, &path); 827 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 828 error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); 829 if (to == NULL) { 830 LFREEPATH(path); 831 return (error); 832 } 833 834 #ifdef DEBUG 835 if (ldebug(symlink)) 836 printf(ARGS(symlink, "%s, %s"), path, to); 837 #endif 838 error = kern_symlink(td, path, to, UIO_SYSSPACE); 839 LFREEPATH(path); 840 LFREEPATH(to); 841 return (error); 842 } 843 844 int 845 linux_symlinkat(struct thread *td, struct linux_symlinkat_args *args) 846 { 847 char *path, *to; 848 int error, dfd; 849 850 dfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; 851 LCONVPATHEXIST_AT(td, args->oldname, &path, dfd); 852 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 853 error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, dfd); 854 if (to == NULL) { 855 LFREEPATH(path); 856 return (error); 857 } 858 859 #ifdef DEBUG 860 if (ldebug(symlinkat)) 861 printf(ARGS(symlinkat, "%s, %s"), path, to); 862 #endif 863 864 error = kern_symlinkat(td, path, dfd, to, UIO_SYSSPACE); 865 LFREEPATH(path); 866 LFREEPATH(to); 867 return (error); 868 } 869 870 int 871 linux_readlink(struct thread *td, struct linux_readlink_args *args) 872 { 873 char *name; 874 int error; 875 876 LCONVPATHEXIST(td, args->name, &name); 877 878 #ifdef DEBUG 879 if (ldebug(readlink)) 880 printf(ARGS(readlink, "%s, %p, %d"), name, (void *)args->buf, 881 args->count); 882 #endif 883 error = kern_readlink(td, name, UIO_SYSSPACE, args->buf, UIO_USERSPACE, 884 args->count); 885 LFREEPATH(name); 886 return (error); 887 } 888 889 int 890 linux_readlinkat(struct thread *td, struct linux_readlinkat_args *args) 891 { 892 char *name; 893 int error, dfd; 894 895 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 896 LCONVPATHEXIST_AT(td, args->path, &name, dfd); 897 898 #ifdef DEBUG 899 if (ldebug(readlinkat)) 900 printf(ARGS(readlinkat, "%s, %p, %d"), name, (void *)args->buf, 901 args->bufsiz); 902 #endif 903 904 error = kern_readlinkat(td, dfd, name, UIO_SYSSPACE, args->buf, 905 UIO_USERSPACE, args->bufsiz); 906 LFREEPATH(name); 907 return (error); 908 } 909 910 int 911 linux_truncate(struct thread *td, struct linux_truncate_args *args) 912 { 913 char *path; 914 int error; 915 916 LCONVPATHEXIST(td, args->path, &path); 917 918 #ifdef DEBUG 919 if (ldebug(truncate)) 920 printf(ARGS(truncate, "%s, %ld"), path, (long)args->length); 921 #endif 922 923 error = kern_truncate(td, path, UIO_SYSSPACE, args->length); 924 LFREEPATH(path); 925 return (error); 926 } 927 928 int 929 linux_truncate64(struct thread *td, struct linux_truncate64_args *args) 930 { 931 char *path; 932 int error; 933 934 LCONVPATHEXIST(td, args->path, &path); 935 936 #ifdef DEBUG 937 if (ldebug(truncate64)) 938 printf(ARGS(truncate64, "%s, %jd"), path, args->length); 939 #endif 940 941 error = kern_truncate(td, path, UIO_SYSSPACE, args->length); 942 LFREEPATH(path); 943 return (error); 944 } 945 int 946 linux_ftruncate(struct thread *td, struct linux_ftruncate_args *args) 947 { 948 struct ftruncate_args /* { 949 int fd; 950 int pad; 951 off_t length; 952 } */ nuap; 953 954 nuap.fd = args->fd; 955 nuap.length = args->length; 956 return (ftruncate(td, &nuap)); 957 } 958 959 int 960 linux_link(struct thread *td, struct linux_link_args *args) 961 { 962 char *path, *to; 963 int error; 964 965 LCONVPATHEXIST(td, args->path, &path); 966 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 967 error = linux_emul_convpath(td, args->to, UIO_USERSPACE, &to, 1, AT_FDCWD); 968 if (to == NULL) { 969 LFREEPATH(path); 970 return (error); 971 } 972 973 #ifdef DEBUG 974 if (ldebug(link)) 975 printf(ARGS(link, "%s, %s"), path, to); 976 #endif 977 error = kern_link(td, path, to, UIO_SYSSPACE); 978 LFREEPATH(path); 979 LFREEPATH(to); 980 return (error); 981 } 982 983 int 984 linux_linkat(struct thread *td, struct linux_linkat_args *args) 985 { 986 char *path, *to; 987 int error, olddfd, newdfd; 988 989 /* 990 * They really introduced flags argument which is forbidden to 991 * use. 992 */ 993 if (args->flags != 0) 994 return (EINVAL); 995 996 olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd; 997 newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd; 998 LCONVPATHEXIST_AT(td, args->oldname, &path, olddfd); 999 /* Expand LCONVPATHCREATE so that `path' can be freed on errors */ 1000 error = linux_emul_convpath(td, args->newname, UIO_USERSPACE, &to, 1, newdfd); 1001 if (to == NULL) { 1002 LFREEPATH(path); 1003 return (error); 1004 } 1005 1006 #ifdef DEBUG 1007 if (ldebug(linkat)) 1008 printf(ARGS(linkat, "%i, %s, %i, %s, %i"), args->olddfd, path, 1009 args->newdfd, to, args->flags); 1010 #endif 1011 1012 error = kern_linkat(td, olddfd, newdfd, path, to, UIO_SYSSPACE, FOLLOW); 1013 LFREEPATH(path); 1014 LFREEPATH(to); 1015 return (error); 1016 } 1017 1018 int 1019 linux_fdatasync(td, uap) 1020 struct thread *td; 1021 struct linux_fdatasync_args *uap; 1022 { 1023 struct fsync_args bsd; 1024 1025 bsd.fd = uap->fd; 1026 return fsync(td, &bsd); 1027 } 1028 1029 int 1030 linux_pread(td, uap) 1031 struct thread *td; 1032 struct linux_pread_args *uap; 1033 { 1034 struct pread_args bsd; 1035 struct vnode *vp; 1036 int error; 1037 1038 bsd.fd = uap->fd; 1039 bsd.buf = uap->buf; 1040 bsd.nbyte = uap->nbyte; 1041 bsd.offset = uap->offset; 1042 1043 error = pread(td, &bsd); 1044 1045 if (error == 0) { 1046 /* This seems to violate POSIX but linux does it */ 1047 if ((error = fgetvp(td, uap->fd, &vp)) != 0) 1048 return (error); 1049 if (vp->v_type == VDIR) { 1050 vrele(vp); 1051 return (EISDIR); 1052 } 1053 vrele(vp); 1054 } 1055 1056 return (error); 1057 } 1058 1059 int 1060 linux_pwrite(td, uap) 1061 struct thread *td; 1062 struct linux_pwrite_args *uap; 1063 { 1064 struct pwrite_args bsd; 1065 1066 bsd.fd = uap->fd; 1067 bsd.buf = uap->buf; 1068 bsd.nbyte = uap->nbyte; 1069 bsd.offset = uap->offset; 1070 return pwrite(td, &bsd); 1071 } 1072 1073 int 1074 linux_mount(struct thread *td, struct linux_mount_args *args) 1075 { 1076 struct ufs_args ufs; 1077 char fstypename[MFSNAMELEN]; 1078 char mntonname[MNAMELEN], mntfromname[MNAMELEN]; 1079 int error; 1080 int fsflags; 1081 void *fsdata; 1082 1083 error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1, 1084 NULL); 1085 if (error) 1086 return (error); 1087 error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL); 1088 if (error) 1089 return (error); 1090 error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL); 1091 if (error) 1092 return (error); 1093 1094 #ifdef DEBUG 1095 if (ldebug(mount)) 1096 printf(ARGS(mount, "%s, %s, %s"), 1097 fstypename, mntfromname, mntonname); 1098 #endif 1099 1100 if (strcmp(fstypename, "ext2") == 0) { 1101 strcpy(fstypename, "ext2fs"); 1102 fsdata = &ufs; 1103 ufs.fspec = mntfromname; 1104 #define DEFAULT_ROOTID -2 1105 ufs.export.ex_root = DEFAULT_ROOTID; 1106 ufs.export.ex_flags = 1107 args->rwflag & LINUX_MS_RDONLY ? MNT_EXRDONLY : 0; 1108 } else if (strcmp(fstypename, "proc") == 0) { 1109 strcpy(fstypename, "linprocfs"); 1110 fsdata = NULL; 1111 } else if (strcmp(fstypename, "vfat") == 0) { 1112 strcpy(fstypename, "msdosfs"); 1113 fsdata = NULL; 1114 } else { 1115 return (ENODEV); 1116 } 1117 1118 fsflags = 0; 1119 1120 if ((args->rwflag & 0xffff0000) == 0xc0ed0000) { 1121 /* 1122 * Linux SYNC flag is not included; the closest equivalent 1123 * FreeBSD has is !ASYNC, which is our default. 1124 */ 1125 if (args->rwflag & LINUX_MS_RDONLY) 1126 fsflags |= MNT_RDONLY; 1127 if (args->rwflag & LINUX_MS_NOSUID) 1128 fsflags |= MNT_NOSUID; 1129 if (args->rwflag & LINUX_MS_NOEXEC) 1130 fsflags |= MNT_NOEXEC; 1131 if (args->rwflag & LINUX_MS_REMOUNT) 1132 fsflags |= MNT_UPDATE; 1133 } 1134 1135 if (strcmp(fstypename, "linprocfs") == 0) { 1136 error = kernel_vmount(fsflags, 1137 "fstype", fstypename, 1138 "fspath", mntonname, 1139 NULL); 1140 } else if (strcmp(fstypename, "msdosfs") == 0) { 1141 error = kernel_vmount(fsflags, 1142 "fstype", fstypename, 1143 "fspath", mntonname, 1144 "from", mntfromname, 1145 NULL); 1146 } else 1147 error = EOPNOTSUPP; 1148 return (error); 1149 } 1150 1151 int 1152 linux_oldumount(struct thread *td, struct linux_oldumount_args *args) 1153 { 1154 struct linux_umount_args args2; 1155 1156 args2.path = args->path; 1157 args2.flags = 0; 1158 return (linux_umount(td, &args2)); 1159 } 1160 1161 int 1162 linux_umount(struct thread *td, struct linux_umount_args *args) 1163 { 1164 struct unmount_args bsd; 1165 1166 bsd.path = args->path; 1167 bsd.flags = args->flags; /* XXX correct? */ 1168 return (unmount(td, &bsd)); 1169 } 1170 1171 /* 1172 * fcntl family of syscalls 1173 */ 1174 1175 struct l_flock { 1176 l_short l_type; 1177 l_short l_whence; 1178 l_off_t l_start; 1179 l_off_t l_len; 1180 l_pid_t l_pid; 1181 } 1182 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1183 __packed 1184 #endif 1185 ; 1186 1187 static void 1188 linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) 1189 { 1190 switch (linux_flock->l_type) { 1191 case LINUX_F_RDLCK: 1192 bsd_flock->l_type = F_RDLCK; 1193 break; 1194 case LINUX_F_WRLCK: 1195 bsd_flock->l_type = F_WRLCK; 1196 break; 1197 case LINUX_F_UNLCK: 1198 bsd_flock->l_type = F_UNLCK; 1199 break; 1200 default: 1201 bsd_flock->l_type = -1; 1202 break; 1203 } 1204 bsd_flock->l_whence = linux_flock->l_whence; 1205 bsd_flock->l_start = (off_t)linux_flock->l_start; 1206 bsd_flock->l_len = (off_t)linux_flock->l_len; 1207 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 1208 bsd_flock->l_sysid = 0; 1209 } 1210 1211 static void 1212 bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) 1213 { 1214 switch (bsd_flock->l_type) { 1215 case F_RDLCK: 1216 linux_flock->l_type = LINUX_F_RDLCK; 1217 break; 1218 case F_WRLCK: 1219 linux_flock->l_type = LINUX_F_WRLCK; 1220 break; 1221 case F_UNLCK: 1222 linux_flock->l_type = LINUX_F_UNLCK; 1223 break; 1224 } 1225 linux_flock->l_whence = bsd_flock->l_whence; 1226 linux_flock->l_start = (l_off_t)bsd_flock->l_start; 1227 linux_flock->l_len = (l_off_t)bsd_flock->l_len; 1228 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 1229 } 1230 1231 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1232 struct l_flock64 { 1233 l_short l_type; 1234 l_short l_whence; 1235 l_loff_t l_start; 1236 l_loff_t l_len; 1237 l_pid_t l_pid; 1238 } 1239 #if defined(__amd64__) && defined(COMPAT_LINUX32) 1240 __packed 1241 #endif 1242 ; 1243 1244 static void 1245 linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) 1246 { 1247 switch (linux_flock->l_type) { 1248 case LINUX_F_RDLCK: 1249 bsd_flock->l_type = F_RDLCK; 1250 break; 1251 case LINUX_F_WRLCK: 1252 bsd_flock->l_type = F_WRLCK; 1253 break; 1254 case LINUX_F_UNLCK: 1255 bsd_flock->l_type = F_UNLCK; 1256 break; 1257 default: 1258 bsd_flock->l_type = -1; 1259 break; 1260 } 1261 bsd_flock->l_whence = linux_flock->l_whence; 1262 bsd_flock->l_start = (off_t)linux_flock->l_start; 1263 bsd_flock->l_len = (off_t)linux_flock->l_len; 1264 bsd_flock->l_pid = (pid_t)linux_flock->l_pid; 1265 bsd_flock->l_sysid = 0; 1266 } 1267 1268 static void 1269 bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) 1270 { 1271 switch (bsd_flock->l_type) { 1272 case F_RDLCK: 1273 linux_flock->l_type = LINUX_F_RDLCK; 1274 break; 1275 case F_WRLCK: 1276 linux_flock->l_type = LINUX_F_WRLCK; 1277 break; 1278 case F_UNLCK: 1279 linux_flock->l_type = LINUX_F_UNLCK; 1280 break; 1281 } 1282 linux_flock->l_whence = bsd_flock->l_whence; 1283 linux_flock->l_start = (l_loff_t)bsd_flock->l_start; 1284 linux_flock->l_len = (l_loff_t)bsd_flock->l_len; 1285 linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; 1286 } 1287 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1288 1289 static int 1290 fcntl_common(struct thread *td, struct linux_fcntl64_args *args) 1291 { 1292 struct l_flock linux_flock; 1293 struct flock bsd_flock; 1294 struct file *fp; 1295 long arg; 1296 int error, result; 1297 1298 switch (args->cmd) { 1299 case LINUX_F_DUPFD: 1300 return (kern_fcntl(td, args->fd, F_DUPFD, args->arg)); 1301 1302 case LINUX_F_GETFD: 1303 return (kern_fcntl(td, args->fd, F_GETFD, 0)); 1304 1305 case LINUX_F_SETFD: 1306 return (kern_fcntl(td, args->fd, F_SETFD, args->arg)); 1307 1308 case LINUX_F_GETFL: 1309 error = kern_fcntl(td, args->fd, F_GETFL, 0); 1310 result = td->td_retval[0]; 1311 td->td_retval[0] = 0; 1312 if (result & O_RDONLY) 1313 td->td_retval[0] |= LINUX_O_RDONLY; 1314 if (result & O_WRONLY) 1315 td->td_retval[0] |= LINUX_O_WRONLY; 1316 if (result & O_RDWR) 1317 td->td_retval[0] |= LINUX_O_RDWR; 1318 if (result & O_NDELAY) 1319 td->td_retval[0] |= LINUX_O_NONBLOCK; 1320 if (result & O_APPEND) 1321 td->td_retval[0] |= LINUX_O_APPEND; 1322 if (result & O_FSYNC) 1323 td->td_retval[0] |= LINUX_O_SYNC; 1324 if (result & O_ASYNC) 1325 td->td_retval[0] |= LINUX_FASYNC; 1326 #ifdef LINUX_O_NOFOLLOW 1327 if (result & O_NOFOLLOW) 1328 td->td_retval[0] |= LINUX_O_NOFOLLOW; 1329 #endif 1330 #ifdef LINUX_O_DIRECT 1331 if (result & O_DIRECT) 1332 td->td_retval[0] |= LINUX_O_DIRECT; 1333 #endif 1334 return (error); 1335 1336 case LINUX_F_SETFL: 1337 arg = 0; 1338 if (args->arg & LINUX_O_NDELAY) 1339 arg |= O_NONBLOCK; 1340 if (args->arg & LINUX_O_APPEND) 1341 arg |= O_APPEND; 1342 if (args->arg & LINUX_O_SYNC) 1343 arg |= O_FSYNC; 1344 if (args->arg & LINUX_FASYNC) 1345 arg |= O_ASYNC; 1346 #ifdef LINUX_O_NOFOLLOW 1347 if (args->arg & LINUX_O_NOFOLLOW) 1348 arg |= O_NOFOLLOW; 1349 #endif 1350 #ifdef LINUX_O_DIRECT 1351 if (args->arg & LINUX_O_DIRECT) 1352 arg |= O_DIRECT; 1353 #endif 1354 return (kern_fcntl(td, args->fd, F_SETFL, arg)); 1355 1356 case LINUX_F_GETLK: 1357 error = copyin((void *)args->arg, &linux_flock, 1358 sizeof(linux_flock)); 1359 if (error) 1360 return (error); 1361 linux_to_bsd_flock(&linux_flock, &bsd_flock); 1362 error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 1363 if (error) 1364 return (error); 1365 bsd_to_linux_flock(&bsd_flock, &linux_flock); 1366 return (copyout(&linux_flock, (void *)args->arg, 1367 sizeof(linux_flock))); 1368 1369 case LINUX_F_SETLK: 1370 error = copyin((void *)args->arg, &linux_flock, 1371 sizeof(linux_flock)); 1372 if (error) 1373 return (error); 1374 linux_to_bsd_flock(&linux_flock, &bsd_flock); 1375 return (kern_fcntl(td, args->fd, F_SETLK, 1376 (intptr_t)&bsd_flock)); 1377 1378 case LINUX_F_SETLKW: 1379 error = copyin((void *)args->arg, &linux_flock, 1380 sizeof(linux_flock)); 1381 if (error) 1382 return (error); 1383 linux_to_bsd_flock(&linux_flock, &bsd_flock); 1384 return (kern_fcntl(td, args->fd, F_SETLKW, 1385 (intptr_t)&bsd_flock)); 1386 1387 case LINUX_F_GETOWN: 1388 return (kern_fcntl(td, args->fd, F_GETOWN, 0)); 1389 1390 case LINUX_F_SETOWN: 1391 /* 1392 * XXX some Linux applications depend on F_SETOWN having no 1393 * significant effect for pipes (SIGIO is not delivered for 1394 * pipes under Linux-2.2.35 at least). 1395 */ 1396 error = fget(td, args->fd, &fp); 1397 if (error) 1398 return (error); 1399 if (fp->f_type == DTYPE_PIPE) { 1400 fdrop(fp, td); 1401 return (EINVAL); 1402 } 1403 fdrop(fp, td); 1404 1405 return (kern_fcntl(td, args->fd, F_SETOWN, args->arg)); 1406 } 1407 1408 return (EINVAL); 1409 } 1410 1411 int 1412 linux_fcntl(struct thread *td, struct linux_fcntl_args *args) 1413 { 1414 struct linux_fcntl64_args args64; 1415 1416 #ifdef DEBUG 1417 if (ldebug(fcntl)) 1418 printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); 1419 #endif 1420 1421 args64.fd = args->fd; 1422 args64.cmd = args->cmd; 1423 args64.arg = args->arg; 1424 return (fcntl_common(td, &args64)); 1425 } 1426 1427 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1428 int 1429 linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) 1430 { 1431 struct l_flock64 linux_flock; 1432 struct flock bsd_flock; 1433 int error; 1434 1435 #ifdef DEBUG 1436 if (ldebug(fcntl64)) 1437 printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); 1438 #endif 1439 1440 switch (args->cmd) { 1441 case LINUX_F_GETLK64: 1442 error = copyin((void *)args->arg, &linux_flock, 1443 sizeof(linux_flock)); 1444 if (error) 1445 return (error); 1446 linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1447 error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); 1448 if (error) 1449 return (error); 1450 bsd_to_linux_flock64(&bsd_flock, &linux_flock); 1451 return (copyout(&linux_flock, (void *)args->arg, 1452 sizeof(linux_flock))); 1453 1454 case LINUX_F_SETLK64: 1455 error = copyin((void *)args->arg, &linux_flock, 1456 sizeof(linux_flock)); 1457 if (error) 1458 return (error); 1459 linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1460 return (kern_fcntl(td, args->fd, F_SETLK, 1461 (intptr_t)&bsd_flock)); 1462 1463 case LINUX_F_SETLKW64: 1464 error = copyin((void *)args->arg, &linux_flock, 1465 sizeof(linux_flock)); 1466 if (error) 1467 return (error); 1468 linux_to_bsd_flock64(&linux_flock, &bsd_flock); 1469 return (kern_fcntl(td, args->fd, F_SETLKW, 1470 (intptr_t)&bsd_flock)); 1471 } 1472 1473 return (fcntl_common(td, args)); 1474 } 1475 #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ 1476 1477 int 1478 linux_chown(struct thread *td, struct linux_chown_args *args) 1479 { 1480 char *path; 1481 int error; 1482 1483 LCONVPATHEXIST(td, args->path, &path); 1484 1485 #ifdef DEBUG 1486 if (ldebug(chown)) 1487 printf(ARGS(chown, "%s, %d, %d"), path, args->uid, args->gid); 1488 #endif 1489 error = kern_chown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1490 LFREEPATH(path); 1491 return (error); 1492 } 1493 1494 int 1495 linux_fchownat(struct thread *td, struct linux_fchownat_args *args) 1496 { 1497 char *path; 1498 int error, dfd, follow; 1499 1500 if (args->flag & ~LINUX_AT_SYMLINK_NOFOLLOW) 1501 return (EINVAL); 1502 1503 dfd = (args->dfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->dfd; 1504 LCONVPATHEXIST_AT(td, args->filename, &path, dfd); 1505 1506 #ifdef DEBUG 1507 if (ldebug(fchownat)) 1508 printf(ARGS(fchownat, "%s, %d, %d"), path, args->uid, args->gid); 1509 #endif 1510 1511 follow = (args->flag & LINUX_AT_SYMLINK_NOFOLLOW) == 0 ? 0 : 1512 AT_SYMLINK_NOFOLLOW; 1513 error = kern_fchownat(td, dfd, path, UIO_SYSSPACE, args->uid, args->gid, 1514 follow); 1515 LFREEPATH(path); 1516 return (error); 1517 } 1518 1519 int 1520 linux_lchown(struct thread *td, struct linux_lchown_args *args) 1521 { 1522 char *path; 1523 int error; 1524 1525 LCONVPATHEXIST(td, args->path, &path); 1526 1527 #ifdef DEBUG 1528 if (ldebug(lchown)) 1529 printf(ARGS(lchown, "%s, %d, %d"), path, args->uid, args->gid); 1530 #endif 1531 error = kern_lchown(td, path, UIO_SYSSPACE, args->uid, args->gid); 1532 LFREEPATH(path); 1533 return (error); 1534 } 1535