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