1 /* $NetBSD: linux_file.c,v 1.21 1997/10/20 22:05:16 thorpej 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 if ((error = copyin(arg, &lfl, sizeof lfl))) 350 return error; 351 linux_to_bsd_flock(&lfl, &bfl); 352 if ((error = copyout(&bfl, bfp, sizeof bfl))) 353 return error; 354 SCARG(&fca, fd) = fd; 355 SCARG(&fca, cmd) = F_GETLK; 356 SCARG(&fca, arg) = bfp; 357 if ((error = sys_fcntl(p, &fca, retval))) 358 return error; 359 if ((error = copyin(bfp, &bfl, sizeof bfl))) 360 return error; 361 bsd_to_linux_flock(&bfl, &lfl); 362 return copyout(&lfl, arg, sizeof lfl); 363 break; 364 case LINUX_F_SETLK: 365 case LINUX_F_SETLKW: 366 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW); 367 if ((error = copyin(arg, &lfl, sizeof lfl))) 368 return error; 369 linux_to_bsd_flock(&lfl, &bfl); 370 sg = stackgap_init(p->p_emul); 371 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp); 372 if ((error = copyout(&bfl, bfp, sizeof bfl))) 373 return error; 374 SCARG(&fca, fd) = fd; 375 SCARG(&fca, cmd) = cmd; 376 SCARG(&fca, arg) = bfp; 377 return sys_fcntl(p, &fca, retval); 378 break; 379 case LINUX_F_SETOWN: 380 case LINUX_F_GETOWN: 381 /* 382 * We need to route around the normal fcntl() for these calls, 383 * since it uses TIOC{G,S}PGRP, which is too restrictive for 384 * Linux F_{G,S}ETOWN semantics. For sockets, this problem 385 * does not exist. 386 */ 387 fdp = p->p_fd; 388 if ((u_int)fd >= fdp->fd_nfiles || 389 (fp = fdp->fd_ofiles[fd]) == NULL) 390 return EBADF; 391 if (fp->f_type == DTYPE_SOCKET) { 392 cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; 393 break; 394 } 395 vp = (struct vnode *)fp->f_data; 396 if (vp->v_type != VCHR) 397 return EINVAL; 398 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) 399 return error; 400 d_tty = cdevsw[major(va.va_rdev)].d_tty; 401 if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) 402 return EINVAL; 403 if (cmd == LINUX_F_GETOWN) { 404 retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 405 return 0; 406 } 407 if ((long)arg <= 0) { 408 pgid = -(long)arg; 409 } else { 410 struct proc *p1 = pfind((long)arg); 411 if (p1 == 0) 412 return (ESRCH); 413 pgid = (long)p1->p_pgrp->pg_id; 414 } 415 pgrp = pgfind(pgid); 416 if (pgrp == NULL || pgrp->pg_session != p->p_session) 417 return EPERM; 418 tp->t_pgrp = pgrp; 419 return 0; 420 default: 421 return EOPNOTSUPP; 422 } 423 424 SCARG(&fca, fd) = fd; 425 SCARG(&fca, cmd) = cmd; 426 SCARG(&fca, arg) = arg; 427 428 return sys_fcntl(p, &fca, retval); 429 } 430 431 /* 432 * Convert a NetBSD stat structure to a Linux stat structure. 433 * Only the order of the fields and the padding in the structure 434 * is different. linux_fakedev is a machine-dependent function 435 * which optionally converts device driver major/minor numbers 436 * (XXX horrible, but what can you do against code that compares 437 * things against constant major device numbers? sigh) 438 */ 439 static void 440 bsd_to_linux_stat(bsp, lsp) 441 struct stat *bsp; 442 struct linux_stat *lsp; 443 { 444 445 lsp->lst_dev = bsp->st_dev; 446 lsp->lst_ino = bsp->st_ino; 447 lsp->lst_mode = (linux_mode_t)bsp->st_mode; 448 if (bsp->st_nlink >= (1 << 15)) 449 lsp->lst_nlink = (1 << 15) - 1; 450 else 451 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink; 452 lsp->lst_uid = bsp->st_uid; 453 lsp->lst_gid = bsp->st_gid; 454 lsp->lst_rdev = linux_fakedev(bsp->st_rdev); 455 lsp->lst_size = bsp->st_size; 456 lsp->lst_blksize = bsp->st_blksize; 457 lsp->lst_blocks = bsp->st_blocks; 458 lsp->lst_atime = bsp->st_atime; 459 lsp->lst_mtime = bsp->st_mtime; 460 lsp->lst_ctime = bsp->st_ctime; 461 } 462 463 /* 464 * The stat functions below are plain sailing. stat and lstat are handled 465 * by one function to avoid code duplication. 466 */ 467 int 468 linux_sys_fstat(p, v, retval) 469 struct proc *p; 470 void *v; 471 register_t *retval; 472 { 473 struct linux_sys_fstat_args /* { 474 syscallarg(int) fd; 475 syscallarg(linux_stat *) sp; 476 } */ *uap = v; 477 struct sys___fstat13_args fsa; 478 struct linux_stat tmplst; 479 struct stat *st,tmpst; 480 caddr_t sg; 481 int error; 482 483 sg = stackgap_init(p->p_emul); 484 485 st = stackgap_alloc(&sg, sizeof (struct stat)); 486 487 SCARG(&fsa, fd) = SCARG(uap, fd); 488 SCARG(&fsa, sb) = st; 489 490 if ((error = sys___fstat13(p, &fsa, retval))) 491 return error; 492 493 if ((error = copyin(st, &tmpst, sizeof tmpst))) 494 return error; 495 496 bsd_to_linux_stat(&tmpst, &tmplst); 497 498 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 499 return error; 500 501 return 0; 502 } 503 504 static int 505 linux_stat1(p, v, retval, dolstat) 506 struct proc *p; 507 void *v; 508 register_t *retval; 509 int dolstat; 510 { 511 struct sys___stat13_args sa; 512 struct linux_stat tmplst; 513 struct stat *st, tmpst; 514 caddr_t sg; 515 int error; 516 struct linux_sys_stat_args *uap = v; 517 518 sg = stackgap_init(p->p_emul); 519 520 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 521 522 st = stackgap_alloc(&sg, sizeof (struct stat)); 523 SCARG(&sa, ub) = st; 524 SCARG(&sa, path) = SCARG(uap, path); 525 526 if ((error = (dolstat ? sys___lstat13(p, &sa, retval) : 527 sys___stat13(p, &sa, retval)))) 528 return error; 529 530 if ((error = copyin(st, &tmpst, sizeof tmpst))) 531 return error; 532 533 bsd_to_linux_stat(&tmpst, &tmplst); 534 535 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 536 return error; 537 538 return 0; 539 } 540 541 int 542 linux_sys_stat(p, v, retval) 543 struct proc *p; 544 void *v; 545 register_t *retval; 546 { 547 struct linux_sys_stat_args /* { 548 syscallarg(char *) path; 549 syscallarg(struct linux_stat *) sp; 550 } */ *uap = v; 551 552 return linux_stat1(p, uap, retval, 0); 553 } 554 555 int 556 linux_sys_lstat(p, v, retval) 557 struct proc *p; 558 void *v; 559 register_t *retval; 560 { 561 struct linux_sys_lstat_args /* { 562 syscallarg(char *) path; 563 syscallarg(struct linux_stat *) sp; 564 } */ *uap = v; 565 566 return linux_stat1(p, uap, retval, 1); 567 } 568 569 /* 570 * The following syscalls are mostly here because of the alternate path check. 571 */ 572 int 573 linux_sys_access(p, v, retval) 574 struct proc *p; 575 void *v; 576 register_t *retval; 577 { 578 struct linux_sys_access_args /* { 579 syscallarg(char *) path; 580 syscallarg(int) flags; 581 } */ *uap = v; 582 caddr_t sg = stackgap_init(p->p_emul); 583 584 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 585 586 return sys_access(p, uap, retval); 587 } 588 589 int 590 linux_sys_unlink(p, v, retval) 591 struct proc *p; 592 void *v; 593 register_t *retval; 594 595 { 596 struct linux_sys_unlink_args /* { 597 syscallarg(char *) path; 598 } */ *uap = v; 599 caddr_t sg = stackgap_init(p->p_emul); 600 601 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 602 603 return sys_unlink(p, uap, retval); 604 } 605 606 int 607 linux_sys_chdir(p, v, retval) 608 struct proc *p; 609 void *v; 610 register_t *retval; 611 { 612 struct linux_sys_chdir_args /* { 613 syscallarg(char *) path; 614 } */ *uap = v; 615 caddr_t sg = stackgap_init(p->p_emul); 616 617 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 618 619 return sys_chdir(p, uap, retval); 620 } 621 622 int 623 linux_sys_mknod(p, v, retval) 624 struct proc *p; 625 void *v; 626 register_t *retval; 627 { 628 struct linux_sys_mknod_args /* { 629 syscallarg(char *) path; 630 syscallarg(int) mode; 631 syscallarg(int) dev; 632 } */ *uap = v; 633 caddr_t sg = stackgap_init(p->p_emul); 634 struct sys_mkfifo_args bma; 635 636 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 637 638 /* 639 * BSD handles FIFOs seperately 640 */ 641 if (SCARG(uap, mode) & S_IFIFO) { 642 SCARG(&bma, path) = SCARG(uap, path); 643 SCARG(&bma, mode) = SCARG(uap, mode); 644 return sys_mkfifo(p, uap, retval); 645 } else 646 return sys_mknod(p, uap, retval); 647 } 648 649 int 650 linux_sys_chmod(p, v, retval) 651 struct proc *p; 652 void *v; 653 register_t *retval; 654 { 655 struct linux_sys_chmod_args /* { 656 syscallarg(char *) path; 657 syscallarg(int) mode; 658 } */ *uap = v; 659 caddr_t sg = stackgap_init(p->p_emul); 660 661 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 662 663 return sys_chmod(p, uap, retval); 664 } 665 666 int 667 linux_sys_chown(p, v, retval) 668 struct proc *p; 669 void *v; 670 register_t *retval; 671 { 672 struct linux_sys_chown_args /* { 673 syscallarg(char *) path; 674 syscallarg(int) uid; 675 syscallarg(int) gid; 676 } */ *uap = v; 677 struct sys_chown_args bca; 678 caddr_t sg = stackgap_init(p->p_emul); 679 680 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 681 682 SCARG(&bca, path) = SCARG(uap, path); 683 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 684 (uid_t)-1 : SCARG(uap, uid); 685 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 686 (gid_t)-1 : SCARG(uap, gid); 687 688 return sys_chown(p, &bca, retval); 689 } 690 691 int 692 linux_sys_fchown(p, v, retval) 693 struct proc *p; 694 void *v; 695 register_t *retval; 696 { 697 struct linux_sys_fchown_args /* { 698 syscallarg(int) fd; 699 syscallarg(int) uid; 700 syscallarg(int) gid; 701 } */ *uap = v; 702 struct sys_fchown_args bfa; 703 704 SCARG(&bfa, fd) = SCARG(uap, fd); 705 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 706 (uid_t)-1 : SCARG(uap, uid); 707 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 708 (gid_t)-1 : SCARG(uap, gid); 709 710 return sys_fchown(p, &bfa, retval); 711 } 712 713 int 714 linux_sys_rename(p, v, retval) 715 struct proc *p; 716 void *v; 717 register_t *retval; 718 { 719 struct linux_sys_rename_args /* { 720 syscallarg(char *) from; 721 syscallarg(char *) to; 722 } */ *uap = v; 723 caddr_t sg = stackgap_init(p->p_emul); 724 725 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 726 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 727 728 return sys_posix_rename(p, uap, retval); 729 } 730 731 int 732 linux_sys_mkdir(p, v, retval) 733 struct proc *p; 734 void *v; 735 register_t *retval; 736 { 737 struct linux_sys_mkdir_args /* { 738 syscallarg(char *) path; 739 syscallarg(int) mode; 740 } */ *uap = v; 741 caddr_t sg = stackgap_init(p->p_emul); 742 743 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 744 745 return sys_mkdir(p, uap, retval); 746 } 747 748 int 749 linux_sys_rmdir(p, v, retval) 750 struct proc *p; 751 void *v; 752 register_t *retval; 753 { 754 struct linux_sys_rmdir_args /* { 755 syscallarg(char *) path; 756 } */ *uap = v; 757 caddr_t sg = stackgap_init(p->p_emul); 758 759 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 760 761 return sys_rmdir(p, uap, retval); 762 } 763 764 int 765 linux_sys_symlink(p, v, retval) 766 struct proc *p; 767 void *v; 768 register_t *retval; 769 { 770 struct linux_sys_symlink_args /* { 771 syscallarg(char *) path; 772 syscallarg(char *) to; 773 } */ *uap = v; 774 caddr_t sg = stackgap_init(p->p_emul); 775 776 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 777 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 778 779 return sys_symlink(p, uap, retval); 780 } 781 782 int 783 linux_sys_readlink(p, v, retval) 784 struct proc *p; 785 void *v; 786 register_t *retval; 787 { 788 struct linux_sys_readlink_args /* { 789 syscallarg(char *) name; 790 syscallarg(char *) buf; 791 syscallarg(int) count; 792 } */ *uap = v; 793 caddr_t sg = stackgap_init(p->p_emul); 794 795 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name)); 796 797 return sys_readlink(p, uap, retval); 798 } 799 800 int 801 linux_sys_truncate(p, v, retval) 802 struct proc *p; 803 void *v; 804 register_t *retval; 805 { 806 struct linux_sys_truncate_args /* { 807 syscallarg(char *) path; 808 syscallarg(long) length; 809 } */ *uap = v; 810 caddr_t sg = stackgap_init(p->p_emul); 811 812 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 813 814 return compat_43_sys_truncate(p, uap, retval); 815 } 816 817 /* 818 * This is just fsync() for now (just as it is in the Linux kernel) 819 */ 820 int 821 linux_sys_fdatasync(p, v, retval) 822 struct proc *p; 823 void *v; 824 register_t *retval; 825 { 826 #ifdef notdef 827 struct linux_sys_fdatasync_args /* { 828 syscallarg(int) fd; 829 } */ *uap = v; 830 #endif 831 return sys_fsync(p, v, retval); 832 } 833