1 /* $NetBSD: linux_file.c,v 1.28 1999/12/05 21:24:30 tron Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Functions in multiarch: 41 * linux_sys_llseek : linux_llseek.c 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/namei.h> 47 #include <sys/proc.h> 48 #include <sys/file.h> 49 #include <sys/stat.h> 50 #include <sys/filedesc.h> 51 #include <sys/ioctl.h> 52 #include <sys/kernel.h> 53 #include <sys/mount.h> 54 #include <sys/malloc.h> 55 #include <sys/vnode.h> 56 #include <sys/tty.h> 57 #include <sys/conf.h> 58 59 #include <sys/syscallargs.h> 60 61 #include <compat/linux/common/linux_types.h> 62 #include <compat/linux/common/linux_signal.h> 63 #include <compat/linux/common/linux_fcntl.h> 64 #include <compat/linux/common/linux_util.h> 65 #include <compat/linux/common/linux_machdep.h> 66 67 #include <compat/linux/linux_syscallargs.h> 68 69 static int linux_to_bsd_ioflags __P((int)); 70 static int bsd_to_linux_ioflags __P((int)); 71 static void bsd_to_linux_flock __P((struct flock *, struct linux_flock *)); 72 static void linux_to_bsd_flock __P((struct linux_flock *, struct flock *)); 73 static void bsd_to_linux_stat __P((struct stat *, struct linux_stat *)); 74 static int linux_stat1 __P((struct proc *, void *, register_t *, int)); 75 76 /* 77 * Some file-related calls are handled here. The usual flag conversion 78 * an structure conversion is done, and alternate emul path searching. 79 */ 80 81 /* 82 * The next two functions convert between the Linux and NetBSD values 83 * of the flags used in open(2) and fcntl(2). 84 */ 85 static int 86 linux_to_bsd_ioflags(lflags) 87 int lflags; 88 { 89 int res = 0; 90 91 res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY); 92 res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY); 93 res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR); 94 res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT); 95 res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL); 96 res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY); 97 res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC); 98 res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY); 99 res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC); 100 res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC); 101 res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND); 102 103 return res; 104 } 105 106 static int 107 bsd_to_linux_ioflags(bflags) 108 int bflags; 109 { 110 int res = 0; 111 112 res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY); 113 res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY); 114 res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR); 115 res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT); 116 res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL); 117 res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY); 118 res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC); 119 res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY); 120 res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC); 121 res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC); 122 res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND); 123 124 return res; 125 } 126 127 /* 128 * creat(2) is an obsolete function, but it's present as a Linux 129 * system call, so let's deal with it. 130 * 131 * Note: On the Alpha this doesn't really exist in Linux, but it's defined 132 * in syscalls.master anyway so this doesn't have to be special cased. 133 * 134 * Just call open(2) with the TRUNC, CREAT and WRONLY flags. 135 */ 136 int 137 linux_sys_creat(p, v, retval) 138 struct proc *p; 139 void *v; 140 register_t *retval; 141 { 142 struct linux_sys_creat_args /* { 143 syscallarg(const char *) path; 144 syscallarg(int) mode; 145 } */ *uap = v; 146 struct sys_open_args oa; 147 caddr_t sg; 148 149 sg = stackgap_init(p->p_emul); 150 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 151 152 SCARG(&oa, path) = SCARG(uap, path); 153 SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY; 154 SCARG(&oa, mode) = SCARG(uap, mode); 155 156 return sys_open(p, &oa, retval); 157 } 158 159 /* 160 * open(2). Take care of the different flag values, and let the 161 * NetBSD syscall do the real work. See if this operation 162 * gives the current process a controlling terminal. 163 * (XXX is this necessary?) 164 */ 165 int 166 linux_sys_open(p, v, retval) 167 struct proc *p; 168 void *v; 169 register_t *retval; 170 { 171 struct linux_sys_open_args /* { 172 syscallarg(const char *) path; 173 syscallarg(int) flags; 174 syscallarg(int) mode; 175 } */ *uap = v; 176 int error, fl; 177 struct sys_open_args boa; 178 caddr_t sg; 179 180 sg = stackgap_init(p->p_emul); 181 182 fl = linux_to_bsd_ioflags(SCARG(uap, flags)); 183 184 if (fl & O_CREAT) 185 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 186 else 187 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 188 189 SCARG(&boa, path) = SCARG(uap, path); 190 SCARG(&boa, flags) = fl; 191 SCARG(&boa, mode) = SCARG(uap, mode); 192 193 if ((error = sys_open(p, &boa, retval))) 194 return error; 195 196 /* 197 * this bit from sunos_misc.c (and svr4_fcntl.c). 198 * If we are a session leader, and we don't have a controlling 199 * terminal yet, and the O_NOCTTY flag is not set, try to make 200 * this the controlling terminal. 201 */ 202 if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) { 203 struct filedesc *fdp = p->p_fd; 204 struct file *fp = fdp->fd_ofiles[*retval]; 205 206 /* ignore any error, just give it a try */ 207 if (fp->f_type == DTYPE_VNODE) 208 (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p); 209 } 210 return 0; 211 } 212 213 /* 214 * The next two functions take care of converting the flock 215 * structure back and forth between Linux and NetBSD format. 216 * The only difference in the structures is the order of 217 * the fields, and the 'whence' value. 218 */ 219 static void 220 bsd_to_linux_flock(bfp, lfp) 221 struct flock *bfp; 222 struct linux_flock *lfp; 223 { 224 225 lfp->l_start = bfp->l_start; 226 lfp->l_len = bfp->l_len; 227 lfp->l_pid = bfp->l_pid; 228 lfp->l_whence = bfp->l_whence; 229 switch (bfp->l_type) { 230 case F_RDLCK: 231 lfp->l_type = LINUX_F_RDLCK; 232 break; 233 case F_UNLCK: 234 lfp->l_type = LINUX_F_UNLCK; 235 break; 236 case F_WRLCK: 237 lfp->l_type = LINUX_F_WRLCK; 238 break; 239 } 240 } 241 242 static void 243 linux_to_bsd_flock(lfp, bfp) 244 struct linux_flock *lfp; 245 struct flock *bfp; 246 { 247 248 bfp->l_start = lfp->l_start; 249 bfp->l_len = lfp->l_len; 250 bfp->l_pid = lfp->l_pid; 251 bfp->l_whence = lfp->l_whence; 252 switch (lfp->l_type) { 253 case LINUX_F_RDLCK: 254 bfp->l_type = F_RDLCK; 255 break; 256 case LINUX_F_UNLCK: 257 bfp->l_type = F_UNLCK; 258 break; 259 case LINUX_F_WRLCK: 260 bfp->l_type = F_WRLCK; 261 break; 262 } 263 } 264 265 /* 266 * Most actions in the fcntl() call are straightforward; simply 267 * pass control to the NetBSD system call. A few commands need 268 * conversions after the actual system call has done its work, 269 * because the flag values and lock structure are different. 270 */ 271 int 272 linux_sys_fcntl(p, v, retval) 273 struct proc *p; 274 void *v; 275 register_t *retval; 276 { 277 struct linux_sys_fcntl_args /* { 278 syscallarg(int) fd; 279 syscallarg(int) cmd; 280 syscallarg(void *) arg; 281 } */ *uap = v; 282 int fd, cmd, error; 283 u_long val; 284 caddr_t arg, sg; 285 struct linux_flock lfl; 286 struct flock *bfp, bfl; 287 struct sys_fcntl_args fca; 288 struct filedesc *fdp; 289 struct file *fp; 290 struct vnode *vp; 291 struct vattr va; 292 long pgid; 293 struct pgrp *pgrp; 294 struct tty *tp, *(*d_tty) __P((dev_t)); 295 296 fd = SCARG(uap, fd); 297 cmd = SCARG(uap, cmd); 298 arg = (caddr_t) SCARG(uap, arg); 299 300 switch (cmd) { 301 case LINUX_F_DUPFD: 302 cmd = F_DUPFD; 303 break; 304 case LINUX_F_GETFD: 305 cmd = F_GETFD; 306 break; 307 case LINUX_F_SETFD: 308 cmd = F_SETFD; 309 break; 310 case LINUX_F_GETFL: 311 SCARG(&fca, fd) = fd; 312 SCARG(&fca, cmd) = F_GETFL; 313 SCARG(&fca, arg) = arg; 314 if ((error = sys_fcntl(p, &fca, retval))) 315 return error; 316 retval[0] = bsd_to_linux_ioflags(retval[0]); 317 return 0; 318 case LINUX_F_SETFL: 319 val = linux_to_bsd_ioflags((unsigned long)SCARG(uap, arg)); 320 SCARG(&fca, fd) = fd; 321 SCARG(&fca, cmd) = F_SETFL; 322 SCARG(&fca, arg) = (caddr_t) val; 323 return sys_fcntl(p, &fca, retval); 324 case LINUX_F_GETLK: 325 sg = stackgap_init(p->p_emul); 326 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp); 327 if ((error = copyin(arg, &lfl, sizeof lfl))) 328 return error; 329 linux_to_bsd_flock(&lfl, &bfl); 330 if ((error = copyout(&bfl, bfp, sizeof bfl))) 331 return error; 332 SCARG(&fca, fd) = fd; 333 SCARG(&fca, cmd) = F_GETLK; 334 SCARG(&fca, arg) = bfp; 335 if ((error = sys_fcntl(p, &fca, retval))) 336 return error; 337 if ((error = copyin(bfp, &bfl, sizeof bfl))) 338 return error; 339 bsd_to_linux_flock(&bfl, &lfl); 340 return copyout(&lfl, arg, sizeof lfl); 341 break; 342 case LINUX_F_SETLK: 343 case LINUX_F_SETLKW: 344 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW); 345 if ((error = copyin(arg, &lfl, sizeof lfl))) 346 return error; 347 linux_to_bsd_flock(&lfl, &bfl); 348 sg = stackgap_init(p->p_emul); 349 bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp); 350 if ((error = copyout(&bfl, bfp, sizeof bfl))) 351 return error; 352 SCARG(&fca, fd) = fd; 353 SCARG(&fca, cmd) = cmd; 354 SCARG(&fca, arg) = bfp; 355 return sys_fcntl(p, &fca, retval); 356 break; 357 case LINUX_F_SETOWN: 358 case LINUX_F_GETOWN: 359 /* 360 * We need to route around the normal fcntl() for these calls, 361 * since it uses TIOC{G,S}PGRP, which is too restrictive for 362 * Linux F_{G,S}ETOWN semantics. For sockets, this problem 363 * does not exist. 364 */ 365 fdp = p->p_fd; 366 if ((u_int)fd >= fdp->fd_nfiles || 367 (fp = fdp->fd_ofiles[fd]) == NULL) 368 return EBADF; 369 if (fp->f_type == DTYPE_SOCKET) { 370 cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; 371 break; 372 } 373 vp = (struct vnode *)fp->f_data; 374 if (vp->v_type != VCHR) 375 return EINVAL; 376 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) 377 return error; 378 d_tty = cdevsw[major(va.va_rdev)].d_tty; 379 if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) 380 return EINVAL; 381 if (cmd == LINUX_F_GETOWN) { 382 retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID; 383 return 0; 384 } 385 if ((long)arg <= 0) { 386 pgid = -(long)arg; 387 } else { 388 struct proc *p1 = pfind((long)arg); 389 if (p1 == 0) 390 return (ESRCH); 391 pgid = (long)p1->p_pgrp->pg_id; 392 } 393 pgrp = pgfind(pgid); 394 if (pgrp == NULL || pgrp->pg_session != p->p_session) 395 return EPERM; 396 tp->t_pgrp = pgrp; 397 return 0; 398 default: 399 return EOPNOTSUPP; 400 } 401 402 SCARG(&fca, fd) = fd; 403 SCARG(&fca, cmd) = cmd; 404 SCARG(&fca, arg) = arg; 405 406 return sys_fcntl(p, &fca, retval); 407 } 408 409 /* 410 * Convert a NetBSD stat structure to a Linux stat structure. 411 * Only the order of the fields and the padding in the structure 412 * is different. linux_fakedev is a machine-dependent function 413 * which optionally converts device driver major/minor numbers 414 * (XXX horrible, but what can you do against code that compares 415 * things against constant major device numbers? sigh) 416 */ 417 static void 418 bsd_to_linux_stat(bsp, lsp) 419 struct stat *bsp; 420 struct linux_stat *lsp; 421 { 422 423 lsp->lst_dev = bsp->st_dev; 424 lsp->lst_ino = bsp->st_ino; 425 lsp->lst_mode = (linux_mode_t)bsp->st_mode; 426 if (bsp->st_nlink >= (1 << 15)) 427 lsp->lst_nlink = (1 << 15) - 1; 428 else 429 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink; 430 lsp->lst_uid = bsp->st_uid; 431 lsp->lst_gid = bsp->st_gid; 432 lsp->lst_rdev = linux_fakedev(bsp->st_rdev); 433 lsp->lst_size = bsp->st_size; 434 lsp->lst_blksize = bsp->st_blksize; 435 lsp->lst_blocks = bsp->st_blocks; 436 lsp->lst_atime = bsp->st_atime; 437 lsp->lst_mtime = bsp->st_mtime; 438 lsp->lst_ctime = bsp->st_ctime; 439 } 440 441 /* 442 * The stat functions below are plain sailing. stat and lstat are handled 443 * by one function to avoid code duplication. 444 */ 445 int 446 linux_sys_fstat(p, v, retval) 447 struct proc *p; 448 void *v; 449 register_t *retval; 450 { 451 struct linux_sys_fstat_args /* { 452 syscallarg(int) fd; 453 syscallarg(linux_stat *) sp; 454 } */ *uap = v; 455 struct sys___fstat13_args fsa; 456 struct linux_stat tmplst; 457 struct stat *st,tmpst; 458 caddr_t sg; 459 int error; 460 461 sg = stackgap_init(p->p_emul); 462 463 st = stackgap_alloc(&sg, sizeof (struct stat)); 464 465 SCARG(&fsa, fd) = SCARG(uap, fd); 466 SCARG(&fsa, sb) = st; 467 468 if ((error = sys___fstat13(p, &fsa, retval))) 469 return error; 470 471 if ((error = copyin(st, &tmpst, sizeof tmpst))) 472 return error; 473 474 bsd_to_linux_stat(&tmpst, &tmplst); 475 476 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 477 return error; 478 479 return 0; 480 } 481 482 static int 483 linux_stat1(p, v, retval, dolstat) 484 struct proc *p; 485 void *v; 486 register_t *retval; 487 int dolstat; 488 { 489 struct sys___stat13_args sa; 490 struct linux_stat tmplst; 491 struct stat *st, tmpst; 492 caddr_t sg; 493 int error; 494 struct linux_sys_stat_args *uap = v; 495 496 sg = stackgap_init(p->p_emul); 497 498 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 499 500 st = stackgap_alloc(&sg, sizeof (struct stat)); 501 SCARG(&sa, ub) = st; 502 SCARG(&sa, path) = SCARG(uap, path); 503 504 if ((error = (dolstat ? sys___lstat13(p, &sa, retval) : 505 sys___stat13(p, &sa, retval)))) 506 return error; 507 508 if ((error = copyin(st, &tmpst, sizeof tmpst))) 509 return error; 510 511 bsd_to_linux_stat(&tmpst, &tmplst); 512 513 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 514 return error; 515 516 return 0; 517 } 518 519 int 520 linux_sys_stat(p, v, retval) 521 struct proc *p; 522 void *v; 523 register_t *retval; 524 { 525 struct linux_sys_stat_args /* { 526 syscallarg(const char *) path; 527 syscallarg(struct linux_stat *) sp; 528 } */ *uap = v; 529 530 return linux_stat1(p, uap, retval, 0); 531 } 532 533 /* Note: this is "newlstat" in the Linux sources */ 534 /* (we don't bother with the old lstat currently) */ 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(const 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(const 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(const 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(const 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(const 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(const 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(const char *) path; 654 syscallarg(int) uid; 655 syscallarg(int) gid; 656 } */ *uap = v; 657 struct sys___posix_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___posix_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___posix_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___posix_fchown(p, &bfa, retval); 691 } 692 693 int 694 linux_sys_lchown(p, v, retval) 695 struct proc *p; 696 void *v; 697 register_t *retval; 698 { 699 struct linux_sys_lchown_args /* { 700 syscallarg(char *) path; 701 syscallarg(int) uid; 702 syscallarg(int) gid; 703 } */ *uap = v; 704 struct sys___posix_lchown_args bla; 705 706 SCARG(&bla, path) = SCARG(uap, path); 707 SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 708 (uid_t)-1 : SCARG(uap, uid); 709 SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 710 (gid_t)-1 : SCARG(uap, gid); 711 712 return sys___posix_lchown(p, &bla, retval); 713 } 714 715 int 716 linux_sys_rename(p, v, retval) 717 struct proc *p; 718 void *v; 719 register_t *retval; 720 { 721 struct linux_sys_rename_args /* { 722 syscallarg(const char *) from; 723 syscallarg(const char *) to; 724 } */ *uap = v; 725 caddr_t sg = stackgap_init(p->p_emul); 726 727 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 728 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 729 730 return sys___posix_rename(p, uap, retval); 731 } 732 733 int 734 linux_sys_mkdir(p, v, retval) 735 struct proc *p; 736 void *v; 737 register_t *retval; 738 { 739 struct linux_sys_mkdir_args /* { 740 syscallarg(const char *) path; 741 syscallarg(int) mode; 742 } */ *uap = v; 743 caddr_t sg = stackgap_init(p->p_emul); 744 745 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 746 747 return sys_mkdir(p, uap, retval); 748 } 749 750 int 751 linux_sys_rmdir(p, v, retval) 752 struct proc *p; 753 void *v; 754 register_t *retval; 755 { 756 struct linux_sys_rmdir_args /* { 757 syscallarg(const char *) path; 758 } */ *uap = v; 759 caddr_t sg = stackgap_init(p->p_emul); 760 761 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 762 763 return sys_rmdir(p, uap, retval); 764 } 765 766 int 767 linux_sys_symlink(p, v, retval) 768 struct proc *p; 769 void *v; 770 register_t *retval; 771 { 772 struct linux_sys_symlink_args /* { 773 syscallarg(const char *) path; 774 syscallarg(const char *) to; 775 } */ *uap = v; 776 caddr_t sg = stackgap_init(p->p_emul); 777 778 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 779 LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 780 781 return sys_symlink(p, uap, retval); 782 } 783 784 int 785 linux_sys_readlink(p, v, retval) 786 struct proc *p; 787 void *v; 788 register_t *retval; 789 { 790 struct linux_sys_readlink_args /* { 791 syscallarg(const char *) name; 792 syscallarg(char *) buf; 793 syscallarg(int) count; 794 } */ *uap = v; 795 caddr_t sg = stackgap_init(p->p_emul); 796 797 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name)); 798 799 return sys_readlink(p, uap, retval); 800 } 801 802 int 803 linux_sys_truncate(p, v, retval) 804 struct proc *p; 805 void *v; 806 register_t *retval; 807 { 808 struct linux_sys_truncate_args /* { 809 syscallarg(const char *) path; 810 syscallarg(long) length; 811 } */ *uap = v; 812 caddr_t sg = stackgap_init(p->p_emul); 813 814 LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 815 816 return compat_43_sys_truncate(p, uap, retval); 817 } 818 819 /* 820 * This is just fsync() for now (just as it is in the Linux kernel) 821 * Note: this is not implemented under Linux on Alpha and Arm 822 * but should still be defined in our syscalls.master. 823 * (syscall #148 on the arm) 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 839 /* 840 * pread(2). 841 */ 842 int 843 linux_sys_pread(p, v, retval) 844 struct proc *p; 845 void *v; 846 register_t *retval; 847 { 848 struct linux_sys_pread_args /* { 849 syscallarg(int) fd; 850 syscallarg(void *) buf; 851 syscallarg(size_t) nbyte; 852 syscallarg(linux_off_t) offset; 853 } */ *uap = v; 854 struct sys_pread_args pra; 855 caddr_t sg; 856 857 sg = stackgap_init(p->p_emul); 858 859 SCARG(&pra, fd) = SCARG(uap, fd); 860 SCARG(&pra, buf) = SCARG(uap, buf); 861 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 862 SCARG(&pra, offset) = SCARG(uap, offset); 863 864 return sys_read(p, &pra, retval); 865 } 866 867 /* 868 * pwrite(2). 869 */ 870 int 871 linux_sys_pwrite(p, v, retval) 872 struct proc *p; 873 void *v; 874 register_t *retval; 875 { 876 struct linux_sys_pwrite_args /* { 877 syscallarg(int) fd; 878 syscallarg(void *) buf; 879 syscallarg(size_t) nbyte; 880 syscallarg(linux_off_t) offset; 881 } */ *uap = v; 882 struct sys_pwrite_args pra; 883 caddr_t sg; 884 885 sg = stackgap_init(p->p_emul); 886 887 SCARG(&pra, fd) = SCARG(uap, fd); 888 SCARG(&pra, buf) = SCARG(uap, buf); 889 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 890 SCARG(&pra, offset) = SCARG(uap, offset); 891 892 return sys_write(p, &pra, retval); 893 } 894