1 /* $NetBSD: linux_file.c,v 1.89 2007/12/08 19:29:39 pooka 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/cdefs.h> 45 __KERNEL_RCSID(0, "$NetBSD: linux_file.c,v 1.89 2007/12/08 19:29:39 pooka Exp $"); 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/namei.h> 50 #include <sys/proc.h> 51 #include <sys/file.h> 52 #include <sys/stat.h> 53 #include <sys/filedesc.h> 54 #include <sys/ioctl.h> 55 #include <sys/kernel.h> 56 #include <sys/mount.h> 57 #include <sys/malloc.h> 58 #include <sys/namei.h> 59 #include <sys/vnode.h> 60 #include <sys/tty.h> 61 #include <sys/socketvar.h> 62 #include <sys/conf.h> 63 #include <sys/pipe.h> 64 65 #include <sys/syscallargs.h> 66 #include <sys/vfs_syscalls.h> 67 68 #include <compat/linux/common/linux_types.h> 69 #include <compat/linux/common/linux_signal.h> 70 #include <compat/linux/common/linux_fcntl.h> 71 #include <compat/linux/common/linux_util.h> 72 #include <compat/linux/common/linux_machdep.h> 73 #include <compat/linux/common/linux_ipc.h> 74 #include <compat/linux/common/linux_sem.h> 75 76 #include <compat/linux/linux_syscallargs.h> 77 78 static int linux_to_bsd_ioflags(int); 79 static int bsd_to_linux_ioflags(int); 80 static void bsd_to_linux_flock(struct flock *, struct linux_flock *); 81 static void linux_to_bsd_flock(struct linux_flock *, struct flock *); 82 #ifndef __amd64__ 83 static void bsd_to_linux_stat(struct stat *, struct linux_stat *); 84 static int linux_stat1(struct lwp *, void *, register_t *, int); 85 #endif 86 87 /* 88 * Some file-related calls are handled here. The usual flag conversion 89 * an structure conversion is done, and alternate emul path searching. 90 */ 91 92 /* 93 * The next two functions convert between the Linux and NetBSD values 94 * of the flags used in open(2) and fcntl(2). 95 */ 96 static int 97 linux_to_bsd_ioflags(int lflags) 98 { 99 int res = 0; 100 101 res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY); 102 res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY); 103 res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR); 104 res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT); 105 res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL); 106 res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY); 107 res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC); 108 res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY); 109 res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_FSYNC); 110 res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC); 111 res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND); 112 113 return res; 114 } 115 116 static int 117 bsd_to_linux_ioflags(int bflags) 118 { 119 int res = 0; 120 121 res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY); 122 res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY); 123 res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR); 124 res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT); 125 res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL); 126 res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY); 127 res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC); 128 res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY); 129 res |= cvtto_linux_mask(bflags, O_FSYNC, LINUX_O_SYNC); 130 res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC); 131 res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND); 132 133 return res; 134 } 135 136 /* 137 * creat(2) is an obsolete function, but it's present as a Linux 138 * system call, so let's deal with it. 139 * 140 * Note: On the Alpha this doesn't really exist in Linux, but it's defined 141 * in syscalls.master anyway so this doesn't have to be special cased. 142 * 143 * Just call open(2) with the TRUNC, CREAT and WRONLY flags. 144 */ 145 int 146 linux_sys_creat(struct lwp *l, void *v, register_t *retval) 147 { 148 struct linux_sys_creat_args /* { 149 syscallarg(const char *) path; 150 syscallarg(int) mode; 151 } */ *uap = v; 152 struct sys_open_args oa; 153 154 SCARG(&oa, path) = SCARG(uap, path); 155 SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY; 156 SCARG(&oa, mode) = SCARG(uap, mode); 157 158 return sys_open(l, &oa, retval); 159 } 160 161 /* 162 * open(2). Take care of the different flag values, and let the 163 * NetBSD syscall do the real work. See if this operation 164 * gives the current process a controlling terminal. 165 * (XXX is this necessary?) 166 */ 167 int 168 linux_sys_open(struct lwp *l, void *v, register_t *retval) 169 { 170 struct linux_sys_open_args /* { 171 syscallarg(const char *) path; 172 syscallarg(int) flags; 173 syscallarg(int) mode; 174 } */ *uap = v; 175 struct proc *p = l->l_proc; 176 int error, fl; 177 struct sys_open_args boa; 178 179 fl = linux_to_bsd_ioflags(SCARG(uap, flags)); 180 181 SCARG(&boa, path) = SCARG(uap, path); 182 SCARG(&boa, flags) = fl; 183 SCARG(&boa, mode) = SCARG(uap, mode); 184 185 if ((error = sys_open(l, &boa, retval))) 186 return error; 187 188 /* 189 * this bit from sunos_misc.c (and svr4_fcntl.c). 190 * If we are a session leader, and we don't have a controlling 191 * terminal yet, and the O_NOCTTY flag is not set, try to make 192 * this the controlling terminal. 193 */ 194 if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) { 195 struct filedesc *fdp = p->p_fd; 196 struct file *fp; 197 198 fp = fd_getfile(fdp, *retval); 199 200 /* ignore any error, just give it a try */ 201 if (fp != NULL) { 202 FILE_USE(fp); 203 if (fp->f_type == DTYPE_VNODE) { 204 (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, 205 (void *) 0, l); 206 } 207 FILE_UNUSE(fp, l); 208 } 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(struct flock *bfp, struct linux_flock *lfp) 221 { 222 223 lfp->l_start = bfp->l_start; 224 lfp->l_len = bfp->l_len; 225 lfp->l_pid = bfp->l_pid; 226 lfp->l_whence = bfp->l_whence; 227 switch (bfp->l_type) { 228 case F_RDLCK: 229 lfp->l_type = LINUX_F_RDLCK; 230 break; 231 case F_UNLCK: 232 lfp->l_type = LINUX_F_UNLCK; 233 break; 234 case F_WRLCK: 235 lfp->l_type = LINUX_F_WRLCK; 236 break; 237 } 238 } 239 240 static void 241 linux_to_bsd_flock(struct linux_flock *lfp, struct flock *bfp) 242 { 243 244 bfp->l_start = lfp->l_start; 245 bfp->l_len = lfp->l_len; 246 bfp->l_pid = lfp->l_pid; 247 bfp->l_whence = lfp->l_whence; 248 switch (lfp->l_type) { 249 case LINUX_F_RDLCK: 250 bfp->l_type = F_RDLCK; 251 break; 252 case LINUX_F_UNLCK: 253 bfp->l_type = F_UNLCK; 254 break; 255 case LINUX_F_WRLCK: 256 bfp->l_type = F_WRLCK; 257 break; 258 } 259 } 260 261 /* 262 * Most actions in the fcntl() call are straightforward; simply 263 * pass control to the NetBSD system call. A few commands need 264 * conversions after the actual system call has done its work, 265 * because the flag values and lock structure are different. 266 */ 267 int 268 linux_sys_fcntl(struct lwp *l, void *v, register_t *retval) 269 { 270 struct linux_sys_fcntl_args /* { 271 syscallarg(int) fd; 272 syscallarg(int) cmd; 273 syscallarg(void *) arg; 274 } */ *uap = v; 275 struct proc *p = l->l_proc; 276 int fd, cmd, error; 277 u_long val; 278 void *arg; 279 struct linux_flock lfl; 280 struct flock bfl; 281 struct sys_fcntl_args fca; 282 struct filedesc *fdp; 283 struct file *fp; 284 struct vnode *vp; 285 struct vattr va; 286 const struct cdevsw *cdev; 287 long pgid; 288 struct pgrp *pgrp; 289 struct tty *tp, *(*d_tty)(dev_t); 290 291 fd = SCARG(uap, fd); 292 cmd = SCARG(uap, cmd); 293 arg = (void *) SCARG(uap, arg); 294 295 switch (cmd) { 296 case LINUX_F_DUPFD: 297 cmd = F_DUPFD; 298 break; 299 case LINUX_F_GETFD: 300 cmd = F_GETFD; 301 break; 302 case LINUX_F_SETFD: 303 cmd = F_SETFD; 304 break; 305 case LINUX_F_GETFL: 306 SCARG(&fca, fd) = fd; 307 SCARG(&fca, cmd) = F_GETFL; 308 SCARG(&fca, arg) = arg; 309 if ((error = sys_fcntl(l, &fca, retval))) 310 return error; 311 retval[0] = bsd_to_linux_ioflags(retval[0]); 312 return 0; 313 case LINUX_F_SETFL: { 314 struct file *fp1 = NULL; 315 316 val = linux_to_bsd_ioflags((unsigned long)SCARG(uap, arg)); 317 /* 318 * Linux seems to have same semantics for sending SIGIO to the 319 * read side of socket, but slightly different semantics 320 * for SIGIO to the write side. Rather than sending the SIGIO 321 * every time it's possible to write (directly) more data, it 322 * only sends SIGIO if last write(2) failed due to insufficient 323 * memory to hold the data. This is compatible enough 324 * with NetBSD semantics to not do anything about the 325 * difference. 326 * 327 * Linux does NOT send SIGIO for pipes. Deal with socketpair 328 * ones and DTYPE_PIPE ones. For these, we don't set 329 * the underlying flags (we don't pass O_ASYNC flag down 330 * to sys_fcntl()), but set the FASYNC flag for file descriptor, 331 * so that F_GETFL would report the ASYNC i/o is on. 332 */ 333 if (val & O_ASYNC) { 334 if (((fp1 = fd_getfile(p->p_fd, fd)) == NULL)) 335 return (EBADF); 336 337 FILE_USE(fp1); 338 339 if (((fp1->f_type == DTYPE_SOCKET) && fp1->f_data 340 && ((struct socket *)fp1->f_data)->so_state & SS_ISAPIPE) 341 || (fp1->f_type == DTYPE_PIPE)) 342 val &= ~O_ASYNC; 343 else { 344 /* not a pipe, do not modify anything */ 345 FILE_UNUSE(fp1, l); 346 fp1 = NULL; 347 } 348 } 349 350 SCARG(&fca, fd) = fd; 351 SCARG(&fca, cmd) = F_SETFL; 352 SCARG(&fca, arg) = (void *) val; 353 354 error = sys_fcntl(l, &fca, retval); 355 356 /* Now set the FASYNC flag for pipes */ 357 if (fp1) { 358 if (!error) 359 fp1->f_flag |= FASYNC; 360 FILE_UNUSE(fp1, l); 361 } 362 363 return (error); 364 } 365 case LINUX_F_GETLK: 366 if ((error = copyin(arg, &lfl, sizeof lfl))) 367 return error; 368 linux_to_bsd_flock(&lfl, &bfl); 369 error = do_fcntl_lock(l, fd, F_GETLK, &bfl); 370 if (error) 371 return error; 372 bsd_to_linux_flock(&bfl, &lfl); 373 return copyout(&lfl, arg, sizeof lfl); 374 375 case LINUX_F_SETLK: 376 case LINUX_F_SETLKW: 377 cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW); 378 if ((error = copyin(arg, &lfl, sizeof lfl))) 379 return error; 380 linux_to_bsd_flock(&lfl, &bfl); 381 return do_fcntl_lock(l, fd, cmd, &bfl); 382 383 case LINUX_F_SETOWN: 384 case LINUX_F_GETOWN: 385 /* 386 * We need to route fcntl() for tty descriptors around normal 387 * fcntl(), since NetBSD tty TIOC{G,S}PGRP semantics is too 388 * restrictive for Linux F_{G,S}ETOWN. For non-tty descriptors, 389 * this is not a problem. 390 */ 391 fdp = p->p_fd; 392 if ((fp = fd_getfile(fdp, fd)) == NULL) 393 return EBADF; 394 FILE_USE(fp); 395 396 /* Check it's a character device vnode */ 397 if (fp->f_type != DTYPE_VNODE 398 || (vp = (struct vnode *)fp->f_data) == NULL 399 || vp->v_type != VCHR) { 400 FILE_UNUSE(fp, l); 401 402 not_tty: 403 /* Not a tty, proceed with common fcntl() */ 404 cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN; 405 break; 406 } 407 408 error = VOP_GETATTR(vp, &va, l->l_cred); 409 410 FILE_UNUSE(fp, l); 411 412 if (error) 413 return error; 414 415 cdev = cdevsw_lookup(va.va_rdev); 416 if (cdev == NULL) 417 return (ENXIO); 418 d_tty = cdev->d_tty; 419 if (!d_tty || (!(tp = (*d_tty)(va.va_rdev)))) 420 goto not_tty; 421 422 /* set tty pg_id appropriately */ 423 if (cmd == LINUX_F_GETOWN) { 424 retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID; 425 return 0; 426 } 427 mutex_enter(&proclist_lock); 428 if ((long)arg <= 0) { 429 pgid = -(long)arg; 430 } else { 431 struct proc *p1 = p_find((long)arg, PFIND_LOCKED | PFIND_UNLOCK_FAIL); 432 if (p1 == NULL) 433 return (ESRCH); 434 pgid = (long)p1->p_pgrp->pg_id; 435 } 436 pgrp = pg_find(pgid, PFIND_LOCKED); 437 if (pgrp == NULL || pgrp->pg_session != p->p_session) { 438 mutex_exit(&proclist_lock); 439 return EPERM; 440 } 441 tp->t_pgrp = pgrp; 442 mutex_exit(&proclist_lock); 443 return 0; 444 445 default: 446 return EOPNOTSUPP; 447 } 448 449 SCARG(&fca, fd) = fd; 450 SCARG(&fca, cmd) = cmd; 451 SCARG(&fca, arg) = arg; 452 453 return sys_fcntl(l, &fca, retval); 454 } 455 456 #if !defined(__amd64__) 457 /* 458 * Convert a NetBSD stat structure to a Linux stat structure. 459 * Only the order of the fields and the padding in the structure 460 * is different. linux_fakedev is a machine-dependent function 461 * which optionally converts device driver major/minor numbers 462 * (XXX horrible, but what can you do against code that compares 463 * things against constant major device numbers? sigh) 464 */ 465 static void 466 bsd_to_linux_stat(struct stat *bsp, struct linux_stat *lsp) 467 { 468 469 lsp->lst_dev = linux_fakedev(bsp->st_dev, 0); 470 lsp->lst_ino = bsp->st_ino; 471 lsp->lst_mode = (linux_mode_t)bsp->st_mode; 472 if (bsp->st_nlink >= (1 << 15)) 473 lsp->lst_nlink = (1 << 15) - 1; 474 else 475 lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink; 476 lsp->lst_uid = bsp->st_uid; 477 lsp->lst_gid = bsp->st_gid; 478 lsp->lst_rdev = linux_fakedev(bsp->st_rdev, 1); 479 lsp->lst_size = bsp->st_size; 480 lsp->lst_blksize = bsp->st_blksize; 481 lsp->lst_blocks = bsp->st_blocks; 482 lsp->lst_atime = bsp->st_atime; 483 lsp->lst_mtime = bsp->st_mtime; 484 lsp->lst_ctime = bsp->st_ctime; 485 #ifdef LINUX_STAT_HAS_NSEC 486 lsp->lst_atime_nsec = bsp->st_atimensec; 487 lsp->lst_mtime_nsec = bsp->st_mtimensec; 488 lsp->lst_ctime_nsec = bsp->st_ctimensec; 489 #endif 490 } 491 492 /* 493 * The stat functions below are plain sailing. stat and lstat are handled 494 * by one function to avoid code duplication. 495 */ 496 int 497 linux_sys_fstat(struct lwp *l, void *v, register_t *retval) 498 { 499 struct linux_sys_fstat_args /* { 500 syscallarg(int) fd; 501 syscallarg(linux_stat *) sp; 502 } */ *uap = v; 503 struct linux_stat tmplst; 504 struct stat tmpst; 505 int error; 506 507 error = do_sys_fstat(l, SCARG(uap, fd), &tmpst); 508 if (error != 0) 509 return error; 510 bsd_to_linux_stat(&tmpst, &tmplst); 511 512 return copyout(&tmplst, SCARG(uap, sp), sizeof tmplst); 513 } 514 515 static int 516 linux_stat1(struct lwp *l, void *v, register_t *retval, int flags) 517 { 518 struct linux_stat tmplst; 519 struct stat tmpst; 520 int error; 521 struct linux_sys_stat_args *uap = v; 522 523 error = do_sys_stat(l, SCARG(uap, path), flags, &tmpst); 524 if (error != 0) 525 return error; 526 527 bsd_to_linux_stat(&tmpst, &tmplst); 528 529 return copyout(&tmplst, SCARG(uap, sp), sizeof tmplst); 530 } 531 532 int 533 linux_sys_stat(struct lwp *l, void *v, register_t *retval) 534 { 535 struct linux_sys_stat_args /* { 536 syscallarg(const char *) path; 537 syscallarg(struct linux_stat *) sp; 538 } */ *uap = v; 539 540 return linux_stat1(l, uap, retval, FOLLOW); 541 } 542 543 /* Note: this is "newlstat" in the Linux sources */ 544 /* (we don't bother with the old lstat currently) */ 545 int 546 linux_sys_lstat(struct lwp *l, void *v, register_t *retval) 547 { 548 struct linux_sys_lstat_args /* { 549 syscallarg(const char *) path; 550 syscallarg(struct linux_stat *) sp; 551 } */ *uap = v; 552 553 return linux_stat1(l, uap, retval, NOFOLLOW); 554 } 555 #endif /* !__amd64__ */ 556 557 /* 558 * The following syscalls are mostly here because of the alternate path check. 559 */ 560 int 561 linux_sys_unlink(l, v, retval) 562 struct lwp *l; 563 void *v; 564 register_t *retval; 565 566 { 567 struct linux_sys_unlink_args /* { 568 syscallarg(const char *) path; 569 } */ *uap = v; 570 int error; 571 struct nameidata nd; 572 573 error = sys_unlink(l, uap, retval); 574 if (error != EPERM) 575 return (error); 576 577 /* 578 * Linux returns EISDIR if unlink(2) is called on a directory. 579 * We return EPERM in such cases. To emulate correct behaviour, 580 * check if the path points to directory and return EISDIR if this 581 * is the case. 582 */ 583 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE, 584 SCARG(uap, path)); 585 if (namei(&nd) == 0) { 586 struct stat sb; 587 588 if (vn_stat(nd.ni_vp, &sb, l) == 0 589 && S_ISDIR(sb.st_mode)) 590 error = EISDIR; 591 592 vput(nd.ni_vp); 593 } 594 595 return (error); 596 } 597 598 int 599 linux_sys_mknod(struct lwp *l, void *v, register_t *retval) 600 { 601 struct linux_sys_mknod_args /* { 602 syscallarg(const char *) path; 603 syscallarg(int) mode; 604 syscallarg(int) dev; 605 } */ *uap = v; 606 607 /* 608 * BSD handles FIFOs separately 609 */ 610 if (S_ISFIFO(SCARG(uap, mode))) { 611 struct sys_mkfifo_args bma; 612 613 SCARG(&bma, path) = SCARG(uap, path); 614 SCARG(&bma, mode) = SCARG(uap, mode); 615 return sys_mkfifo(l, &bma, retval); 616 } else { 617 struct sys_mknod_args bma; 618 619 SCARG(&bma, path) = SCARG(uap, path); 620 SCARG(&bma, mode) = SCARG(uap, mode); 621 /* 622 * Linux device numbers uses 8 bits for minor and 8 bits 623 * for major. Due to how we map our major and minor, 624 * this just fits into our dev_t. Just mask off the 625 * upper 16bit to remove any random junk. 626 */ 627 SCARG(&bma, dev) = SCARG(uap, dev) & 0xffff; 628 return sys_mknod(l, &bma, retval); 629 } 630 } 631 632 #if defined(__i386__) || defined(__m68k__) || \ 633 defined(__arm__) 634 int 635 linux_sys_chown16(struct lwp *l, void *v, register_t *retval) 636 { 637 struct linux_sys_chown16_args /* { 638 syscallarg(const char *) path; 639 syscallarg(int) uid; 640 syscallarg(int) gid; 641 } */ *uap = v; 642 struct sys___posix_chown_args bca; 643 644 SCARG(&bca, path) = SCARG(uap, path); 645 SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 646 (uid_t)-1 : SCARG(uap, uid); 647 SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 648 (gid_t)-1 : SCARG(uap, gid); 649 650 return sys___posix_chown(l, &bca, retval); 651 } 652 653 int 654 linux_sys_fchown16(struct lwp *l, void *v, register_t *retval) 655 { 656 struct linux_sys_fchown16_args /* { 657 syscallarg(int) fd; 658 syscallarg(int) uid; 659 syscallarg(int) gid; 660 } */ *uap = v; 661 struct sys___posix_fchown_args bfa; 662 663 SCARG(&bfa, fd) = SCARG(uap, fd); 664 SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 665 (uid_t)-1 : SCARG(uap, uid); 666 SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 667 (gid_t)-1 : SCARG(uap, gid); 668 669 return sys___posix_fchown(l, &bfa, retval); 670 } 671 672 int 673 linux_sys_lchown16(struct lwp *l, void *v, register_t *retval) 674 { 675 struct linux_sys_lchown16_args /* { 676 syscallarg(char *) path; 677 syscallarg(int) uid; 678 syscallarg(int) gid; 679 } */ *uap = v; 680 struct sys___posix_lchown_args bla; 681 682 SCARG(&bla, path) = SCARG(uap, path); 683 SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ? 684 (uid_t)-1 : SCARG(uap, uid); 685 SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ? 686 (gid_t)-1 : SCARG(uap, gid); 687 688 return sys___posix_lchown(l, &bla, retval); 689 } 690 #endif /* __i386__ || __m68k__ || __arm__ || __amd64__ */ 691 692 /* 693 * This is just fsync() for now (just as it is in the Linux kernel) 694 * Note: this is not implemented under Linux on Alpha and Arm 695 * but should still be defined in our syscalls.master. 696 * (syscall #148 on the arm) 697 */ 698 int 699 linux_sys_fdatasync(struct lwp *l, void *v, register_t *retval) 700 { 701 #ifdef notdef 702 struct linux_sys_fdatasync_args /* { 703 syscallarg(int) fd; 704 } */ *uap = v; 705 #endif 706 return sys_fsync(l, v, retval); 707 } 708 709 /* 710 * pread(2). 711 */ 712 int 713 linux_sys_pread(struct lwp *l, void *v, register_t *retval) 714 { 715 struct linux_sys_pread_args /* { 716 syscallarg(int) fd; 717 syscallarg(void *) buf; 718 syscallarg(size_t) nbyte; 719 syscallarg(linux_off_t) offset; 720 } */ *uap = v; 721 struct sys_pread_args pra; 722 723 SCARG(&pra, fd) = SCARG(uap, fd); 724 SCARG(&pra, buf) = SCARG(uap, buf); 725 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 726 SCARG(&pra, offset) = SCARG(uap, offset); 727 728 return sys_pread(l, &pra, retval); 729 } 730 731 /* 732 * pwrite(2). 733 */ 734 int 735 linux_sys_pwrite(struct lwp *l, void *v, register_t *retval) 736 { 737 struct linux_sys_pwrite_args /* { 738 syscallarg(int) fd; 739 syscallarg(void *) buf; 740 syscallarg(size_t) nbyte; 741 syscallarg(linux_off_t) offset; 742 } */ *uap = v; 743 struct sys_pwrite_args pra; 744 745 SCARG(&pra, fd) = SCARG(uap, fd); 746 SCARG(&pra, buf) = SCARG(uap, buf); 747 SCARG(&pra, nbyte) = SCARG(uap, nbyte); 748 SCARG(&pra, offset) = SCARG(uap, offset); 749 750 return sys_pwrite(l, &pra, retval); 751 } 752 753 #define LINUX_NOT_SUPPORTED(fun) \ 754 int \ 755 fun(struct lwp *l, void *v, register_t *retval) \ 756 { \ 757 return EOPNOTSUPP; \ 758 } 759 760 LINUX_NOT_SUPPORTED(linux_sys_setxattr) 761 LINUX_NOT_SUPPORTED(linux_sys_lsetxattr) 762 LINUX_NOT_SUPPORTED(linux_sys_fsetxattr) 763 764 LINUX_NOT_SUPPORTED(linux_sys_getxattr) 765 LINUX_NOT_SUPPORTED(linux_sys_lgetxattr) 766 LINUX_NOT_SUPPORTED(linux_sys_fgetxattr) 767 768 LINUX_NOT_SUPPORTED(linux_sys_listxattr) 769 LINUX_NOT_SUPPORTED(linux_sys_llistxattr) 770 LINUX_NOT_SUPPORTED(linux_sys_flistxattr) 771 772 LINUX_NOT_SUPPORTED(linux_sys_removexattr) 773 LINUX_NOT_SUPPORTED(linux_sys_lremovexattr) 774 LINUX_NOT_SUPPORTED(linux_sys_fremovexattr) 775