1 /* $NetBSD: linux_file.c,v 1.30 2000/12/01 12:28:33 jdolecek 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 int 646 linux_sys_chown(p, v, retval) 647 struct proc *p; 648 void *v; 649 register_t *retval; 650 { 651 struct linux_sys_chown_args /* { 652 syscallarg(const char *) path; 653 syscallarg(int) uid; 654 syscallarg(int) gid; 655 } */ *uap = v; 656 struct sys___posix_chown_args bca; 657 caddr_t sg = stackgap_init(p->p_emul); 658 659 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 660 661 SCARG(&bca, path) = SCARG(uap, path); 662 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 663 (uid_t)-1 : SCARG(uap, uid); 664 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 665 (gid_t)-1 : SCARG(uap, gid); 666 667 return sys___posix_chown(p, &bca, retval); 668 } 669 670 int 671 linux_sys_fchown(p, v, retval) 672 struct proc *p; 673 void *v; 674 register_t *retval; 675 { 676 struct linux_sys_fchown_args /* { 677 syscallarg(int) fd; 678 syscallarg(int) uid; 679 syscallarg(int) gid; 680 } */ *uap = v; 681 struct sys___posix_fchown_args bfa; 682 683 SCARG(&bfa, fd) = SCARG(uap, fd); 684 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 685 (uid_t)-1 : SCARG(uap, uid); 686 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 687 (gid_t)-1 : SCARG(uap, gid); 688 689 return sys___posix_fchown(p, &bfa, retval); 690 } 691 692 int 693 linux_sys_lchown(p, v, retval) 694 struct proc *p; 695 void *v; 696 register_t *retval; 697 { 698 struct linux_sys_lchown_args /* { 699 syscallarg(char *) path; 700 syscallarg(int) uid; 701 syscallarg(int) gid; 702 } */ *uap = v; 703 struct sys___posix_lchown_args bla; 704 705 SCARG(&bla, path) = SCARG(uap, path); 706 SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 707 (uid_t)-1 : SCARG(uap, uid); 708 SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 709 (gid_t)-1 : SCARG(uap, gid); 710 711 return sys___posix_lchown(p, &bla, retval); 712 } 713 714 int 715 linux_sys_rename(p, v, retval) 716 struct proc *p; 717 void *v; 718 register_t *retval; 719 { 720 struct linux_sys_rename_args /* { 721 syscallarg(const char *) from; 722 syscallarg(const char *) to; 723 } */ *uap = v; 724 caddr_t sg = stackgap_init(p->p_emul); 725 726 CHECK_ALT_EXIST(p, &sg, SCARG(uap, from)); 727 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 728 729 return sys___posix_rename(p, uap, retval); 730 } 731 732 int 733 linux_sys_mkdir(p, v, retval) 734 struct proc *p; 735 void *v; 736 register_t *retval; 737 { 738 struct linux_sys_mkdir_args /* { 739 syscallarg(const char *) path; 740 syscallarg(int) mode; 741 } */ *uap = v; 742 caddr_t sg = stackgap_init(p->p_emul); 743 744 CHECK_ALT_CREAT(p, &sg, SCARG(uap, path)); 745 746 return sys_mkdir(p, uap, retval); 747 } 748 749 int 750 linux_sys_rmdir(p, v, retval) 751 struct proc *p; 752 void *v; 753 register_t *retval; 754 { 755 struct linux_sys_rmdir_args /* { 756 syscallarg(const char *) path; 757 } */ *uap = v; 758 caddr_t sg = stackgap_init(p->p_emul); 759 760 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 761 762 return sys_rmdir(p, uap, retval); 763 } 764 765 int 766 linux_sys_symlink(p, v, retval) 767 struct proc *p; 768 void *v; 769 register_t *retval; 770 { 771 struct linux_sys_symlink_args /* { 772 syscallarg(const char *) path; 773 syscallarg(const char *) to; 774 } */ *uap = v; 775 caddr_t sg = stackgap_init(p->p_emul); 776 777 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 778 CHECK_ALT_CREAT(p, &sg, SCARG(uap, to)); 779 780 return sys_symlink(p, uap, retval); 781 } 782 783 int 784 linux_sys_readlink(p, v, retval) 785 struct proc *p; 786 void *v; 787 register_t *retval; 788 { 789 struct linux_sys_readlink_args /* { 790 syscallarg(const char *) name; 791 syscallarg(char *) buf; 792 syscallarg(int) count; 793 } */ *uap = v; 794 caddr_t sg = stackgap_init(p->p_emul); 795 796 CHECK_ALT_EXIST(p, &sg, SCARG(uap, name)); 797 798 return sys_readlink(p, uap, retval); 799 } 800 801 int 802 linux_sys_truncate(p, v, retval) 803 struct proc *p; 804 void *v; 805 register_t *retval; 806 { 807 struct linux_sys_truncate_args /* { 808 syscallarg(const char *) path; 809 syscallarg(long) length; 810 } */ *uap = v; 811 caddr_t sg = stackgap_init(p->p_emul); 812 813 CHECK_ALT_EXIST(p, &sg, SCARG(uap, path)); 814 815 return compat_43_sys_truncate(p, uap, retval); 816 } 817 818 /* 819 * This is just fsync() for now (just as it is in the Linux kernel) 820 * Note: this is not implemented under Linux on Alpha and Arm 821 * but should still be defined in our syscalls.master. 822 * (syscall #148 on the arm) 823 */ 824 int 825 linux_sys_fdatasync(p, v, retval) 826 struct proc *p; 827 void *v; 828 register_t *retval; 829 { 830 #ifdef notdef 831 struct linux_sys_fdatasync_args /* { 832 syscallarg(int) fd; 833 } */ *uap = v; 834 #endif 835 return sys_fsync(p, v, retval); 836 } 837 838 /* 839 * pread(2). 840 */ 841 int 842 linux_sys_pread(p, v, retval) 843 struct proc *p; 844 void *v; 845 register_t *retval; 846 { 847 struct linux_sys_pread_args /* { 848 syscallarg(int) fd; 849 syscallarg(void *) buf; 850 syscallarg(size_t) nbyte; 851 syscallarg(linux_off_t) offset; 852 } */ *uap = v; 853 struct sys_pread_args pra; 854 caddr_t sg; 855 856 sg = stackgap_init(p->p_emul); 857 858 SCARG(&pra, fd) = SCARG(uap, fd); 859 SCARG(&pra, buf) = SCARG(uap, buf); 860 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 861 SCARG(&pra, offset) = SCARG(uap, offset); 862 863 return sys_read(p, &pra, retval); 864 } 865 866 /* 867 * pwrite(2). 868 */ 869 int 870 linux_sys_pwrite(p, v, retval) 871 struct proc *p; 872 void *v; 873 register_t *retval; 874 { 875 struct linux_sys_pwrite_args /* { 876 syscallarg(int) fd; 877 syscallarg(void *) buf; 878 syscallarg(size_t) nbyte; 879 syscallarg(linux_off_t) offset; 880 } */ *uap = v; 881 struct sys_pwrite_args pra; 882 caddr_t sg; 883 884 sg = stackgap_init(p->p_emul); 885 886 SCARG(&pra, fd) = SCARG(uap, fd); 887 SCARG(&pra, buf) = SCARG(uap, buf); 888 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 889 SCARG(&pra, offset) = SCARG(uap, offset); 890 891 return sys_write(p, &pra, retval); 892 } 893