1 /* $NetBSD: linux_llseek.c,v 1.20 1997/10/19 18:35:19 mycroft 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_fstat_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_fstat(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_stat_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_lstat(p, &sa, retval) : 527 sys_stat(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 mfa; 635 struct sys_mknod_args mna; 636 637 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 638 639 /* 640 * BSD handles FIFOs seperately 641 */ 642 if (S_ISFIFO(SCARG(uap, mode))) { 643 SCARG(&mfa, path) = SCARG(uap, path); 644 SCARG(&mfa, mode) = SCARG(uap, mode); 645 return (sys_mkfifo(p, &mfa, retval)); 646 } else { 647 SCARG(&mna, path) = SCARG(uap, path); 648 SCARG(&mna, mode) = SCARG(uap, mode); 649 SCARG(&mna, dev) = SCARG(uap, dev); 650 return (sys_mknod(p, &mna, retval)); 651 } 652 } 653 654 int 655 linux_sys_chmod(p, v, retval) 656 struct proc *p; 657 void *v; 658 register_t *retval; 659 { 660 struct linux_sys_chmod_args /* { 661 syscallarg(char *) path; 662 syscallarg(int) mode; 663 } */ *uap = v; 664 caddr_t sg = stackgap_init(p->p_emul); 665 666 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 667 668 return sys_chmod(p, uap, retval); 669 } 670 671 int 672 linux_sys_chown(p, v, retval) 673 struct proc *p; 674 void *v; 675 register_t *retval; 676 { 677 struct linux_sys_chown_args /* { 678 syscallarg(char *) path; 679 syscallarg(int) uid; 680 syscallarg(int) gid; 681 } */ *uap = v; 682 struct sys_chown_args bca; 683 caddr_t sg = stackgap_init(p->p_emul); 684 685 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 686 687 SCARG(&bca, path) = SCARG(uap, path); 688 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 689 (uid_t)-1 : SCARG(uap, uid); 690 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 691 (gid_t)-1 : SCARG(uap, gid); 692 693 return sys_chown(p, &bca, retval); 694 } 695 696 int 697 linux_sys_fchown(p, v, retval) 698 struct proc *p; 699 void *v; 700 register_t *retval; 701 { 702 struct linux_sys_fchown_args /* { 703 syscallarg(int) fd; 704 syscallarg(int) uid; 705 syscallarg(int) gid; 706 } */ *uap = v; 707 struct sys_fchown_args bfa; 708 709 SCARG(&bfa, fd) = SCARG(uap, fd); 710 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 711 (uid_t)-1 : SCARG(uap, uid); 712 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 713 (gid_t)-1 : SCARG(uap, gid); 714 715 return sys_fchown(p, &bfa, retval); 716 } 717 718 int 719 linux_sys_rename(p, v, retval) 720 struct proc *p; 721 void *v; 722 register_t *retval; 723 { 724 struct linux_sys_rename_args /* { 725 syscallarg(char *) from; 726 syscallarg(char *) to; 727 } */ *uap = v; 728 caddr_t sg = stackgap_init(p->p_emul); 729 730 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 731 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 732 733 return sys_posix_rename(p, uap, retval); 734 } 735 736 int 737 linux_sys_mkdir(p, v, retval) 738 struct proc *p; 739 void *v; 740 register_t *retval; 741 { 742 struct linux_sys_mkdir_args /* { 743 syscallarg(char *) path; 744 syscallarg(int) mode; 745 } */ *uap = v; 746 caddr_t sg = stackgap_init(p->p_emul); 747 748 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 749 750 return sys_mkdir(p, uap, retval); 751 } 752 753 int 754 linux_sys_rmdir(p, v, retval) 755 struct proc *p; 756 void *v; 757 register_t *retval; 758 { 759 struct linux_sys_rmdir_args /* { 760 syscallarg(char *) path; 761 } */ *uap = v; 762 caddr_t sg = stackgap_init(p->p_emul); 763 764 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 765 766 return sys_rmdir(p, uap, retval); 767 } 768 769 int 770 linux_sys_symlink(p, v, retval) 771 struct proc *p; 772 void *v; 773 register_t *retval; 774 { 775 struct linux_sys_symlink_args /* { 776 syscallarg(char *) path; 777 syscallarg(char *) to; 778 } */ *uap = v; 779 caddr_t sg = stackgap_init(p->p_emul); 780 781 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 782 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 783 784 return sys_symlink(p, uap, retval); 785 } 786 787 int 788 linux_sys_readlink(p, v, retval) 789 struct proc *p; 790 void *v; 791 register_t *retval; 792 { 793 struct linux_sys_readlink_args /* { 794 syscallarg(char *) name; 795 syscallarg(char *) buf; 796 syscallarg(int) count; 797 } */ *uap = v; 798 caddr_t sg = stackgap_init(p->p_emul); 799 800 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name)); 801 802 return sys_readlink(p, uap, retval); 803 } 804 805 int 806 linux_sys_truncate(p, v, retval) 807 struct proc *p; 808 void *v; 809 register_t *retval; 810 { 811 struct linux_sys_truncate_args /* { 812 syscallarg(char *) path; 813 syscallarg(long) length; 814 } */ *uap = v; 815 caddr_t sg = stackgap_init(p->p_emul); 816 817 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 818 819 return compat_43_sys_truncate(p, uap, retval); 820 } 821 822 /* 823 * This is just fsync() for now (just as it is in the Linux kernel) 824 */ 825 int 826 linux_sys_fdatasync(p, v, retval) 827 struct proc *p; 828 void *v; 829 register_t *retval; 830 { 831 #ifdef notdef 832 struct linux_sys_fdatasync_args /* { 833 syscallarg(int) fd; 834 } */ *uap = v; 835 #endif 836 return sys_fsync(p, v, retval); 837 } 838