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