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