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