1 /* $NetBSD: linux_file.c,v 1.16 1996/10/10 17:51:57 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Frank van der Linden 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Frank van der Linden 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/namei.h> 37 #include <sys/proc.h> 38 #include <sys/file.h> 39 #include <sys/stat.h> 40 #include <sys/filedesc.h> 41 #include <sys/ioctl.h> 42 #include <sys/kernel.h> 43 #include <sys/mount.h> 44 #include <sys/malloc.h> 45 #include <sys/vnode.h> 46 #include <sys/tty.h> 47 #include <sys/conf.h> 48 49 #include <sys/syscallargs.h> 50 51 #include <compat/linux/linux_types.h> 52 #include <compat/linux/linux_signal.h> 53 #include <compat/linux/linux_syscallargs.h> 54 #include <compat/linux/linux_fcntl.h> 55 #include <compat/linux/linux_util.h> 56 57 #include <machine/linux_machdep.h> 58 59 static int linux_to_bsd_ioflags __P((int)); 60 static int bsd_to_linux_ioflags __P((int)); 61 static void bsd_to_linux_flock __P((struct flock *, struct linux_flock *)); 62 static void linux_to_bsd_flock __P((struct linux_flock *, struct flock *)); 63 static void bsd_to_linux_stat __P((struct stat *, struct linux_stat *)); 64 static int linux_stat1 __P((struct proc *, void *, register_t *, int)); 65 66 /* 67 * Some file-related calls are handled here. The usual flag conversion 68 * an structure conversion is done, and alternate emul path searching. 69 */ 70 71 /* 72 * The next two functions convert between the Linux and NetBSD values 73 * of the flags used in open(2) and fcntl(2). 74 */ 75 static int 76 linux_to_bsd_ioflags(lflags) 77 int lflags; 78 { 79 int res = 0; 80 81 res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY); 82 res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY); 83 res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR); 84 res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT); 85 res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL); 86 res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY); 87 res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC); 88 res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY); 89 res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC); 90 res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC); 91 res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND); 92 93 return res; 94 } 95 96 static int 97 bsd_to_linux_ioflags(bflags) 98 int bflags; 99 { 100 int res = 0; 101 102 res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY); 103 res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY); 104 res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR); 105 res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT); 106 res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL); 107 res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY); 108 res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC); 109 res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY); 110 res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC); 111 res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC); 112 res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND); 113 114 return res; 115 } 116 117 /* 118 * creat(2) is an obsolete function, but it's present as a Linux 119 * system call, so let's deal with it. 120 * 121 * Just call open(2) with the TRUNC, CREAT and WRONLY flags. 122 */ 123 int 124 linux_sys_creat(p, v, retval) 125 struct proc *p; 126 void *v; 127 register_t *retval; 128 { 129 struct linux_sys_creat_args /* { 130 syscallarg(char *) path; 131 syscallarg(int) mode; 132 } */ *uap = v; 133 struct sys_open_args oa; 134 caddr_t sg; 135 136 sg = stackgap_init(p->p_emul); 137 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 138 139 SCARG(&oa, path) = SCARG(uap, path); 140 SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY; 141 SCARG(&oa, mode) = SCARG(uap, mode); 142 143 return sys_open(p, &oa, retval); 144 } 145 146 /* 147 * open(2). Take care of the different flag values, and let the 148 * NetBSD syscall do the real work. See if this operation 149 * gives the current process a controlling terminal. 150 * (XXX is this necessary?) 151 */ 152 int 153 linux_sys_open(p, v, retval) 154 struct proc *p; 155 void *v; 156 register_t *retval; 157 { 158 struct linux_sys_open_args /* { 159 syscallarg(char *) path; 160 syscallarg(int) flags; 161 syscallarg(int) mode; 162 } */ *uap = v; 163 int error, fl; 164 struct sys_open_args boa; 165 caddr_t sg; 166 167 sg = stackgap_init(p->p_emul); 168 169 fl = linux_to_bsd_ioflags(SCARG(uap, flags)); 170 171 if (fl & O_CREAT) 172 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 173 else 174 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 175 176 SCARG(&boa, path) = SCARG(uap, path); 177 SCARG(&boa, flags) = fl; 178 SCARG(&boa, mode) = SCARG(uap, mode); 179 180 if ((error = sys_open(p, &boa, retval))) 181 return error; 182 183 /* 184 * this bit from sunos_misc.c (and svr4_fcntl.c). 185 * If we are a session leader, and we don't have a controlling 186 * terminal yet, and the O_NOCTTY flag is not set, try to make 187 * this the controlling terminal. 188 */ 189 if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 190 struct filedesc *fdp = p->p_fd; 191 struct file *fp = fdp->fd_ofiles[*retval]; 192 193 /* ignore any error, just give it a try */ 194 if (fp->f_type == DTYPE_VNODE) 195 (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p); 196 } 197 return 0; 198 } 199 200 /* 201 * This appears to be part of a Linux attempt to switch to 64 bits file sizes. 202 */ 203 int 204 linux_sys_llseek(p, v, retval) 205 struct proc *p; 206 void *v; 207 register_t *retval; 208 { 209 struct linux_sys_llseek_args /* { 210 syscallarg(int) fd; 211 syscallarg(uint32_t) ohigh; 212 syscallarg(uint32_t) olow; 213 syscallarg(caddr_t) res; 214 syscallarg(int) whence; 215 } */ *uap = v; 216 struct sys_lseek_args bla; 217 int error; 218 off_t off; 219 220 off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32); 221 222 SCARG(&bla, fd) = SCARG(uap, fd); 223 SCARG(&bla, offset) = off; 224 SCARG(&bla, whence) = SCARG(uap, whence); 225 226 if ((error = sys_lseek(p, &bla, retval))) 227 return error; 228 229 if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t)))) 230 return error; 231 232 retval[0] = 0; 233 return 0; 234 } 235 236 /* 237 * The next two functions take care of converting the flock 238 * structure back and forth between Linux and NetBSD format. 239 * The only difference in the structures is the order of 240 * the fields, and the 'whence' value. 241 */ 242 static void 243 bsd_to_linux_flock(bfp, lfp) 244 struct flock *bfp; 245 struct linux_flock *lfp; 246 { 247 248 lfp->l_start = bfp->l_start; 249 lfp->l_len = bfp->l_len; 250 lfp->l_pid = bfp->l_pid; 251 lfp->l_whence = bfp->l_whence; 252 switch (bfp->l_type) { 253 case F_RDLCK: 254 lfp->l_type = LINUX_F_RDLCK; 255 break; 256 case F_UNLCK: 257 lfp->l_type = LINUX_F_UNLCK; 258 break; 259 case F_WRLCK: 260 lfp->l_type = LINUX_F_WRLCK; 261 break; 262 } 263 } 264 265 static void 266 linux_to_bsd_flock(lfp, bfp) 267 struct linux_flock *lfp; 268 struct flock *bfp; 269 { 270 271 bfp->l_start = lfp->l_start; 272 bfp->l_len = lfp->l_len; 273 bfp->l_pid = lfp->l_pid; 274 bfp->l_whence = lfp->l_whence; 275 switch (lfp->l_type) { 276 case LINUX_F_RDLCK: 277 bfp->l_type = F_RDLCK; 278 break; 279 case LINUX_F_UNLCK: 280 bfp->l_type = F_UNLCK; 281 break; 282 case LINUX_F_WRLCK: 283 bfp->l_type = F_WRLCK; 284 break; 285 } 286 } 287 288 /* 289 * Most actions in the fcntl() call are straightforward; simply 290 * pass control to the NetBSD system call. A few commands need 291 * conversions after the actual system call has done its work, 292 * because the flag values and lock structure are different. 293 */ 294 int 295 linux_sys_fcntl(p, v, retval) 296 struct proc *p; 297 void *v; 298 register_t *retval; 299 { 300 struct linux_sys_fcntl_args /* { 301 syscallarg(int) fd; 302 syscallarg(int) cmd; 303 syscallarg(void *) arg; 304 } */ *uap = v; 305 int fd, cmd, error, val; 306 caddr_t arg, sg; 307 struct linux_flock lfl; 308 struct flock *bfp, bfl; 309 struct sys_fcntl_args fca; 310 struct filedesc *fdp; 311 struct file *fp; 312 struct vnode *vp; 313 struct vattr va; 314 long pgid; 315 struct pgrp *pgrp; 316 struct tty *tp, *(*d_tty) __P((dev_t)); 317 318 fd = SCARG(uap, fd); 319 cmd = SCARG(uap, cmd); 320 arg = (caddr_t) SCARG(uap, arg); 321 322 switch (cmd) { 323 case LINUX_F_DUPFD: 324 cmd = F_DUPFD; 325 break; 326 case LINUX_F_GETFD: 327 cmd = F_GETFD; 328 break; 329 case LINUX_F_SETFD: 330 cmd = F_SETFD; 331 break; 332 case LINUX_F_GETFL: 333 SCARG(&fca, fd) = fd; 334 SCARG(&fca, cmd) = F_GETFL; 335 SCARG(&fca, arg) = arg; 336 if ((error = sys_fcntl(p, &fca, retval))) 337 return error; 338 retval[0] = bsd_to_linux_ioflags(retval[0]); 339 return 0; 340 case LINUX_F_SETFL: 341 val = linux_to_bsd_ioflags((int)SCARG(uap, arg)); 342 SCARG(&fca, fd) = fd; 343 SCARG(&fca, cmd) = F_SETFL; 344 SCARG(&fca, arg) = (caddr_t) val; 345 return sys_fcntl(p, &fca, retval); 346 case LINUX_F_GETLK: 347 sg = stackgap_init(p->p_emul); 348 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp); 349 SCARG(&fca, fd) = fd; 350 SCARG(&fca, cmd) = F_GETLK; 351 SCARG(&fca, arg) = bfp; 352 if ((error = sys_fcntl(p, &fca, retval))) 353 return error; 354 if ((error = copyin(bfp, &bfl, sizeof bfl))) 355 return error; 356 bsd_to_linux_flock(&bfl, &lfl); 357 return copyout(&lfl, arg, sizeof lfl); 358 break; 359 case LINUX_F_SETLK: 360 case LINUX_F_SETLKW: 361 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW); 362 if ((error = copyin(arg, &lfl, sizeof lfl))) 363 return error; 364 linux_to_bsd_flock(&lfl, &bfl); 365 sg = stackgap_init(p->p_emul); 366 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp); 367 if ((error = copyout(&bfl, bfp, sizeof bfl))) 368 return error; 369 SCARG(&fca, fd) = fd; 370 SCARG(&fca, cmd) = cmd; 371 SCARG(&fca, arg) = bfp; 372 return sys_fcntl(p, &fca, retval); 373 break; 374 case LINUX_F_SETOWN: 375 case LINUX_F_GETOWN: 376 /* 377 * We need to route around the normal fcntl() for these calls, 378 * since it uses TIOC{G,S}PGRP, which is too restrictive for 379 * Linux F_{G,S}ETOWN semantics. For sockets, this problem 380 * does not exist. 381 */ 382 fdp = p->p_fd; 383 if ((u_int)fd >= fdp->fd_nfiles || 384 (fp = fdp->fd_ofiles[fd]) == NULL) 385 return EBADF; 386 if (fp->f_type == DTYPE_SOCKET) { 387 cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; 388 break; 389 } 390 vp = (struct vnode *)fp->f_data; 391 if (vp->v_type != VCHR) 392 return EINVAL; 393 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) 394 return error; 395 d_tty = cdevsw[major(va.va_rdev)].d_tty; 396 if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) 397 return EINVAL; 398 if (cmd == LINUX_F_GETOWN) { 399 retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 400 return 0; 401 } 402 if ((long)arg <= 0) { 403 pgid = -(long)arg; 404 } else { 405 struct proc *p1 = pfind((long)arg); 406 if (p1 == 0) 407 return (ESRCH); 408 pgid = (long)p1->p_pgrp->pg_id; 409 } 410 pgrp = pgfind(pgid); 411 if (pgrp == NULL || pgrp->pg_session != p->p_session) 412 return EPERM; 413 tp->t_pgrp = pgrp; 414 return 0; 415 default: 416 return EOPNOTSUPP; 417 } 418 419 SCARG(&fca, fd) = fd; 420 SCARG(&fca, cmd) = cmd; 421 SCARG(&fca, arg) = arg; 422 423 return sys_fcntl(p, &fca, retval); 424 } 425 426 /* 427 * Convert a NetBSD stat structure to a Linux stat structure. 428 * Only the order of the fields and the padding in the structure 429 * is different. linux_fakedev is a machine-dependent function 430 * which optionally converts device driver major/minor numbers 431 * (XXX horrible, but what can you do against code that compares 432 * things against constant major device numbers? sigh) 433 */ 434 static void 435 bsd_to_linux_stat(bsp, lsp) 436 struct stat *bsp; 437 struct linux_stat *lsp; 438 { 439 440 lsp->lst_dev = bsp->st_dev; 441 lsp->lst_ino = bsp->st_ino; 442 lsp->lst_mode = bsp->st_mode; 443 lsp->lst_nlink = bsp->st_nlink; 444 lsp->lst_uid = bsp->st_uid; 445 lsp->lst_gid = bsp->st_gid; 446 lsp->lst_rdev = linux_fakedev(bsp->st_rdev); 447 lsp->lst_size = bsp->st_size; 448 lsp->lst_blksize = bsp->st_blksize; 449 lsp->lst_blocks = bsp->st_blocks; 450 lsp->lst_atime = bsp->st_atime; 451 lsp->lst_mtime = bsp->st_mtime; 452 lsp->lst_ctime = bsp->st_ctime; 453 } 454 455 /* 456 * The stat functions below are plain sailing. stat and lstat are handled 457 * by one function to avoid code duplication. 458 */ 459 int 460 linux_sys_fstat(p, v, retval) 461 struct proc *p; 462 void *v; 463 register_t *retval; 464 { 465 struct linux_sys_fstat_args /* { 466 syscallarg(int) fd; 467 syscallarg(linux_stat *) sp; 468 } */ *uap = v; 469 struct sys_fstat_args fsa; 470 struct linux_stat tmplst; 471 struct stat *st,tmpst; 472 caddr_t sg; 473 int error; 474 475 sg = stackgap_init(p->p_emul); 476 477 st = stackgap_alloc(&sg, sizeof (struct stat)); 478 479 SCARG(&fsa, fd) = SCARG(uap, fd); 480 SCARG(&fsa, sb) = st; 481 482 if ((error = sys_fstat(p, &fsa, retval))) 483 return error; 484 485 if ((error = copyin(st, &tmpst, sizeof tmpst))) 486 return error; 487 488 bsd_to_linux_stat(&tmpst, &tmplst); 489 490 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 491 return error; 492 493 return 0; 494 } 495 496 static int 497 linux_stat1(p, v, retval, dolstat) 498 struct proc *p; 499 void *v; 500 register_t *retval; 501 int dolstat; 502 { 503 struct sys_stat_args sa; 504 struct linux_stat tmplst; 505 struct stat *st, tmpst; 506 caddr_t sg; 507 int error; 508 struct linux_sys_stat_args *uap = v; 509 510 sg = stackgap_init(p->p_emul); 511 512 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 513 514 st = stackgap_alloc(&sg, sizeof (struct stat)); 515 SCARG(&sa, ub) = st; 516 SCARG(&sa, path) = SCARG(uap, path); 517 518 if ((error = (dolstat ? sys_lstat(p, &sa, retval) : 519 sys_stat(p, &sa, retval)))) 520 return error; 521 522 if ((error = copyin(st, &tmpst, sizeof tmpst))) 523 return error; 524 525 bsd_to_linux_stat(&tmpst, &tmplst); 526 527 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 528 return error; 529 530 return 0; 531 } 532 533 int 534 linux_sys_stat(p, v, retval) 535 struct proc *p; 536 void *v; 537 register_t *retval; 538 { 539 struct linux_sys_stat_args /* { 540 syscallarg(char *) path; 541 syscallarg(struct linux_stat *) sp; 542 } */ *uap = v; 543 544 return linux_stat1(p, uap, retval, 0); 545 } 546 547 int 548 linux_sys_lstat(p, v, retval) 549 struct proc *p; 550 void *v; 551 register_t *retval; 552 { 553 struct linux_sys_lstat_args /* { 554 syscallarg(char *) path; 555 syscallarg(struct linux_stat *) sp; 556 } */ *uap = v; 557 558 return linux_stat1(p, uap, retval, 1); 559 } 560 561 /* 562 * The following syscalls are mostly here because of the alternate path check. 563 */ 564 int 565 linux_sys_access(p, v, retval) 566 struct proc *p; 567 void *v; 568 register_t *retval; 569 { 570 struct linux_sys_access_args /* { 571 syscallarg(char *) path; 572 syscallarg(int) flags; 573 } */ *uap = v; 574 caddr_t sg = stackgap_init(p->p_emul); 575 576 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 577 578 return sys_access(p, uap, retval); 579 } 580 581 int 582 linux_sys_unlink(p, v, retval) 583 struct proc *p; 584 void *v; 585 register_t *retval; 586 587 { 588 struct linux_sys_unlink_args /* { 589 syscallarg(char *) path; 590 } */ *uap = v; 591 caddr_t sg = stackgap_init(p->p_emul); 592 593 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 594 595 return sys_unlink(p, uap, retval); 596 } 597 598 int 599 linux_sys_chdir(p, v, retval) 600 struct proc *p; 601 void *v; 602 register_t *retval; 603 { 604 struct linux_sys_chdir_args /* { 605 syscallarg(char *) path; 606 } */ *uap = v; 607 caddr_t sg = stackgap_init(p->p_emul); 608 609 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 610 611 return sys_chdir(p, uap, retval); 612 } 613 614 int 615 linux_sys_mknod(p, v, retval) 616 struct proc *p; 617 void *v; 618 register_t *retval; 619 { 620 struct linux_sys_mknod_args /* { 621 syscallarg(char *) path; 622 syscallarg(int) mode; 623 syscallarg(int) dev; 624 } */ *uap = v; 625 caddr_t sg = stackgap_init(p->p_emul); 626 struct sys_mkfifo_args bma; 627 628 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 629 630 /* 631 * BSD handles FIFOs seperately 632 */ 633 if (SCARG(uap, mode) & S_IFIFO) { 634 SCARG(&bma, path) = SCARG(uap, path); 635 SCARG(&bma, mode) = SCARG(uap, mode); 636 return sys_mkfifo(p, uap, retval); 637 } else 638 return sys_mknod(p, uap, retval); 639 } 640 641 int 642 linux_sys_chmod(p, v, retval) 643 struct proc *p; 644 void *v; 645 register_t *retval; 646 { 647 struct linux_sys_chmod_args /* { 648 syscallarg(char *) path; 649 syscallarg(int) mode; 650 } */ *uap = v; 651 caddr_t sg = stackgap_init(p->p_emul); 652 653 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 654 655 return sys_chmod(p, uap, retval); 656 } 657 658 int 659 linux_sys_chown(p, v, retval) 660 struct proc *p; 661 void *v; 662 register_t *retval; 663 { 664 struct linux_sys_chown_args /* { 665 syscallarg(char *) path; 666 syscallarg(int) uid; 667 syscallarg(int) gid; 668 } */ *uap = v; 669 struct sys_chown_args bca; 670 caddr_t sg = stackgap_init(p->p_emul); 671 672 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 673 674 SCARG(&bca, path) = SCARG(uap, path); 675 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 676 (uid_t)-1 : SCARG(uap, uid); 677 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 678 (gid_t)-1 : SCARG(uap, gid); 679 680 return sys_chown(p, &bca, retval); 681 } 682 683 int 684 linux_sys_fchown(p, v, retval) 685 struct proc *p; 686 void *v; 687 register_t *retval; 688 { 689 struct linux_sys_fchown_args /* { 690 syscallarg(int) fd; 691 syscallarg(int) uid; 692 syscallarg(int) gid; 693 } */ *uap = v; 694 struct sys_fchown_args bfa; 695 696 SCARG(&bfa, fd) = SCARG(uap, fd); 697 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 698 (uid_t)-1 : SCARG(uap, uid); 699 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 700 (gid_t)-1 : SCARG(uap, gid); 701 702 return sys_fchown(p, &bfa, retval); 703 } 704 705 int 706 linux_sys_rename(p, v, retval) 707 struct proc *p; 708 void *v; 709 register_t *retval; 710 { 711 struct linux_sys_rename_args /* { 712 syscallarg(char *) from; 713 syscallarg(char *) to; 714 } */ *uap = v; 715 caddr_t sg = stackgap_init(p->p_emul); 716 717 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 718 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 719 720 return sys_rename(p, uap, retval); 721 } 722 723 int 724 linux_sys_mkdir(p, v, retval) 725 struct proc *p; 726 void *v; 727 register_t *retval; 728 { 729 struct linux_sys_mkdir_args /* { 730 syscallarg(char *) path; 731 syscallarg(int) mode; 732 } */ *uap = v; 733 caddr_t sg = stackgap_init(p->p_emul); 734 735 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 736 737 return sys_mkdir(p, uap, retval); 738 } 739 740 int 741 linux_sys_rmdir(p, v, retval) 742 struct proc *p; 743 void *v; 744 register_t *retval; 745 { 746 struct linux_sys_rmdir_args /* { 747 syscallarg(char *) path; 748 } */ *uap = v; 749 caddr_t sg = stackgap_init(p->p_emul); 750 751 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 752 753 return sys_rmdir(p, uap, retval); 754 } 755 756 int 757 linux_sys_symlink(p, v, retval) 758 struct proc *p; 759 void *v; 760 register_t *retval; 761 { 762 struct linux_sys_symlink_args /* { 763 syscallarg(char *) path; 764 syscallarg(char *) to; 765 } */ *uap = v; 766 caddr_t sg = stackgap_init(p->p_emul); 767 768 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 769 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 770 771 return sys_symlink(p, uap, retval); 772 } 773 774 int 775 linux_sys_readlink(p, v, retval) 776 struct proc *p; 777 void *v; 778 register_t *retval; 779 { 780 struct linux_sys_readlink_args /* { 781 syscallarg(char *) name; 782 syscallarg(char *) buf; 783 syscallarg(int) count; 784 } */ *uap = v; 785 caddr_t sg = stackgap_init(p->p_emul); 786 787 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name)); 788 789 return sys_readlink(p, uap, retval); 790 } 791 792 int 793 linux_sys_truncate(p, v, retval) 794 struct proc *p; 795 void *v; 796 register_t *retval; 797 { 798 struct linux_sys_truncate_args /* { 799 syscallarg(char *) path; 800 syscallarg(long) length; 801 } */ *uap = v; 802 caddr_t sg = stackgap_init(p->p_emul); 803 804 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 805 806 return compat_43_sys_truncate(p, uap, retval); 807 } 808 809 /* 810 * This is just fsync() for now (just as it is in the Linux kernel) 811 */ 812 int 813 linux_sys_fdatasync(p, v, retval) 814 struct proc *p; 815 void *v; 816 register_t *retval; 817 { 818 #ifdef notdef 819 struct linux_sys_fdatasync_args /* { 820 syscallarg(int) fd; 821 } */ *uap = v; 822 #endif 823 return sys_fsync(p, v, retval); 824 } 825