Annotation of sys/compat/linux/linux_file64.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: linux_file64.c,v 1.6 2003/08/03 18:08:03 deraadt Exp $ */
! 2: /* $NetBSD: linux_file64.c,v 1.2 2000/12/12 22:24:56 jdolecek Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1995, 1998, 2000 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Frank van der Linden and Eric Haszlakiewicz.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: * Linux 64bit filesystem calls. Used on 32bit archs, not used on 64bit ones.
! 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/linux_types.h>
! 62: #include <compat/linux/linux_signal.h>
! 63: #include <compat/linux/linux_syscallargs.h>
! 64: #include <compat/linux/linux_fcntl.h>
! 65: #include <compat/linux/linux_util.h>
! 66:
! 67: #include <machine/linux_machdep.h>
! 68:
! 69:
! 70: void bsd_to_linux_flock64(struct flock *, struct linux_flock64 *);
! 71: void linux_to_bsd_flock64(struct linux_flock64 *, struct flock *);
! 72: static void bsd_to_linux_stat(struct stat *, struct linux_stat64 *);
! 73: static int linux_do_stat64(struct proc *, void *, register_t *, int);
! 74:
! 75: /*
! 76: * Convert a OpenBSD stat structure to a Linux stat structure.
! 77: * Only the order of the fields and the padding in the structure
! 78: * is different. linux_fakedev is a machine-dependent function
! 79: * which optionally converts device driver major/minor numbers
! 80: * (XXX horrible, but what can you do against code that compares
! 81: * things against constant major device numbers? sigh)
! 82: */
! 83: static void
! 84: bsd_to_linux_stat(bsp, lsp)
! 85: struct stat *bsp;
! 86: struct linux_stat64 *lsp;
! 87: {
! 88: lsp->lst_dev = bsp->st_dev;
! 89: lsp->lst_ino = bsp->st_ino;
! 90: lsp->lst_mode = (linux_mode_t)bsp->st_mode;
! 91: if (bsp->st_nlink >= (1 << 15))
! 92: lsp->lst_nlink = (1 << 15) - 1;
! 93: else
! 94: lsp->lst_nlink = (linux_nlink_t)bsp->st_nlink;
! 95: lsp->lst_uid = bsp->st_uid;
! 96: lsp->lst_gid = bsp->st_gid;
! 97: lsp->lst_rdev = linux_fakedev(bsp->st_rdev);
! 98: lsp->lst_size = bsp->st_size;
! 99: lsp->lst_blksize = bsp->st_blksize;
! 100: lsp->lst_blocks = bsp->st_blocks;
! 101: lsp->lst_atime = bsp->st_atime;
! 102: lsp->lst_mtime = bsp->st_mtime;
! 103: lsp->lst_ctime = bsp->st_ctime;
! 104: #if LINUX_STAT64_HAS_BROKEN_ST_INO
! 105: lsp->__lst_ino = (linux_ino_t)bsp->st_ino;
! 106: #endif
! 107: }
! 108:
! 109: /*
! 110: * The stat functions below are plain sailing. stat and lstat are handled
! 111: * by one function to avoid code duplication.
! 112: */
! 113: int
! 114: linux_sys_fstat64(p, v, retval)
! 115: struct proc *p;
! 116: void *v;
! 117: register_t *retval;
! 118: {
! 119: struct linux_sys_fstat64_args /* {
! 120: syscallarg(int) fd;
! 121: syscallarg(linux_stat64 *) sp;
! 122: } */ *uap = v;
! 123: struct sys_fstat_args fsa;
! 124: struct linux_stat64 tmplst;
! 125: struct stat *st,tmpst;
! 126: caddr_t sg;
! 127: int error;
! 128:
! 129: sg = stackgap_init(p->p_emul);
! 130:
! 131: st = stackgap_alloc(&sg, sizeof (struct stat));
! 132:
! 133: SCARG(&fsa, fd) = SCARG(uap, fd);
! 134: SCARG(&fsa, sb) = st;
! 135:
! 136: if ((error = sys_fstat(p, &fsa, retval)))
! 137: return error;
! 138:
! 139: if ((error = copyin(st, &tmpst, sizeof tmpst)))
! 140: return error;
! 141:
! 142: bsd_to_linux_stat(&tmpst, &tmplst);
! 143:
! 144: if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
! 145: return error;
! 146:
! 147: return 0;
! 148: }
! 149:
! 150: static int
! 151: linux_do_stat64(p, v, retval, dolstat)
! 152: struct proc *p;
! 153: void *v;
! 154: register_t *retval;
! 155: int dolstat;
! 156: {
! 157: struct sys_stat_args sa;
! 158: struct linux_stat64 tmplst;
! 159: struct stat *st, tmpst;
! 160: caddr_t sg;
! 161: int error;
! 162: struct linux_sys_stat64_args *uap = v;
! 163:
! 164: sg = stackgap_init(p->p_emul);
! 165: st = stackgap_alloc(&sg, sizeof (struct stat));
! 166: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 167:
! 168: SCARG(&sa, ub) = st;
! 169: SCARG(&sa, path) = SCARG(uap, path);
! 170:
! 171: if ((error = (dolstat ? sys_lstat(p, &sa, retval) :
! 172: sys_stat(p, &sa, retval))))
! 173: return error;
! 174:
! 175: if ((error = copyin(st, &tmpst, sizeof tmpst)))
! 176: return error;
! 177:
! 178: bsd_to_linux_stat(&tmpst, &tmplst);
! 179:
! 180: if ((error = copyout(&tmplst, SCARG(uap, sp), sizeof tmplst)))
! 181: return error;
! 182:
! 183: return 0;
! 184: }
! 185:
! 186: int
! 187: linux_sys_stat64(p, v, retval)
! 188: struct proc *p;
! 189: void *v;
! 190: register_t *retval;
! 191: {
! 192: struct linux_sys_stat64_args /* {
! 193: syscallarg(const char *) path;
! 194: syscallarg(struct linux_stat64 *) sp;
! 195: } */ *uap = v;
! 196:
! 197: return linux_do_stat64(p, uap, retval, 0);
! 198: }
! 199:
! 200: int
! 201: linux_sys_lstat64(p, v, retval)
! 202: struct proc *p;
! 203: void *v;
! 204: register_t *retval;
! 205: {
! 206: struct linux_sys_lstat64_args /* {
! 207: syscallarg(char *) path;
! 208: syscallarg(struct linux_stat64 *) sp;
! 209: } */ *uap = v;
! 210:
! 211: return linux_do_stat64(p, uap, retval, 1);
! 212: }
! 213:
! 214: int
! 215: linux_sys_truncate64(p, v, retval)
! 216: struct proc *p;
! 217: void *v;
! 218: register_t *retval;
! 219: {
! 220: struct linux_sys_truncate64_args /* {
! 221: syscallarg(char *) path;
! 222: syscallarg(off_t) length;
! 223: } */ *uap = v;
! 224: struct sys_truncate_args ta;
! 225: caddr_t sg = stackgap_init(p->p_emul);
! 226:
! 227: LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
! 228:
! 229: SCARG(&ta, path) = SCARG(uap, path);
! 230: SCARG(&ta, length) = SCARG(uap, length);
! 231:
! 232: return sys_truncate(p, &ta, retval);
! 233: }
! 234:
! 235: /*
! 236: * This is needed due to padding in OpenBSD's sys_ftruncate_args
! 237: */
! 238: int
! 239: linux_sys_ftruncate64(p, v, retval)
! 240: struct proc *p;
! 241: void *v;
! 242: register_t *retval;
! 243: {
! 244: struct linux_sys_ftruncate64_args /* {
! 245: syscallarg(int) fd;
! 246: syscallarg(off_t) length;
! 247: } */ *uap = v;
! 248: struct sys_ftruncate_args fta;
! 249:
! 250: SCARG(&fta, fd) = SCARG(uap, fd);
! 251: SCARG(&fta, length) = SCARG(uap, length);
! 252:
! 253: return sys_ftruncate(p, &fta, retval);
! 254: }
! 255:
! 256: /*
! 257: * The next two functions take care of converting the flock
! 258: * structure back and forth between Linux and OpenBSD format.
! 259: * The only difference in the structures is the order of
! 260: * the fields, and the 'whence' value.
! 261: */
! 262: void
! 263: bsd_to_linux_flock64(struct flock *bfp, struct linux_flock64 *lfp)
! 264: {
! 265: lfp->l_start = bfp->l_start;
! 266: lfp->l_len = bfp->l_len;
! 267: lfp->l_pid = bfp->l_pid;
! 268: lfp->l_whence = bfp->l_whence;
! 269: switch (bfp->l_type) {
! 270: case F_RDLCK:
! 271: lfp->l_type = LINUX_F_RDLCK;
! 272: break;
! 273: case F_UNLCK:
! 274: lfp->l_type = LINUX_F_UNLCK;
! 275: break;
! 276: case F_WRLCK:
! 277: lfp->l_type = LINUX_F_WRLCK;
! 278: break;
! 279: }
! 280: }
! 281:
! 282: void
! 283: linux_to_bsd_flock64(struct linux_flock64 *lfp, struct flock *bfp)
! 284: {
! 285: bfp->l_start = lfp->l_start;
! 286: bfp->l_len = lfp->l_len;
! 287: bfp->l_pid = lfp->l_pid;
! 288: bfp->l_whence = lfp->l_whence;
! 289: switch (lfp->l_type) {
! 290: case LINUX_F_RDLCK:
! 291: bfp->l_type = F_RDLCK;
! 292: break;
! 293: case LINUX_F_UNLCK:
! 294: bfp->l_type = F_UNLCK;
! 295: break;
! 296: case LINUX_F_WRLCK:
! 297: bfp->l_type = F_WRLCK;
! 298: break;
! 299: }
! 300: }
! 301:
! 302: int
! 303: linux_sys_fcntl64(p, v, retval)
! 304: struct proc *p;
! 305: void *v;
! 306: register_t *retval;
! 307: {
! 308: struct linux_sys_fcntl64_args /* {
! 309: syscallarg(u_int) fd;
! 310: syscallarg(u_int) cmd;
! 311: syscallarg(void *) arg;
! 312: } */ *uap = v;
! 313: int fd, cmd, error;
! 314: caddr_t arg, sg;
! 315: struct linux_flock64 lfl;
! 316: struct flock *bfp, bfl;
! 317: struct sys_fcntl_args fca;
! 318:
! 319: fd = SCARG(uap, fd);
! 320: cmd = SCARG(uap, cmd);
! 321: arg = (caddr_t) SCARG(uap, arg);
! 322:
! 323: switch (cmd) {
! 324: case LINUX_F_GETLK64:
! 325: sg = stackgap_init(p->p_emul);
! 326: if ((error = copyin(arg, &lfl, sizeof lfl)))
! 327: return error;
! 328: linux_to_bsd_flock64(&lfl, &bfl);
! 329: bfp = (struct flock *) stackgap_alloc(&sg, sizeof *bfp);
! 330: SCARG(&fca, fd) = fd;
! 331: SCARG(&fca, cmd) = F_GETLK;
! 332: SCARG(&fca, arg) = bfp;
! 333: if ((error = copyout(&bfl, bfp, sizeof bfl)))
! 334: return error;
! 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_flock64(&bfl, &lfl);
! 340: error = copyout(&lfl, arg, sizeof lfl);
! 341: return (error);
! 342: case LINUX_F_SETLK64:
! 343: case LINUX_F_SETLKW64:
! 344: cmd = (cmd == LINUX_F_SETLK64 ? F_SETLK : F_SETLKW);
! 345: if ((error = copyin(arg, &lfl, sizeof lfl)))
! 346: return error;
! 347: linux_to_bsd_flock64(&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: default:
! 357: return (linux_sys_fcntl(p, v, retval));
! 358: }
! 359: /* NOTREACHED */
! 360: }
CVSweb