Annotation of sys/compat/linux/linux_ipc.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: linux_ipc.c,v 1.10 2007/05/29 10:44:29 sturm Exp $ */
! 2: /* $NetBSD: linux_ipc.c,v 1.10 1996/04/05 00:01:44 christos 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/types.h>
! 36: #include <sys/param.h>
! 37: #include <sys/kernel.h>
! 38: #include <sys/shm.h>
! 39: #include <sys/sem.h>
! 40: #include <sys/msg.h>
! 41: #include <sys/proc.h>
! 42: #include <sys/uio.h>
! 43: #include <sys/time.h>
! 44: #include <sys/malloc.h>
! 45: #include <sys/mman.h>
! 46: #include <sys/systm.h>
! 47: #include <sys/stat.h>
! 48:
! 49: #include <sys/mount.h>
! 50: #include <sys/syscallargs.h>
! 51:
! 52: #include <compat/linux/linux_types.h>
! 53: #include <compat/linux/linux_signal.h>
! 54: #include <compat/linux/linux_syscallargs.h>
! 55: #include <compat/linux/linux_util.h>
! 56: #include <compat/linux/linux_ipc.h>
! 57: #include <compat/linux/linux_msg.h>
! 58: #include <compat/linux/linux_shm.h>
! 59: #include <compat/linux/linux_sem.h>
! 60: #include <compat/linux/linux_ipccall.h>
! 61:
! 62: /*
! 63: * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
! 64: * The main difference is, that Linux handles it all via one
! 65: * system call, which has the usual maximum amount of 5 arguments.
! 66: * This results in a kludge for calls that take 6 of them.
! 67: *
! 68: * The SYSVXXXX options have to be enabled to get the appropriate
! 69: * functions to work.
! 70: */
! 71:
! 72: #ifdef SYSVSEM
! 73: int linux_semop(struct proc *, void *, register_t *);
! 74: int linux_semget(struct proc *, void *, register_t *);
! 75: int linux_semctl(struct proc *, void *, register_t *);
! 76: void bsd_to_linux_semid_ds(struct semid_ds *, struct linux_semid_ds *);
! 77: void linux_to_bsd_semid_ds(struct linux_semid_ds *, struct semid_ds *);
! 78: #endif
! 79:
! 80: #ifdef SYSVMSG
! 81: int linux_msgsnd(struct proc *, void *, register_t *);
! 82: int linux_msgrcv(struct proc *, void *, register_t *);
! 83: int linux_msgget(struct proc *, void *, register_t *);
! 84: int linux_msgctl(struct proc *, void *, register_t *);
! 85: void linux_to_bsd_msqid_ds(struct linux_msqid_ds *, struct msqid_ds *);
! 86: void bsd_to_linux_msqid_ds(struct msqid_ds *, struct linux_msqid_ds *);
! 87: #endif
! 88:
! 89: #ifdef SYSVSHM
! 90: int linux_shmat(struct proc *, void *, register_t *);
! 91: int linux_shmdt(struct proc *, void *, register_t *);
! 92: int linux_shmget(struct proc *, void *, register_t *);
! 93: int linux_shmctl(struct proc *, void *, register_t *);
! 94: void linux_to_bsd_shmid_ds(struct linux_shmid_ds *, struct shmid_ds *);
! 95: void bsd_to_linux_shmid_ds(struct shmid_ds *, struct linux_shmid_ds *);
! 96: #endif
! 97:
! 98: #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
! 99: void linux_to_bsd_ipc_perm(struct linux_ipc_perm *, struct ipc_perm *);
! 100: void bsd_to_linux_ipc_perm(struct ipc_perm *, struct linux_ipc_perm *);
! 101: #endif
! 102:
! 103: int
! 104: linux_sys_ipc(p, v, retval)
! 105: struct proc *p;
! 106: void *v;
! 107: register_t *retval;
! 108: {
! 109: struct linux_sys_ipc_args /* {
! 110: syscallarg(int) what;
! 111: syscallarg(int) a1;
! 112: syscallarg(int) a2;
! 113: syscallarg(int) a3;
! 114: syscallarg(caddr_t) ptr;
! 115: } */ *uap = v;
! 116:
! 117: switch (SCARG(uap, what)) {
! 118: #ifdef SYSVSEM
! 119: case LINUX_SYS_semop:
! 120: return linux_semop(p, uap, retval);
! 121: case LINUX_SYS_semget:
! 122: return linux_semget(p, uap, retval);
! 123: case LINUX_SYS_semctl:
! 124: return linux_semctl(p, uap, retval);
! 125: #endif
! 126: #ifdef SYSVMSG
! 127: case LINUX_SYS_msgsnd:
! 128: return linux_msgsnd(p, uap, retval);
! 129: case LINUX_SYS_msgrcv:
! 130: return linux_msgrcv(p, uap, retval);
! 131: case LINUX_SYS_msgget:
! 132: return linux_msgget(p, uap, retval);
! 133: case LINUX_SYS_msgctl:
! 134: return linux_msgctl(p, uap, retval);
! 135: #endif
! 136: #ifdef SYSVSHM
! 137: case LINUX_SYS_shmat:
! 138: return linux_shmat(p, uap, retval);
! 139: case LINUX_SYS_shmdt:
! 140: return linux_shmdt(p, uap, retval);
! 141: case LINUX_SYS_shmget:
! 142: return linux_shmget(p, uap, retval);
! 143: case LINUX_SYS_shmctl:
! 144: return linux_shmctl(p, uap, retval);
! 145: #endif
! 146: default:
! 147: return ENOSYS;
! 148: }
! 149: }
! 150:
! 151: #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
! 152: /*
! 153: * Convert between Linux and OpenBSD ipc_perm structures. Only the
! 154: * order of the fields is different.
! 155: */
! 156: void
! 157: linux_to_bsd_ipc_perm(lpp, bpp)
! 158: struct linux_ipc_perm *lpp;
! 159: struct ipc_perm *bpp;
! 160: {
! 161:
! 162: bpp->key = lpp->l_key;
! 163: bpp->uid = lpp->l_uid;
! 164: bpp->gid = lpp->l_gid;
! 165: bpp->cuid = lpp->l_cuid;
! 166: bpp->cgid = lpp->l_cgid;
! 167: bpp->mode = lpp->l_mode;
! 168: bpp->seq = lpp->l_seq;
! 169: }
! 170:
! 171: void
! 172: bsd_to_linux_ipc_perm(bpp, lpp)
! 173: struct ipc_perm *bpp;
! 174: struct linux_ipc_perm *lpp;
! 175: {
! 176:
! 177: lpp->l_key = bpp->key;
! 178: lpp->l_uid = bpp->uid;
! 179: lpp->l_gid = bpp->gid;
! 180: lpp->l_cuid = bpp->cuid;
! 181: lpp->l_cgid = bpp->cgid;
! 182: lpp->l_mode = bpp->mode;
! 183: lpp->l_seq = bpp->seq;
! 184: }
! 185: #endif
! 186:
! 187: #ifdef SYSVSEM
! 188: /*
! 189: * Semaphore operations. Most constants and structures are the same on
! 190: * both systems. Only semctl() needs some extra work.
! 191: */
! 192:
! 193: /*
! 194: * Convert between Linux and OpenBSD semid_ds structures.
! 195: */
! 196: void
! 197: bsd_to_linux_semid_ds(bs, ls)
! 198: struct semid_ds *bs;
! 199: struct linux_semid_ds *ls;
! 200: {
! 201:
! 202: bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
! 203: ls->l_sem_otime = bs->sem_otime;
! 204: ls->l_sem_ctime = bs->sem_ctime;
! 205: ls->l_sem_nsems = bs->sem_nsems;
! 206: ls->l_sem_base = bs->sem_base;
! 207: }
! 208:
! 209: void
! 210: linux_to_bsd_semid_ds(ls, bs)
! 211: struct linux_semid_ds *ls;
! 212: struct semid_ds *bs;
! 213: {
! 214:
! 215: linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
! 216: bs->sem_otime = ls->l_sem_otime;
! 217: bs->sem_ctime = ls->l_sem_ctime;
! 218: bs->sem_nsems = ls->l_sem_nsems;
! 219: bs->sem_base = ls->l_sem_base;
! 220: }
! 221:
! 222: int
! 223: linux_semop(p, v, retval)
! 224: struct proc *p;
! 225: void *v;
! 226: register_t *retval;
! 227: {
! 228: struct linux_sys_ipc_args /* {
! 229: syscallarg(int) what;
! 230: syscallarg(int) a1;
! 231: syscallarg(int) a2;
! 232: syscallarg(int) a3;
! 233: syscallarg(caddr_t) ptr;
! 234: } */ *uap = v;
! 235: struct sys_semop_args bsa;
! 236:
! 237: SCARG(&bsa, semid) = SCARG(uap, a1);
! 238: SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
! 239: SCARG(&bsa, nsops) = SCARG(uap, a2);
! 240:
! 241: return sys_semop(p, &bsa, retval);
! 242: }
! 243:
! 244: int
! 245: linux_semget(p, v, retval)
! 246: struct proc *p;
! 247: void *v;
! 248: register_t *retval;
! 249: {
! 250: struct linux_sys_ipc_args /* {
! 251: syscallarg(int) what;
! 252: syscallarg(int) a1;
! 253: syscallarg(int) a2;
! 254: syscallarg(int) a3;
! 255: syscallarg(caddr_t) ptr;
! 256: } */ *uap = v;
! 257: struct sys_semget_args bsa;
! 258:
! 259: SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
! 260: SCARG(&bsa, nsems) = SCARG(uap, a2);
! 261: SCARG(&bsa, semflg) = SCARG(uap, a3);
! 262:
! 263: return sys_semget(p, &bsa, retval);
! 264: }
! 265:
! 266: /*
! 267: * Most of this can be handled by directly passing the arguments on,
! 268: * buf IPC_* require a lot of copy{in,out} because of the extra indirection
! 269: * (we are passed a pointer to a union cointaining a pointer to a semid_ds
! 270: * structure.
! 271: */
! 272: int
! 273: linux_semctl(p, v, retval)
! 274: struct proc *p;
! 275: void *v;
! 276: register_t *retval;
! 277: {
! 278: struct linux_sys_ipc_args /* {
! 279: syscallarg(int) what;
! 280: syscallarg(int) a1;
! 281: syscallarg(int) a2;
! 282: syscallarg(int) a3;
! 283: syscallarg(caddr_t) ptr;
! 284: } */ *uap = v;
! 285: caddr_t sg, unptr, dsp, ldsp;
! 286: int error, cmd;
! 287: struct sys___semctl_args bsa;
! 288: struct linux_semid_ds lm;
! 289: struct semid_ds bm;
! 290:
! 291: SCARG(&bsa, semid) = SCARG(uap, a1);
! 292: SCARG(&bsa, semnum) = SCARG(uap, a2);
! 293: SCARG(&bsa, cmd) = SCARG(uap, a3);
! 294: SCARG(&bsa, arg) = (union semun *)SCARG(uap, ptr);
! 295: switch(SCARG(uap, a3)) {
! 296: case LINUX_GETVAL:
! 297: cmd = GETVAL;
! 298: break;
! 299: case LINUX_GETPID:
! 300: cmd = GETPID;
! 301: break;
! 302: case LINUX_GETNCNT:
! 303: cmd = GETNCNT;
! 304: break;
! 305: case LINUX_GETZCNT:
! 306: cmd = GETZCNT;
! 307: break;
! 308: case LINUX_SETVAL:
! 309: cmd = SETVAL;
! 310: break;
! 311: case LINUX_IPC_RMID:
! 312: cmd = IPC_RMID;
! 313: break;
! 314: case LINUX_IPC_SET:
! 315: if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
! 316: return error;
! 317: if ((error = copyin(ldsp, (caddr_t)&lm, sizeof lm)))
! 318: return error;
! 319: linux_to_bsd_semid_ds(&lm, &bm);
! 320: sg = stackgap_init(p->p_emul);
! 321: unptr = stackgap_alloc(&sg, sizeof (union semun));
! 322: dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
! 323: if ((error = copyout((caddr_t)&bm, dsp, sizeof bm)))
! 324: return error;
! 325: if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
! 326: return error;
! 327: SCARG(&bsa, arg) = (union semun *)unptr;
! 328: return sys___semctl(p, &bsa, retval);
! 329: case LINUX_IPC_STAT:
! 330: sg = stackgap_init(p->p_emul);
! 331: unptr = stackgap_alloc(&sg, sizeof (union semun *));
! 332: dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
! 333: if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
! 334: return error;
! 335: SCARG(&bsa, arg) = (union semun *)unptr;
! 336: if ((error = sys___semctl(p, &bsa, retval)))
! 337: return error;
! 338: if ((error = copyin(dsp, (caddr_t)&bm, sizeof bm)))
! 339: return error;
! 340: bsd_to_linux_semid_ds(&bm, &lm);
! 341: if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
! 342: return error;
! 343: return copyout((caddr_t)&lm, ldsp, sizeof lm);
! 344: default:
! 345: return EINVAL;
! 346: }
! 347: SCARG(&bsa, cmd) = cmd;
! 348:
! 349: return sys___semctl(p, &bsa, retval);
! 350: }
! 351: #endif /* SYSVSEM */
! 352:
! 353: #ifdef SYSVMSG
! 354:
! 355: void
! 356: linux_to_bsd_msqid_ds(lmp, bmp)
! 357: struct linux_msqid_ds *lmp;
! 358: struct msqid_ds *bmp;
! 359: {
! 360:
! 361: linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
! 362: bmp->msg_first = lmp->l_msg_first;
! 363: bmp->msg_last = lmp->l_msg_last;
! 364: bmp->msg_cbytes = lmp->l_msg_cbytes;
! 365: bmp->msg_qnum = lmp->l_msg_qnum;
! 366: bmp->msg_qbytes = lmp->l_msg_qbytes;
! 367: bmp->msg_lspid = lmp->l_msg_lspid;
! 368: bmp->msg_lrpid = lmp->l_msg_lrpid;
! 369: bmp->msg_stime = lmp->l_msg_stime;
! 370: bmp->msg_rtime = lmp->l_msg_rtime;
! 371: bmp->msg_ctime = lmp->l_msg_ctime;
! 372: }
! 373:
! 374: void
! 375: bsd_to_linux_msqid_ds(bmp, lmp)
! 376: struct msqid_ds *bmp;
! 377: struct linux_msqid_ds *lmp;
! 378: {
! 379:
! 380: bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
! 381: lmp->l_msg_first = bmp->msg_first;
! 382: lmp->l_msg_last = bmp->msg_last;
! 383: lmp->l_msg_cbytes = bmp->msg_cbytes;
! 384: lmp->l_msg_qnum = bmp->msg_qnum;
! 385: lmp->l_msg_qbytes = bmp->msg_qbytes;
! 386: lmp->l_msg_lspid = bmp->msg_lspid;
! 387: lmp->l_msg_lrpid = bmp->msg_lrpid;
! 388: lmp->l_msg_stime = bmp->msg_stime;
! 389: lmp->l_msg_rtime = bmp->msg_rtime;
! 390: lmp->l_msg_ctime = bmp->msg_ctime;
! 391: }
! 392:
! 393: int
! 394: linux_msgsnd(p, v, retval)
! 395: struct proc *p;
! 396: void *v;
! 397: register_t *retval;
! 398: {
! 399: struct linux_sys_ipc_args /* {
! 400: syscallarg(int) what;
! 401: syscallarg(int) a1;
! 402: syscallarg(int) a2;
! 403: syscallarg(int) a3;
! 404: syscallarg(caddr_t) ptr;
! 405: } */ *uap = v;
! 406: struct sys_msgsnd_args bma;
! 407:
! 408: SCARG(&bma, msqid) = SCARG(uap, a1);
! 409: SCARG(&bma, msgp) = SCARG(uap, ptr);
! 410: SCARG(&bma, msgsz) = SCARG(uap, a2);
! 411: SCARG(&bma, msgflg) = SCARG(uap, a3);
! 412:
! 413: return sys_msgsnd(p, &bma, retval);
! 414: }
! 415:
! 416: int
! 417: linux_msgrcv(p, v, retval)
! 418: struct proc *p;
! 419: void *v;
! 420: register_t *retval;
! 421: {
! 422: struct linux_sys_ipc_args /* {
! 423: syscallarg(int) what;
! 424: syscallarg(int) a1;
! 425: syscallarg(int) a2;
! 426: syscallarg(int) a3;
! 427: syscallarg(caddr_t) ptr;
! 428: } */ *uap = v;
! 429: struct sys_msgrcv_args bma;
! 430: struct linux_msgrcv_msgarg kluge;
! 431: int error;
! 432:
! 433: if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
! 434: return error;
! 435:
! 436: SCARG(&bma, msqid) = SCARG(uap, a1);
! 437: SCARG(&bma, msgp) = kluge.msg;
! 438: SCARG(&bma, msgsz) = SCARG(uap, a2);
! 439: SCARG(&bma, msgtyp) = kluge.type;
! 440: SCARG(&bma, msgflg) = SCARG(uap, a3);
! 441:
! 442: return sys_msgrcv(p, &bma, retval);
! 443: }
! 444:
! 445: int
! 446: linux_msgget(p, v, retval)
! 447: struct proc *p;
! 448: void *v;
! 449: register_t *retval;
! 450: {
! 451: struct linux_sys_ipc_args /* {
! 452: syscallarg(int) what;
! 453: syscallarg(int) a1;
! 454: syscallarg(int) a2;
! 455: syscallarg(int) a3;
! 456: syscallarg(caddr_t) ptr;
! 457: } */ *uap = v;
! 458: struct sys_msgget_args bma;
! 459:
! 460: SCARG(&bma, key) = (key_t)SCARG(uap, a1);
! 461: SCARG(&bma, msgflg) = SCARG(uap, a2);
! 462:
! 463: return sys_msgget(p, &bma, retval);
! 464: }
! 465:
! 466: int
! 467: linux_msgctl(p, v, retval)
! 468: struct proc *p;
! 469: void *v;
! 470: register_t *retval;
! 471: {
! 472: struct linux_sys_ipc_args /* {
! 473: syscallarg(int) what;
! 474: syscallarg(int) a1;
! 475: syscallarg(int) a2;
! 476: syscallarg(int) a3;
! 477: syscallarg(caddr_t) ptr;
! 478: } */ *uap = v;
! 479: struct sys_msgctl_args bma;
! 480: caddr_t umsgptr, sg;
! 481: struct linux_msqid_ds lm;
! 482: struct msqid_ds bm;
! 483: int error;
! 484:
! 485: SCARG(&bma, msqid) = SCARG(uap, a1);
! 486: SCARG(&bma, cmd) = SCARG(uap, a2);
! 487: switch (SCARG(uap, a2)) {
! 488: case LINUX_IPC_RMID:
! 489: return sys_msgctl(p, &bma, retval);
! 490: case LINUX_IPC_SET:
! 491: if ((error = copyin(SCARG(uap, ptr), (caddr_t)&lm, sizeof lm)))
! 492: return error;
! 493: linux_to_bsd_msqid_ds(&lm, &bm);
! 494: sg = stackgap_init(p->p_emul);
! 495: umsgptr = stackgap_alloc(&sg, sizeof bm);
! 496: if ((error = copyout((caddr_t)&bm, umsgptr, sizeof bm)))
! 497: return error;
! 498: SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
! 499: return sys_msgctl(p, &bma, retval);
! 500: case LINUX_IPC_STAT:
! 501: sg = stackgap_init(p->p_emul);
! 502: umsgptr = stackgap_alloc(&sg, sizeof (struct msqid_ds));
! 503: SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
! 504: if ((error = sys_msgctl(p, &bma, retval)))
! 505: return error;
! 506: if ((error = copyin(umsgptr, (caddr_t)&bm, sizeof bm)))
! 507: return error;
! 508: bsd_to_linux_msqid_ds(&bm, &lm);
! 509: return copyout((caddr_t)&lm, SCARG(uap, ptr), sizeof lm);
! 510: }
! 511: return EINVAL;
! 512: }
! 513: #endif /* SYSVMSG */
! 514:
! 515: #ifdef SYSVSHM
! 516: /*
! 517: * shmat(2). Very straightforward, except that Linux passes a pointer
! 518: * in which the return value is to be passed. This is subsequently
! 519: * handled by libc, apparently.
! 520: */
! 521: int
! 522: linux_shmat(p, v, retval)
! 523: struct proc *p;
! 524: void *v;
! 525: register_t *retval;
! 526: {
! 527: struct linux_sys_ipc_args /* {
! 528: syscallarg(int) what;
! 529: syscallarg(int) a1;
! 530: syscallarg(int) a2;
! 531: syscallarg(int) a3;
! 532: syscallarg(caddr_t) ptr;
! 533: } */ *uap = v;
! 534: struct sys_shmat_args bsa;
! 535: int error;
! 536:
! 537: SCARG(&bsa, shmid) = SCARG(uap, a1);
! 538: SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
! 539: SCARG(&bsa, shmflg) = SCARG(uap, a2);
! 540:
! 541: if ((error = sys_shmat(p, &bsa, retval)))
! 542: return error;
! 543:
! 544: if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, a3),
! 545: sizeof retval[0])))
! 546: return error;
! 547:
! 548: retval[0] = 0;
! 549: return 0;
! 550: }
! 551:
! 552: /*
! 553: * shmdt(): this could have been mapped directly, if it wasn't for
! 554: * the extra indirection by the linux_ipc system call.
! 555: */
! 556: int
! 557: linux_shmdt(p, v, retval)
! 558: struct proc *p;
! 559: void *v;
! 560: register_t *retval;
! 561: {
! 562: struct linux_sys_ipc_args /* {
! 563: syscallarg(int) what;
! 564: syscallarg(int) a1;
! 565: syscallarg(int) a2;
! 566: syscallarg(int) a3;
! 567: syscallarg(caddr_t) ptr;
! 568: } */ *uap = v;
! 569: struct sys_shmdt_args bsa;
! 570:
! 571: SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
! 572:
! 573: return sys_shmdt(p, &bsa, retval);
! 574: }
! 575:
! 576: /*
! 577: * Same story as shmdt.
! 578: */
! 579: int
! 580: linux_shmget(p, v, retval)
! 581: struct proc *p;
! 582: void *v;
! 583: register_t *retval;
! 584: {
! 585: struct linux_sys_ipc_args /* {
! 586: syscallarg(int) what;
! 587: syscallarg(int) a1;
! 588: syscallarg(int) a2;
! 589: syscallarg(int) a3;
! 590: syscallarg(caddr_t) ptr;
! 591: } */ *uap = v;
! 592: struct sys_shmget_args bsa;
! 593:
! 594: SCARG(&bsa, key) = SCARG(uap, a1);
! 595: SCARG(&bsa, size) = SCARG(uap, a2);
! 596: SCARG(&bsa, shmflg) = SCARG(uap, a3);
! 597:
! 598: SCARG(&bsa, shmflg) |= _SHM_RMLINGER;
! 599:
! 600: return sys_shmget(p, &bsa, retval);
! 601: }
! 602:
! 603: /*
! 604: * Convert between Linux and OpenBSD shmid_ds structures.
! 605: * The order of the fields is once again the difference, and
! 606: * we also need a place to store the internal data pointer
! 607: * in, which is unfortunately stored in this structure.
! 608: *
! 609: * We abuse a Linux internal field for that.
! 610: */
! 611: void
! 612: linux_to_bsd_shmid_ds(lsp, bsp)
! 613: struct linux_shmid_ds *lsp;
! 614: struct shmid_ds *bsp;
! 615: {
! 616:
! 617: linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
! 618: bsp->shm_segsz = lsp->l_shm_segsz;
! 619: bsp->shm_lpid = lsp->l_shm_lpid;
! 620: bsp->shm_cpid = lsp->l_shm_cpid;
! 621: bsp->shm_nattch = lsp->l_shm_nattch;
! 622: bsp->shm_atime = lsp->l_shm_atime;
! 623: bsp->shm_dtime = lsp->l_shm_dtime;
! 624: bsp->shm_ctime = lsp->l_shm_ctime;
! 625: bsp->shm_internal = lsp->l_private2; /* XXX Oh well. */
! 626: }
! 627:
! 628: void
! 629: bsd_to_linux_shmid_ds(bsp, lsp)
! 630: struct shmid_ds *bsp;
! 631: struct linux_shmid_ds *lsp;
! 632: {
! 633:
! 634: bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
! 635: lsp->l_shm_segsz = bsp->shm_segsz;
! 636: lsp->l_shm_lpid = bsp->shm_lpid;
! 637: lsp->l_shm_cpid = bsp->shm_cpid;
! 638: lsp->l_shm_nattch = bsp->shm_nattch;
! 639: lsp->l_shm_atime = bsp->shm_atime;
! 640: lsp->l_shm_dtime = bsp->shm_dtime;
! 641: lsp->l_shm_ctime = bsp->shm_ctime;
! 642: lsp->l_private2 = bsp->shm_internal; /* XXX */
! 643: }
! 644:
! 645: /*
! 646: * shmctl. Not implemented (for now): IPC_INFO, SHM_INFO, SHM_STAT
! 647: * SHM_LOCK and SHM_UNLOCK are passed on, but currently not implemented
! 648: * by OpenBSD itself.
! 649: *
! 650: * The usual structure conversion and massaging is done.
! 651: */
! 652: int
! 653: linux_shmctl(p, v, retval)
! 654: struct proc *p;
! 655: void *v;
! 656: register_t *retval;
! 657: {
! 658: struct linux_sys_ipc_args /* {
! 659: syscallarg(int) what;
! 660: syscallarg(int) a1;
! 661: syscallarg(int) a2;
! 662: syscallarg(int) a3;
! 663: syscallarg(caddr_t) ptr;
! 664: } */ *uap = v;
! 665: int error;
! 666: caddr_t sg;
! 667: struct sys_shmctl_args bsa;
! 668: struct shmid_ds *bsp, bs;
! 669: struct linux_shmid_ds lseg;
! 670:
! 671: switch (SCARG(uap, a2)) {
! 672: case LINUX_IPC_STAT:
! 673: sg = stackgap_init(p->p_emul);
! 674: bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
! 675: SCARG(&bsa, shmid) = SCARG(uap, a1);
! 676: SCARG(&bsa, cmd) = IPC_STAT;
! 677: SCARG(&bsa, buf) = bsp;
! 678: if ((error = sys_shmctl(p, &bsa, retval)))
! 679: return error;
! 680: if ((error = copyin((caddr_t) bsp, (caddr_t) &bs, sizeof bs)))
! 681: return error;
! 682: bsd_to_linux_shmid_ds(&bs, &lseg);
! 683: return copyout((caddr_t) &lseg, SCARG(uap, ptr), sizeof lseg);
! 684: case LINUX_IPC_SET:
! 685: if ((error = copyin(SCARG(uap, ptr), (caddr_t) &lseg,
! 686: sizeof lseg)))
! 687: return error;
! 688: linux_to_bsd_shmid_ds(&lseg, &bs);
! 689: sg = stackgap_init(p->p_emul);
! 690: bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
! 691: if ((error = copyout((caddr_t) &bs, (caddr_t) bsp, sizeof bs)))
! 692: return error;
! 693: SCARG(&bsa, shmid) = SCARG(uap, a1);
! 694: SCARG(&bsa, cmd) = IPC_SET;
! 695: SCARG(&bsa, buf) = bsp;
! 696: return sys_shmctl(p, &bsa, retval);
! 697: case LINUX_IPC_RMID:
! 698: case LINUX_SHM_LOCK:
! 699: case LINUX_SHM_UNLOCK:
! 700: SCARG(&bsa, shmid) = SCARG(uap, a1);
! 701: switch (SCARG(uap, a2)) {
! 702: case LINUX_IPC_RMID:
! 703: SCARG(&bsa, cmd) = IPC_RMID;
! 704: break;
! 705: case LINUX_SHM_LOCK:
! 706: SCARG(&bsa, cmd) = SHM_LOCK;
! 707: break;
! 708: case LINUX_SHM_UNLOCK:
! 709: SCARG(&bsa, cmd) = SHM_UNLOCK;
! 710: break;
! 711: }
! 712: SCARG(&bsa, buf) = NULL;
! 713: return sys_shmctl(p, &bsa, retval);
! 714: case LINUX_IPC_INFO:
! 715: case LINUX_SHM_STAT:
! 716: case LINUX_SHM_INFO:
! 717: default:
! 718: return EINVAL;
! 719: }
! 720: }
! 721: #endif /* SYSVSHM */
CVSweb