1 /* $NetBSD: linux_file.c,v 1.34 2000/12/29 20:08:31 fvdl 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 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 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 186 else 187 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 st = stackgap_alloc(&sg, sizeof (struct stat)); 498 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 499 500 SCARG(&sa, ub) = st; 501 SCARG(&sa, path) = SCARG(uap, path); 502 503 if ((error = (dolstat ? sys___lstat13(p, &sa, retval) : 504 sys___stat13(p, &sa, retval)))) 505 return error; 506 507 if ((error = copyin(st, &tmpst, sizeof tmpst))) 508 return error; 509 510 bsd_to_linux_stat(&tmpst, &tmplst); 511 512 if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst))) 513 return error; 514 515 return 0; 516 } 517 518 int 519 linux_sys_stat(p, v, retval) 520 struct proc *p; 521 void *v; 522 register_t *retval; 523 { 524 struct linux_sys_stat_args /* { 525 syscallarg(const char *) path; 526 syscallarg(struct linux_stat *) sp; 527 } */ *uap = v; 528 529 return linux_stat1(p, uap, retval, 0); 530 } 531 532 /* Note: this is "newlstat" in the Linux sources */ 533 /* (we don't bother with the old lstat currently) */ 534 int 535 linux_sys_lstat(p, v, retval) 536 struct proc *p; 537 void *v; 538 register_t *retval; 539 { 540 struct linux_sys_lstat_args /* { 541 syscallarg(const char *) path; 542 syscallarg(struct linux_stat *) sp; 543 } */ *uap = v; 544 545 return linux_stat1(p, uap, retval, 1); 546 } 547 548 /* 549 * The following syscalls are mostly here because of the alternate path check. 550 */ 551 int 552 linux_sys_access(p, v, retval) 553 struct proc *p; 554 void *v; 555 register_t *retval; 556 { 557 struct linux_sys_access_args /* { 558 syscallarg(const char *) path; 559 syscallarg(int) flags; 560 } */ *uap = v; 561 caddr_t sg = stackgap_init(p->p_emul); 562 563 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 564 565 return sys_access(p, uap, retval); 566 } 567 568 int 569 linux_sys_unlink(p, v, retval) 570 struct proc *p; 571 void *v; 572 register_t *retval; 573 574 { 575 struct linux_sys_unlink_args /* { 576 syscallarg(const char *) path; 577 } */ *uap = v; 578 caddr_t sg = stackgap_init(p->p_emul); 579 580 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 581 582 return sys_unlink(p, uap, retval); 583 } 584 585 int 586 linux_sys_chdir(p, v, retval) 587 struct proc *p; 588 void *v; 589 register_t *retval; 590 { 591 struct linux_sys_chdir_args /* { 592 syscallarg(const char *) path; 593 } */ *uap = v; 594 caddr_t sg = stackgap_init(p->p_emul); 595 596 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 597 598 return sys_chdir(p, uap, retval); 599 } 600 601 int 602 linux_sys_mknod(p, v, retval) 603 struct proc *p; 604 void *v; 605 register_t *retval; 606 { 607 struct linux_sys_mknod_args /* { 608 syscallarg(const char *) path; 609 syscallarg(int) mode; 610 syscallarg(int) dev; 611 } */ *uap = v; 612 caddr_t sg = stackgap_init(p->p_emul); 613 struct sys_mkfifo_args bma; 614 615 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 616 617 /* 618 * BSD handles FIFOs seperately 619 */ 620 if (SCARG(uap, mode) & S_IFIFO) { 621 SCARG(&bma, path) = SCARG(uap, path); 622 SCARG(&bma, mode) = SCARG(uap, mode); 623 return sys_mkfifo(p, uap, retval); 624 } else 625 return sys_mknod(p, uap, retval); 626 } 627 628 int 629 linux_sys_chmod(p, v, retval) 630 struct proc *p; 631 void *v; 632 register_t *retval; 633 { 634 struct linux_sys_chmod_args /* { 635 syscallarg(const char *) path; 636 syscallarg(int) mode; 637 } */ *uap = v; 638 caddr_t sg = stackgap_init(p->p_emul); 639 640 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 641 642 return sys_chmod(p, uap, retval); 643 } 644 645 #if defined(__i386__) || defined(__m68k__) 646 int 647 linux_sys_chown16(p, v, retval) 648 struct proc *p; 649 void *v; 650 register_t *retval; 651 { 652 struct linux_sys_chown16_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 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_fchown16(p, v, retval) 673 struct proc *p; 674 void *v; 675 register_t *retval; 676 { 677 struct linux_sys_fchown16_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_lchown16(p, v, retval) 695 struct proc *p; 696 void *v; 697 register_t *retval; 698 { 699 struct linux_sys_lchown16_args /* { 700 syscallarg(char *) path; 701 syscallarg(int) uid; 702 syscallarg(int) gid; 703 } */ *uap = v; 704 struct sys___posix_lchown_args bla; 705 caddr_t sg = stackgap_init(p->p_emul); 706 707 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 708 709 SCARG(&bla, path) = SCARG(uap, path); 710 SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 711 (uid_t)-1 : SCARG(uap, uid); 712 SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 713 (gid_t)-1 : SCARG(uap, gid); 714 715 return sys___posix_lchown(p, &bla, retval); 716 } 717 718 int 719 linux_sys_chown(p, v, retval) 720 struct proc *p; 721 void *v; 722 register_t *retval; 723 { 724 struct linux_sys_chown_args /* { 725 syscallarg(char *) path; 726 syscallarg(int) uid; 727 syscallarg(int) gid; 728 } */ *uap = v; 729 caddr_t sg = stackgap_init(p->p_emul); 730 731 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 732 733 return sys___posix_chown(p, uap, retval); 734 } 735 736 int 737 linux_sys_lchown(p, v, retval) 738 struct proc *p; 739 void *v; 740 register_t *retval; 741 { 742 struct linux_sys_lchown_args /* { 743 syscallarg(char *) path; 744 syscallarg(int) uid; 745 syscallarg(int) gid; 746 } */ *uap = v; 747 caddr_t sg = stackgap_init(p->p_emul); 748 749 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 750 751 return sys___posix_lchown(p, uap, retval); 752 } 753 #endif /* __i386__ || __m68k__ */ 754 755 int 756 linux_sys_rename(p, v, retval) 757 struct proc *p; 758 void *v; 759 register_t *retval; 760 { 761 struct linux_sys_rename_args /* { 762 syscallarg(const char *) from; 763 syscallarg(const char *) to; 764 } */ *uap = v; 765 caddr_t sg = stackgap_init(p->p_emul); 766 767 CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 768 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 769 770 return sys___posix_rename(p, uap, retval); 771 } 772 773 int 774 linux_sys_mkdir(p, v, retval) 775 struct proc *p; 776 void *v; 777 register_t *retval; 778 { 779 struct linux_sys_mkdir_args /* { 780 syscallarg(const char *) path; 781 syscallarg(int) mode; 782 } */ *uap = v; 783 caddr_t sg = stackgap_init(p->p_emul); 784 785 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 786 787 return sys_mkdir(p, uap, retval); 788 } 789 790 int 791 linux_sys_rmdir(p, v, retval) 792 struct proc *p; 793 void *v; 794 register_t *retval; 795 { 796 struct linux_sys_rmdir_args /* { 797 syscallarg(const char *) path; 798 } */ *uap = v; 799 caddr_t sg = stackgap_init(p->p_emul); 800 801 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 802 803 return sys_rmdir(p, uap, retval); 804 } 805 806 int 807 linux_sys_symlink(p, v, retval) 808 struct proc *p; 809 void *v; 810 register_t *retval; 811 { 812 struct linux_sys_symlink_args /* { 813 syscallarg(const char *) path; 814 syscallarg(const char *) to; 815 } */ *uap = v; 816 caddr_t sg = stackgap_init(p->p_emul); 817 818 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 819 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 820 821 return sys_symlink(p, uap, retval); 822 } 823 824 int 825 linux_sys_link(p, v, retval) 826 struct proc *p; 827 void *v; 828 register_t *retval; 829 { 830 struct linux_sys_link_args /* { 831 syscallarg(const char *) path; 832 syscallarg(const char *) link; 833 } */ *uap = v; 834 caddr_t sg = stackgap_init(p->p_emul); 835 836 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 837 CHECK_ALT_CREAT(p, &sg, SCARG(uap, link)); 838 839 return sys_link(p, uap, retval); 840 } 841 842 int 843 linux_sys_readlink(p, v, retval) 844 struct proc *p; 845 void *v; 846 register_t *retval; 847 { 848 struct linux_sys_readlink_args /* { 849 syscallarg(const char *) name; 850 syscallarg(char *) buf; 851 syscallarg(int) count; 852 } */ *uap = v; 853 caddr_t sg = stackgap_init(p->p_emul); 854 855 CHECK_ALT_EXIST(p, &sg, SCARG(uap, name)); 856 857 return sys_readlink(p, uap, retval); 858 } 859 860 int 861 linux_sys_truncate(p, v, retval) 862 struct proc *p; 863 void *v; 864 register_t *retval; 865 { 866 struct linux_sys_truncate_args /* { 867 syscallarg(const char *) path; 868 syscallarg(long) length; 869 } */ *uap = v; 870 caddr_t sg = stackgap_init(p->p_emul); 871 872 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 873 874 return compat_43_sys_truncate(p, uap, retval); 875 } 876 877 /* 878 * This is just fsync() for now (just as it is in the Linux kernel) 879 * Note: this is not implemented under Linux on Alpha and Arm 880 * but should still be defined in our syscalls.master. 881 * (syscall #148 on the arm) 882 */ 883 int 884 linux_sys_fdatasync(p, v, retval) 885 struct proc *p; 886 void *v; 887 register_t *retval; 888 { 889 #ifdef notdef 890 struct linux_sys_fdatasync_args /* { 891 syscallarg(int) fd; 892 } */ *uap = v; 893 #endif 894 return sys_fsync(p, v, retval); 895 } 896 897 /* 898 * pread(2). 899 */ 900 int 901 linux_sys_pread(p, v, retval) 902 struct proc *p; 903 void *v; 904 register_t *retval; 905 { 906 struct linux_sys_pread_args /* { 907 syscallarg(int) fd; 908 syscallarg(void *) buf; 909 syscallarg(size_t) nbyte; 910 syscallarg(linux_off_t) offset; 911 } */ *uap = v; 912 struct sys_pread_args pra; 913 caddr_t sg; 914 915 sg = stackgap_init(p->p_emul); 916 917 SCARG(&pra, fd) = SCARG(uap, fd); 918 SCARG(&pra, buf) = SCARG(uap, buf); 919 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 920 SCARG(&pra, offset) = SCARG(uap, offset); 921 922 return sys_read(p, &pra, retval); 923 } 924 925 /* 926 * pwrite(2). 927 */ 928 int 929 linux_sys_pwrite(p, v, retval) 930 struct proc *p; 931 void *v; 932 register_t *retval; 933 { 934 struct linux_sys_pwrite_args /* { 935 syscallarg(int) fd; 936 syscallarg(void *) buf; 937 syscallarg(size_t) nbyte; 938 syscallarg(linux_off_t) offset; 939 } */ *uap = v; 940 struct sys_pwrite_args pra; 941 caddr_t sg; 942 943 sg = stackgap_init(p->p_emul); 944 945 SCARG(&pra, fd) = SCARG(uap, fd); 946 SCARG(&pra, buf) = SCARG(uap, buf); 947 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 948 SCARG(&pra, offset) = SCARG(uap, offset); 949 950 return sys_write(p, &pra, retval); 951 } 952