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