[BACK]Return to linux_ipc.c CVS log [TXT][DIR] Up to [local] / sys / compat / linux

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