Annotation of sys/compat/linux/linux_file.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: linux_file.c,v 1.23 2006/09/25 07:12:57 otto Exp $ */
! 2: /* $NetBSD: linux_file.c,v 1.15 1996/05/20 01:59:09 fvdl Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Frank van der Linden
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed for the NetBSD Project
! 19: * by Frank van der Linden
! 20: * 4. The name of the author may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #include <sys/param.h>
! 36: #include <sys/systm.h>
! 37: #include <sys/namei.h>
! 38: #include <sys/proc.h>
! 39: #include <sys/file.h>
! 40: #include <sys/stat.h>
! 41: #include <sys/filedesc.h>
! 42: #include <sys/ioctl.h>
! 43: #include <sys/kernel.h>
! 44: #include <sys/mount.h>
! 45: #include <sys/signalvar.h>
! 46: #include <sys/uio.h>
! 47: #include <sys/malloc.h>
! 48: #include <sys/vnode.h>
! 49: #include <sys/tty.h>
! 50: #include <sys/conf.h>
! 51:
! 52: #include <sys/syscallargs.h>
! 53:
! 54: #include <compat/linux/linux_types.h>
! 55: #include <compat/linux/linux_signal.h>
! 56: #include <compat/linux/linux_syscallargs.h>
! 57: #include <compat/linux/linux_fcntl.h>
! 58: #include <compat/linux/linux_util.h>
! 59:
! 60: #include <machine/linux_machdep.h>
! 61:
! 62: static int linux_to_bsd_ioflags(int);
! 63: static int bsd_to_linux_ioflags(int);
! 64: static void bsd_to_linux_flock(struct flock *, struct linux_flock *);
! 65: static void linux_to_bsd_flock(struct linux_flock *, struct flock *);
! 66: static void bsd_to_linux_stat(struct stat *, struct linux_stat *);
! 67: static int linux_stat1(struct proc *, void *, register_t *, int);
! 68:
! 69:
! 70: /*
! 71: * Some file-related calls are handled here. The usual flag conversion
! 72: * an structure conversion is done, and alternate emul path searching.
! 73: */
! 74:
! 75: /*
! 76: * The next two functions convert between the Linux and OpenBSD values
! 77: * of the flags used in open(2) and fcntl(2).
! 78: */
! 79: static int
! 80: linux_to_bsd_ioflags(lflags)
! 81: int lflags;
! 82: {
! 83: int res = 0;
! 84:
! 85: res |= cvtto_bsd_mask(lflags, LINUX_O_WRONLY, O_WRONLY);
! 86: res |= cvtto_bsd_mask(lflags, LINUX_O_RDONLY, O_RDONLY);
! 87: res |= cvtto_bsd_mask(lflags, LINUX_O_RDWR, O_RDWR);
! 88: res |= cvtto_bsd_mask(lflags, LINUX_O_CREAT, O_CREAT);
! 89: res |= cvtto_bsd_mask(lflags, LINUX_O_EXCL, O_EXCL);
! 90: res |= cvtto_bsd_mask(lflags, LINUX_O_NOCTTY, O_NOCTTY);
! 91: res |= cvtto_bsd_mask(lflags, LINUX_O_TRUNC, O_TRUNC);
! 92: res |= cvtto_bsd_mask(lflags, LINUX_O_NDELAY, O_NDELAY);
! 93: res |= cvtto_bsd_mask(lflags, LINUX_O_SYNC, O_SYNC);
! 94: res |= cvtto_bsd_mask(lflags, LINUX_FASYNC, O_ASYNC);
! 95: res |= cvtto_bsd_mask(lflags, LINUX_O_APPEND, O_APPEND);
! 96:
! 97: return res;
! 98: }
! 99:
! 100: static int
! 101: bsd_to_linux_ioflags(bflags)
! 102: int bflags;
! 103: {
! 104: int res = 0;
! 105:
! 106: res |= cvtto_linux_mask(bflags, O_WRONLY, LINUX_O_WRONLY);
! 107: res |= cvtto_linux_mask(bflags, O_RDONLY, LINUX_O_RDONLY);
! 108: res |= cvtto_linux_mask(bflags, O_RDWR, LINUX_O_RDWR);
! 109: res |= cvtto_linux_mask(bflags, O_CREAT, LINUX_O_CREAT);
! 110: res |= cvtto_linux_mask(bflags, O_EXCL, LINUX_O_EXCL);
! 111: res |= cvtto_linux_mask(bflags, O_NOCTTY, LINUX_O_NOCTTY);
! 112: res |= cvtto_linux_mask(bflags, O_TRUNC, LINUX_O_TRUNC);
! 113: res |= cvtto_linux_mask(bflags, O_NDELAY, LINUX_O_NDELAY);
! 114: res |= cvtto_linux_mask(bflags, O_SYNC, LINUX_O_SYNC);
! 115: res |= cvtto_linux_mask(bflags, O_ASYNC, LINUX_FASYNC);
! 116: res |= cvtto_linux_mask(bflags, O_APPEND, LINUX_O_APPEND);
! 117:
! 118: return res;
! 119: }
! 120:
! 121: /*
! 122: * creat(2) is an obsolete function, but it's present as a Linux
! 123: * system call, so let's deal with it.
! 124: *
! 125: * Just call open(2) with the TRUNC, CREAT and WRONLY flags.
! 126: */
! 127: int
! 128: linux_sys_creat(p, v, retval)
! 129: struct proc *p;
! 130: void *v;
! 131: register_t *retval;
! 132: {
! 133: struct linux_sys_creat_args /* {
! 134: syscallarg(char *) path;
! 135: syscallarg(int) mode;
! 136: } */ *uap = v;
! 137: struct sys_open_args oa;
! 138: caddr_t sg;
! 139:
! 140: sg = stackgap_init(p->p_emul);
! 141: LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
! 142:
! 143: SCARG(&oa, path) = SCARG(uap, path);
! 144: SCARG(&oa, flags) = O_CREAT | O_TRUNC | O_WRONLY;
! 145: SCARG(&oa, mode) = SCARG(uap, mode);
! 146:
! 147: return sys_open(p, &oa, retval);
! 148: }
! 149:
! 150: /*
! 151: * open(2). Take care of the different flag values, and let the
! 152: * OpenBSD syscall do the real work. See if this operation
! 153: * gives the current process a controlling terminal.
! 154: * (XXX is this necessary?)
! 155: */
! 156: int
! 157: linux_sys_open(p, v, retval)
! 158: struct proc *p;
! 159: void *v;
! 160: register_t *retval;
! 161: {
! 162: struct linux_sys_open_args /* {
! 163: syscallarg(char *) path;
! 164: syscallarg(int) flags;
! 165: syscallarg(int) mode;
! 166: } */ *uap = v;
! 167: int error, fl;
! 168: struct sys_open_args boa;
! 169: caddr_t sg;
! 170:
! 171: sg = stackgap_init(p->p_emul);
! 172:
! 173: fl = linux_to_bsd_ioflags(SCARG(uap, flags));
! 174:
! 175: if (fl & O_CREAT)
! 176: LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
! 177: else
! 178: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 179:
! 180: SCARG(&boa, path) = SCARG(uap, path);
! 181: SCARG(&boa, flags) = fl;
! 182: SCARG(&boa, mode) = SCARG(uap, mode);
! 183:
! 184: if ((error = sys_open(p, &boa, retval)))
! 185: return error;
! 186:
! 187: /*
! 188: * this bit from sunos_misc.c (and svr4_fcntl.c).
! 189: * If we are a session leader, and we don't have a controlling
! 190: * terminal yet, and the O_NOCTTY flag is not set, try to make
! 191: * this the controlling terminal.
! 192: */
! 193: if (!(fl & O_NOCTTY) && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
! 194: struct filedesc *fdp = p->p_fd;
! 195: struct file *fp;
! 196:
! 197: if ((fp = fd_getfile(fdp, *retval)) == NULL)
! 198: return (EBADF);
! 199: FREF(fp);
! 200: if (fp->f_type == DTYPE_VNODE)
! 201: (fp->f_ops->fo_ioctl) (fp, TIOCSCTTY, (caddr_t) 0, p);
! 202: FRELE(fp);
! 203: }
! 204: return 0;
! 205: }
! 206:
! 207: /*
! 208: * This appears to be part of a Linux attempt to switch to 64 bits file sizes.
! 209: */
! 210: int
! 211: linux_sys_llseek(p, v, retval)
! 212: struct proc *p;
! 213: void *v;
! 214: register_t *retval;
! 215: {
! 216: struct linux_sys_llseek_args /* {
! 217: syscallarg(int) fd;
! 218: syscallarg(uint32_t) ohigh;
! 219: syscallarg(uint32_t) olow;
! 220: syscallarg(caddr_t) res;
! 221: syscallarg(int) whence;
! 222: } */ *uap = v;
! 223: struct sys_lseek_args bla;
! 224: int error;
! 225: off_t off;
! 226:
! 227: off = SCARG(uap, olow) | (((off_t) SCARG(uap, ohigh)) << 32);
! 228:
! 229: SCARG(&bla, fd) = SCARG(uap, fd);
! 230: SCARG(&bla, offset) = off;
! 231: SCARG(&bla, whence) = SCARG(uap, whence);
! 232:
! 233: if ((error = sys_lseek(p, &bla, retval)))
! 234: return error;
! 235:
! 236: if ((error = copyout(retval, SCARG(uap, res), sizeof (off_t))))
! 237: return error;
! 238:
! 239: retval[0] = 0;
! 240: return 0;
! 241: }
! 242:
! 243: /*
! 244: * The next two functions take care of converting the flock
! 245: * structure back and forth between Linux and OpenBSD format.
! 246: * The only difference in the structures is the order of
! 247: * the fields, and the 'whence' value.
! 248: */
! 249: static void
! 250: bsd_to_linux_flock(bfp, lfp)
! 251: struct flock *bfp;
! 252: struct linux_flock *lfp;
! 253: {
! 254:
! 255: lfp->l_start = bfp->l_start;
! 256: lfp->l_len = bfp->l_len;
! 257: lfp->l_pid = bfp->l_pid;
! 258: lfp->l_whence = bfp->l_whence;
! 259: switch (bfp->l_type) {
! 260: case F_RDLCK:
! 261: lfp->l_type = LINUX_F_RDLCK;
! 262: break;
! 263: case F_UNLCK:
! 264: lfp->l_type = LINUX_F_UNLCK;
! 265: break;
! 266: case F_WRLCK:
! 267: lfp->l_type = LINUX_F_WRLCK;
! 268: break;
! 269: }
! 270: }
! 271:
! 272: static void
! 273: linux_to_bsd_flock(lfp, bfp)
! 274: struct linux_flock *lfp;
! 275: struct flock *bfp;
! 276: {
! 277:
! 278: bfp->l_start = lfp->l_start;
! 279: bfp->l_len = lfp->l_len;
! 280: bfp->l_pid = lfp->l_pid;
! 281: bfp->l_whence = lfp->l_whence;
! 282: switch (lfp->l_type) {
! 283: case LINUX_F_RDLCK:
! 284: bfp->l_type = F_RDLCK;
! 285: break;
! 286: case LINUX_F_UNLCK:
! 287: bfp->l_type = F_UNLCK;
! 288: break;
! 289: case LINUX_F_WRLCK:
! 290: bfp->l_type = F_WRLCK;
! 291: break;
! 292: }
! 293: }
! 294:
! 295: /*
! 296: * Most actions in the fcntl() call are straightforward; simply
! 297: * pass control to the OpenBSD system call. A few commands need
! 298: * conversions after the actual system call has done its work,
! 299: * because the flag values and lock structure are different.
! 300: */
! 301: int
! 302: linux_sys_fcntl(p, v, retval)
! 303: struct proc *p;
! 304: void *v;
! 305: register_t *retval;
! 306: {
! 307: struct linux_sys_fcntl_args /* {
! 308: syscallarg(int) fd;
! 309: syscallarg(int) cmd;
! 310: syscallarg(void *) arg;
! 311: } */ *uap = v;
! 312: int fd, cmd, error, val;
! 313: caddr_t arg, sg;
! 314: struct linux_flock lfl;
! 315: struct flock *bfp, bfl;
! 316: struct sys_fcntl_args fca;
! 317: struct filedesc *fdp;
! 318: struct file *fp;
! 319: struct vnode *vp;
! 320: struct vattr va;
! 321: long pgid;
! 322: struct pgrp *pgrp;
! 323: struct tty *tp, *(*d_tty)(dev_t);
! 324:
! 325: fd = SCARG(uap, fd);
! 326: cmd = SCARG(uap, cmd);
! 327: arg = (caddr_t) SCARG(uap, arg);
! 328:
! 329: switch (cmd) {
! 330: case LINUX_F_DUPFD:
! 331: cmd = F_DUPFD;
! 332: break;
! 333: case LINUX_F_GETFD:
! 334: cmd = F_GETFD;
! 335: break;
! 336: case LINUX_F_SETFD:
! 337: cmd = F_SETFD;
! 338: break;
! 339: case LINUX_F_GETFL:
! 340: SCARG(&fca, fd) = fd;
! 341: SCARG(&fca, cmd) = F_GETFL;
! 342: SCARG(&fca, arg) = arg;
! 343: if ((error = sys_fcntl(p, &fca, retval)))
! 344: return error;
! 345: retval[0] = bsd_to_linux_ioflags(retval[0]);
! 346: return 0;
! 347: case LINUX_F_SETFL:
! 348: val = linux_to_bsd_ioflags((int)SCARG(uap, arg));
! 349: SCARG(&fca, fd) = fd;
! 350: SCARG(&fca, cmd) = F_SETFL;
! 351: SCARG(&fca, arg) = (caddr_t) val;
! 352: return sys_fcntl(p, &fca, retval);
! 353: case LINUX_F_GETLK:
! 354: sg = stackgap_init(p->p_emul);
! 355: if ((error = copyin(arg, &lfl, sizeof lfl)))
! 356: return error;
! 357: linux_to_bsd_flock(&lfl, &bfl);
! 358: bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
! 359: SCARG(&fca, fd) = fd;
! 360: SCARG(&fca, cmd) = F_GETLK;
! 361: SCARG(&fca, arg) = bfp;
! 362: if ((error = copyout(&bfl, bfp, sizeof bfl)))
! 363: return error;
! 364: if ((error = sys_fcntl(p, &fca, retval)))
! 365: return error;
! 366: if ((error = copyin(bfp, &bfl, sizeof bfl)))
! 367: return error;
! 368: bsd_to_linux_flock(&bfl, &lfl);
! 369: error = copyout(&lfl, arg, sizeof lfl);
! 370: return error;
! 371: break;
! 372: case LINUX_F_SETLK:
! 373: case LINUX_F_SETLKW:
! 374: cmd = (cmd == LINUX_F_SETLK ? F_SETLK : F_SETLKW);
! 375: if ((error = copyin(arg, &lfl, sizeof lfl)))
! 376: return error;
! 377: linux_to_bsd_flock(&lfl, &bfl);
! 378: sg = stackgap_init(p->p_emul);
! 379: bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
! 380: if ((error = copyout(&bfl, bfp, sizeof bfl)))
! 381: return error;
! 382: SCARG(&fca, fd) = fd;
! 383: SCARG(&fca, cmd) = cmd;
! 384: SCARG(&fca, arg) = bfp;
! 385: return sys_fcntl(p, &fca, retval);
! 386: break;
! 387: case LINUX_F_SETOWN:
! 388: case LINUX_F_GETOWN:
! 389: /*
! 390: * We need to route around the normal fcntl() for these calls,
! 391: * since it uses TIOC{G,S}PGRP, which is too restrictive for
! 392: * Linux F_{G,S}ETOWN semantics. For sockets, this problem
! 393: * does not exist.
! 394: */
! 395: fdp = p->p_fd;
! 396: if ((fp = fd_getfile(fdp, fd)) == NULL)
! 397: return (EBADF);
! 398: if (fp->f_type == DTYPE_SOCKET) {
! 399: cmd = cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
! 400: break;
! 401: }
! 402: vp = (struct vnode *)fp->f_data;
! 403: if (vp->v_type != VCHR)
! 404: return EINVAL;
! 405: FREF(fp);
! 406: error = VOP_GETATTR(vp, &va, p->p_ucred, p);
! 407: FRELE(fp);
! 408: if (error)
! 409: return error;
! 410: d_tty = cdevsw[major(va.va_rdev)].d_tty;
! 411: if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
! 412: return EINVAL;
! 413: if (cmd == LINUX_F_GETOWN) {
! 414: retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
! 415: return 0;
! 416: }
! 417: if ((long)arg <= 0) {
! 418: pgid = -(long)arg;
! 419: } else {
! 420: struct proc *p1 = pfind((long)arg);
! 421: if (p1 == 0)
! 422: return (ESRCH);
! 423: pgid = (long)p1->p_pgrp->pg_id;
! 424: }
! 425: pgrp = pgfind(pgid);
! 426: if (pgrp == NULL || pgrp->pg_session != p->p_session)
! 427: return EPERM;
! 428: tp->t_pgrp = pgrp;
! 429: return 0;
! 430: default:
! 431: return EOPNOTSUPP;
! 432: }
! 433:
! 434: SCARG(&fca, fd) = fd;
! 435: SCARG(&fca, cmd) = cmd;
! 436: SCARG(&fca, arg) = arg;
! 437:
! 438: return sys_fcntl(p, &fca, retval);
! 439: }
! 440:
! 441: /*
! 442: * Convert a OpenBSD stat structure to a Linux stat structure.
! 443: * Only the order of the fields and the padding in the structure
! 444: * is different. linux_fakedev is a machine-dependent function
! 445: * which optionally converts device driver major/minor numbers
! 446: * (XXX horrible, but what can you do against code that compares
! 447: * things against constant major device numbers? sigh)
! 448: */
! 449: static void
! 450: bsd_to_linux_stat(bsp, lsp)
! 451: struct stat *bsp;
! 452: struct linux_stat *lsp;
! 453: {
! 454:
! 455: lsp->lst_dev = bsp->st_dev;
! 456: lsp->lst_ino = bsp->st_ino;
! 457: lsp->lst_mode = bsp->st_mode;
! 458: lsp->lst_nlink = bsp->st_nlink;
! 459: lsp->lst_uid = bsp->st_uid;
! 460: lsp->lst_gid = bsp->st_gid;
! 461: lsp->lst_rdev = linux_fakedev(bsp->st_rdev);
! 462: lsp->lst_size = bsp->st_size;
! 463: lsp->lst_blksize = bsp->st_blksize;
! 464: lsp->lst_blocks = bsp->st_blocks;
! 465: lsp->lst_atime = bsp->st_atime;
! 466: lsp->lst_mtime = bsp->st_mtime;
! 467: lsp->lst_ctime = bsp->st_ctime;
! 468: }
! 469:
! 470: /*
! 471: * The stat functions below are plain sailing. stat and lstat are handled
! 472: * by one function to avoid code duplication.
! 473: */
! 474: int
! 475: linux_sys_fstat(p, v, retval)
! 476: struct proc *p;
! 477: void *v;
! 478: register_t *retval;
! 479: {
! 480: struct linux_sys_fstat_args /* {
! 481: syscallarg(int) fd;
! 482: syscallarg(linux_stat *) sp;
! 483: } */ *uap = v;
! 484: struct sys_fstat_args fsa;
! 485: struct linux_stat tmplst;
! 486: struct stat *st,tmpst;
! 487: caddr_t sg;
! 488: int error;
! 489:
! 490: sg = stackgap_init(p->p_emul);
! 491:
! 492: st = stackgap_alloc(&sg, sizeof (struct stat));
! 493:
! 494: SCARG(&fsa, fd) = SCARG(uap, fd);
! 495: SCARG(&fsa, sb) = st;
! 496:
! 497: if ((error = sys_fstat(p, &fsa, retval)))
! 498: return error;
! 499:
! 500: if ((error = copyin(st, &tmpst, sizeof tmpst)))
! 501: return error;
! 502:
! 503: bsd_to_linux_stat(&tmpst, &tmplst);
! 504:
! 505: if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
! 506: return error;
! 507:
! 508: return 0;
! 509: }
! 510:
! 511: static int
! 512: linux_stat1(p, v, retval, dolstat)
! 513: struct proc *p;
! 514: void *v;
! 515: register_t *retval;
! 516: int dolstat;
! 517: {
! 518: struct sys_stat_args sa;
! 519: struct linux_stat tmplst;
! 520: struct stat *st, tmpst;
! 521: caddr_t sg;
! 522: int error;
! 523: struct linux_sys_stat_args *uap = v;
! 524:
! 525: sg = stackgap_init(p->p_emul);
! 526:
! 527: st = stackgap_alloc(&sg, sizeof (struct stat));
! 528: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 529:
! 530: SCARG(&sa, ub) = st;
! 531: SCARG(&sa, path) = SCARG(uap, path);
! 532:
! 533: if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
! 534: sys_stat(p, &sa, retval))))
! 535: return error;
! 536:
! 537: if ((error = copyin(st, &tmpst, sizeof tmpst)))
! 538: return error;
! 539:
! 540: bsd_to_linux_stat(&tmpst, &tmplst);
! 541:
! 542: if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
! 543: return error;
! 544:
! 545: return 0;
! 546: }
! 547:
! 548: int
! 549: linux_sys_stat(p, v, retval)
! 550: struct proc *p;
! 551: void *v;
! 552: register_t *retval;
! 553: {
! 554: struct linux_sys_stat_args /* {
! 555: syscallarg(char *) path;
! 556: syscallarg(struct linux_stat *) sp;
! 557: } */ *uap = v;
! 558:
! 559: return linux_stat1(p, uap, retval, 0);
! 560: }
! 561:
! 562: int
! 563: linux_sys_lstat(p, v, retval)
! 564: struct proc *p;
! 565: void *v;
! 566: register_t *retval;
! 567: {
! 568: struct linux_sys_lstat_args /* {
! 569: syscallarg(char *) path;
! 570: syscallarg(struct linux_stat *) sp;
! 571: } */ *uap = v;
! 572:
! 573: return linux_stat1(p, uap, retval, 1);
! 574: }
! 575:
! 576: /*
! 577: * The following syscalls are mostly here because of the alternate path check.
! 578: */
! 579: int
! 580: linux_sys_access(p, v, retval)
! 581: struct proc *p;
! 582: void *v;
! 583: register_t *retval;
! 584: {
! 585: struct linux_sys_access_args /* {
! 586: syscallarg(char *) path;
! 587: syscallarg(int) flags;
! 588: } */ *uap = v;
! 589: caddr_t sg = stackgap_init(p->p_emul);
! 590:
! 591: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 592:
! 593: return sys_access(p, uap, retval);
! 594: }
! 595:
! 596: int
! 597: linux_sys_unlink(p, v, retval)
! 598: struct proc *p;
! 599: void *v;
! 600: register_t *retval;
! 601:
! 602: {
! 603: struct linux_sys_unlink_args /* {
! 604: syscallarg(char *) path;
! 605: } */ *uap = v;
! 606: caddr_t sg = stackgap_init(p->p_emul);
! 607:
! 608: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 609:
! 610: return sys_unlink(p, uap, retval);
! 611: }
! 612:
! 613: int
! 614: linux_sys_chdir(p, v, retval)
! 615: struct proc *p;
! 616: void *v;
! 617: register_t *retval;
! 618: {
! 619: struct linux_sys_chdir_args /* {
! 620: syscallarg(char *) path;
! 621: } */ *uap = v;
! 622: caddr_t sg = stackgap_init(p->p_emul);
! 623:
! 624: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 625:
! 626: return sys_chdir(p, uap, retval);
! 627: }
! 628:
! 629: int
! 630: linux_sys_mknod(p, v, retval)
! 631: struct proc *p;
! 632: void *v;
! 633: register_t *retval;
! 634: {
! 635: struct linux_sys_mknod_args /* {
! 636: syscallarg(char *) path;
! 637: syscallarg(int) mode;
! 638: syscallarg(int) dev;
! 639: } */ *uap = v;
! 640: caddr_t sg = stackgap_init(p->p_emul);
! 641: struct sys_mkfifo_args bma;
! 642:
! 643: LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
! 644:
! 645: /*
! 646: * BSD handles FIFOs separately
! 647: */
! 648: if (S_ISFIFO(SCARG(uap, mode))) {
! 649: SCARG(&bma, path) = SCARG(uap, path);
! 650: SCARG(&bma, mode) = SCARG(uap, mode);
! 651: return sys_mkfifo(p, uap, retval);
! 652: } else
! 653: return sys_mknod(p, uap, retval);
! 654: }
! 655:
! 656: int
! 657: linux_sys_chmod(p, v, retval)
! 658: struct proc *p;
! 659: void *v;
! 660: register_t *retval;
! 661: {
! 662: struct linux_sys_chmod_args /* {
! 663: syscallarg(char *) path;
! 664: syscallarg(int) mode;
! 665: } */ *uap = v;
! 666: caddr_t sg = stackgap_init(p->p_emul);
! 667:
! 668: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 669:
! 670: return sys_chmod(p, uap, retval);
! 671: }
! 672:
! 673: int
! 674: linux_sys_chown16(p, v, retval)
! 675: struct proc *p;
! 676: void *v;
! 677: register_t *retval;
! 678: {
! 679: struct linux_sys_chown16_args /* {
! 680: syscallarg(char *) path;
! 681: syscallarg(int) uid;
! 682: syscallarg(int) gid;
! 683: } */ *uap = v;
! 684: struct sys_chown_args bca;
! 685: caddr_t sg = stackgap_init(p->p_emul);
! 686:
! 687: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 688:
! 689: SCARG(&bca, path) = SCARG(uap, path);
! 690: SCARG(&bca, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
! 691: (uid_t)-1 : SCARG(uap, uid);
! 692: SCARG(&bca, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
! 693: (gid_t)-1 : SCARG(uap, gid);
! 694:
! 695: return sys_chown(p, &bca, retval);
! 696: }
! 697:
! 698: int
! 699: linux_sys_fchown16(p, v, retval)
! 700: struct proc *p;
! 701: void *v;
! 702: register_t *retval;
! 703: {
! 704: struct linux_sys_fchown16_args /* {
! 705: syscallarg(int) fd;
! 706: syscallarg(int) uid;
! 707: syscallarg(int) gid;
! 708: } */ *uap = v;
! 709: struct sys_fchown_args bfa;
! 710:
! 711: SCARG(&bfa, fd) = SCARG(uap, fd);
! 712: SCARG(&bfa, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
! 713: (uid_t)-1 : SCARG(uap, uid);
! 714: SCARG(&bfa, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
! 715: (gid_t)-1 : SCARG(uap, gid);
! 716:
! 717: return sys_fchown(p, &bfa, retval);
! 718: }
! 719:
! 720: int
! 721: linux_sys_lchown16(p, v, retval)
! 722: struct proc *p;
! 723: void *v;
! 724: register_t *retval;
! 725: {
! 726: struct linux_sys_lchown16_args /* {
! 727: syscallarg(char *) path;
! 728: syscallarg(int) uid;
! 729: syscallarg(int) gid;
! 730: } */ *uap = v;
! 731: struct sys_lchown_args bla;
! 732:
! 733: SCARG(&bla, path) = SCARG(uap, path);
! 734: SCARG(&bla, uid) = ((linux_uid_t)SCARG(uap, uid) == (linux_uid_t)-1) ?
! 735: (uid_t)-1 : SCARG(uap, uid);
! 736: SCARG(&bla, gid) = ((linux_gid_t)SCARG(uap, gid) == (linux_gid_t)-1) ?
! 737: (gid_t)-1 : SCARG(uap, gid);
! 738:
! 739: return sys_lchown(p, &bla, retval);
! 740: }
! 741:
! 742: int
! 743: linux_sys_rename(p, v, retval)
! 744: struct proc *p;
! 745: void *v;
! 746: register_t *retval;
! 747: {
! 748: struct linux_sys_rename_args /* {
! 749: syscallarg(char *) from;
! 750: syscallarg(char *) to;
! 751: } */ *uap = v;
! 752: caddr_t sg = stackgap_init(p->p_emul);
! 753:
! 754: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, from));
! 755: LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
! 756:
! 757: return sys_rename(p, uap, retval);
! 758: }
! 759:
! 760: int
! 761: linux_sys_mkdir(p, v, retval)
! 762: struct proc *p;
! 763: void *v;
! 764: register_t *retval;
! 765: {
! 766: struct linux_sys_mkdir_args /* {
! 767: syscallarg(char *) path;
! 768: syscallarg(int) mode;
! 769: } */ *uap = v;
! 770: caddr_t sg = stackgap_init(p->p_emul);
! 771:
! 772: LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
! 773:
! 774: return sys_mkdir(p, uap, retval);
! 775: }
! 776:
! 777: int
! 778: linux_sys_rmdir(p, v, retval)
! 779: struct proc *p;
! 780: void *v;
! 781: register_t *retval;
! 782: {
! 783: struct linux_sys_rmdir_args /* {
! 784: syscallarg(char *) path;
! 785: } */ *uap = v;
! 786: caddr_t sg = stackgap_init(p->p_emul);
! 787:
! 788: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 789:
! 790: return sys_rmdir(p, uap, retval);
! 791: }
! 792:
! 793: int
! 794: linux_sys_symlink(p, v, retval)
! 795: struct proc *p;
! 796: void *v;
! 797: register_t *retval;
! 798: {
! 799: struct linux_sys_symlink_args /* {
! 800: syscallarg(char *) path;
! 801: syscallarg(char *) to;
! 802: } */ *uap = v;
! 803: caddr_t sg = stackgap_init(p->p_emul);
! 804:
! 805: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 806: LINUX_CHECK_ALT_CREAT(p, &sg, SCARG(uap, to));
! 807:
! 808: return sys_symlink(p, uap, retval);
! 809: }
! 810:
! 811: int
! 812: linux_sys_readlink(p, v, retval)
! 813: struct proc *p;
! 814: void *v;
! 815: register_t *retval;
! 816: {
! 817: struct linux_sys_readlink_args /* {
! 818: syscallarg(char *) name;
! 819: syscallarg(char *) buf;
! 820: syscallarg(int) count;
! 821: } */ *uap = v;
! 822: caddr_t sg = stackgap_init(p->p_emul);
! 823:
! 824: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, name));
! 825:
! 826: return sys_readlink(p, uap, retval);
! 827: }
! 828:
! 829: int
! 830: linux_sys_truncate(p, v, retval)
! 831: struct proc *p;
! 832: void *v;
! 833: register_t *retval;
! 834: {
! 835: struct linux_sys_truncate_args /* {
! 836: syscallarg(char *) path;
! 837: syscallarg(long) length;
! 838: } */ *uap = v;
! 839: caddr_t sg = stackgap_init(p->p_emul);
! 840:
! 841: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 842:
! 843: return compat_43_sys_truncate(p, uap, retval);
! 844: }
! 845:
! 846: /*
! 847: * This is just fsync() for now (just as it is in the Linux kernel)
! 848: */
! 849: int
! 850: linux_sys_fdatasync(p, v, retval)
! 851: struct proc *p;
! 852: void *v;
! 853: register_t *retval;
! 854: {
! 855: struct linux_sys_fdatasync_args /* {
! 856: syscallarg(int) fd;
! 857: } */ *uap = v;
! 858: return sys_fsync(p, uap, retval);
! 859: }
! 860:
! 861: /*
! 862: * pread(2).
! 863: */
! 864: int
! 865: linux_sys_pread(p, v, retval)
! 866: struct proc *p;
! 867: void *v;
! 868: register_t *retval;
! 869: {
! 870: struct linux_sys_pread_args /* {
! 871: syscallarg(int) fd;
! 872: syscallarg(void *) buf;
! 873: syscallarg(size_t) nbyte;
! 874: syscallarg(linux_off_t) offset;
! 875: } */ *uap = v;
! 876: struct sys_pread_args pra;
! 877:
! 878: SCARG(&pra, fd) = SCARG(uap, fd);
! 879: SCARG(&pra, buf) = SCARG(uap, buf);
! 880: SCARG(&pra, nbyte) = SCARG(uap, nbyte);
! 881: SCARG(&pra, offset) = SCARG(uap, offset);
! 882:
! 883: return sys_pread(p, &pra, retval);
! 884: }
! 885:
! 886: /*
! 887: * pwrite(2).
! 888: */
! 889: int
! 890: linux_sys_pwrite(p, v, retval)
! 891: struct proc *p;
! 892: void *v;
! 893: register_t *retval;
! 894: {
! 895: struct linux_sys_pwrite_args /* {
! 896: syscallarg(int) fd;
! 897: syscallarg(char *) buf;
! 898: syscallarg(size_t) nbyte;
! 899: syscallarg(linux_off_t) offset;
! 900: } */ *uap = v;
! 901: struct sys_pwrite_args pra;
! 902:
! 903: SCARG(&pra, fd) = SCARG(uap, fd);
! 904: SCARG(&pra, buf) = SCARG(uap, buf);
! 905: SCARG(&pra, nbyte) = SCARG(uap, nbyte);
! 906: SCARG(&pra, offset) = SCARG(uap, offset);
! 907:
! 908: return sys_pwrite(p, &pra, retval);
! 909: }
CVSweb