linux_ipc.c revision 64906
110015Speter/*- 212496Speter * Copyright (c) 1994-1995 S�ren Schmidt 310015Speter * All rights reserved. 410015Speter * 510015Speter * Redistribution and use in source and binary forms, with or without 610015Speter * modification, are permitted provided that the following conditions 710015Speter * are met: 810015Speter * 1. Redistributions of source code must retain the above copyright 910015Speter * notice, this list of conditions and the following disclaimer 1010015Speter * in this position and unchanged. 1110015Speter * 2. Redistributions in binary form must reproduce the above copyright 1210015Speter * notice, this list of conditions and the following disclaimer in the 1310015Speter * documentation and/or other materials provided with the distribution. 1410015Speter * 3. The name of the author may not be used to endorse or promote products 1510015Speter * derived from this software withough specific prior written permission 1610015Speter * 1710015Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1810015Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1910015Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2010015Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2110015Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2210015Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310015Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410015Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510015Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2610015Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710015Speter * 2810015Speter * $FreeBSD: head/sys/compat/linux/linux_ipc.c 64906 2000-08-22 01:31:23Z marcel $ 2910015Speter */ 3010015Speter 3110015Speter#include <sys/param.h> 3210015Speter#include <sys/systm.h> 3329677Sgibbs#include <sys/sysproto.h> 3410015Speter#include <sys/proc.h> 3510015Speter#include <sys/sem.h> 3610015Speter#include <sys/shm.h> 3716322Sgpalmer 3816322Sgpalmer#include <machine/../linux/linux.h> 3916322Sgpalmer#include <machine/../linux/linux_proto.h> 4010015Speter#include <compat/linux/linux_ipc.h> 4110015Speter#include <compat/linux/linux_util.h> 4210015Speter 4310015Speterstruct linux_ipc_perm { 4424207Sbde linux_key_t key; 4524207Sbde unsigned short uid; 4624207Sbde unsigned short gid; 4710015Speter unsigned short cuid; 4810015Speter unsigned short cgid; 4910015Speter unsigned short mode; 5024131Sbde unsigned short seq; 5110015Speter}; 5210015Speter 5310015Speterstatic void 5415683Speterlinux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) 5512675Sjulian{ 5612675Sjulian bpp->key = lpp->key; 5712675Sjulian bpp->uid = lpp->uid; 5810015Speter bpp->gid = lpp->gid; 5910015Speter bpp->cuid = lpp->cuid; 6010015Speter bpp->cgid = lpp->cgid; 6112659Sbde bpp->mode = lpp->mode; 6212662Sdg bpp->seq = lpp->seq; 6312659Sbde} 6410015Speter 6510015Speter 6610015Speterstatic void 6710015Speterbsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) 6810015Speter{ 6910015Speter lpp->key = bpp->key; 7013353Speter lpp->uid = bpp->uid; 7110015Speter lpp->gid = bpp->gid; 7210015Speter lpp->cuid = bpp->cuid; 7310015Speter lpp->cgid = bpp->cgid; 7410015Speter lpp->mode = bpp->mode; 7510015Speter lpp->seq = bpp->seq; 7612496Speter} 7710015Speter 7810015Speterstruct linux_semid_ds { 7910015Speter struct linux_ipc_perm sem_perm; 8010015Speter linux_time_t sem_otime; 8110015Speter linux_time_t sem_ctime; 8217547Speter void *sem_base; 8317547Speter void *sem_pending; 8417547Speter void *sem_pending_last; 8510047Speter void *undo; 8612496Speter ushort sem_nsems; 8715639Speter}; 8815639Speter 8910015Speterstruct linux_shmid_ds { 9010015Speter struct linux_ipc_perm shm_perm; 9110015Speter int shm_segsz; 9210015Speter linux_time_t shm_atime; 9310015Speter linux_time_t shm_dtime; 9410015Speter linux_time_t shm_ctime; 9510015Speter ushort shm_cpid; 9610015Speter ushort shm_lpid; 9725047Sbde short shm_nattch; 9810015Speter ushort private1; 9910015Speter void *private2; 10010015Speter void *private3; 10110015Speter}; 10210015Speter 10312724Sphkstatic void 10410015Speterlinux_to_bsd_semid_ds(struct linux_semid_ds *lsp, struct semid_ds *bsp) 10512724Sphk{ 10612724Sphk linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); 10710708Speter bsp->sem_otime = lsp->sem_otime; 10810708Speter bsp->sem_ctime = lsp->sem_ctime; 10912675Sjulian bsp->sem_nsems = lsp->sem_nsems; 11012675Sjulian bsp->sem_base = lsp->sem_base; 11112675Sjulian} 11212675Sjulian 11312675Sjulianstatic void 11412675Sjulianbsd_to_linux_semid_ds(struct semid_ds *bsp, struct linux_semid_ds *lsp) 11512675Sjulian{ 11612675Sjulian bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); 11712675Sjulian lsp->sem_otime = bsp->sem_otime; 11812675Sjulian lsp->sem_ctime = bsp->sem_ctime; 11912731Sbde lsp->sem_nsems = bsp->sem_nsems; 12012675Sjulian lsp->sem_base = bsp->sem_base; 12112675Sjulian} 12212678Sphk 12312675Sjulianstatic void 12412743Sbdelinux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) 12529368Speter{ 12612675Sjulian linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 12712675Sjulian bsp->shm_segsz = lsp->shm_segsz; 12812174Speter bsp->shm_lpid = lsp->shm_lpid; 12913353Speter bsp->shm_cpid = lsp->shm_cpid; 13013353Speter bsp->shm_nattch = lsp->shm_nattch; 13113353Speter bsp->shm_atime = lsp->shm_atime; 13210708Speter bsp->shm_dtime = lsp->shm_dtime; 13313353Speter bsp->shm_ctime = lsp->shm_ctime; 13410708Speter bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ 13513353Speter} 13610708Speter 13710708Speterstatic void 13810708Speterbsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) 13910708Speter{ 14010962Speter bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 14110962Speter lsp->shm_segsz = bsp->shm_segsz; 14210962Speter lsp->shm_lpid = bsp->shm_lpid; 14310015Speter lsp->shm_cpid = bsp->shm_cpid; 14410962Speter lsp->shm_nattch = bsp->shm_nattch; 14510962Speter lsp->shm_atime = bsp->shm_atime; 14612174Speter lsp->shm_dtime = bsp->shm_dtime; 14710015Speter lsp->shm_ctime = bsp->shm_ctime; 14810015Speter lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ 14910015Speter} 15010044Speter 15110044Speterint 15210044Speterlinux_semop(struct proc *p, struct linux_ipc_args *args) 15310044Speter{ 15410044Speter struct semop_args /* { 15510044Speter int semid; 15610044Speter struct sembuf *sops; 15710044Speter int nsops; 15810044Speter } */ bsd_args; 15910044Speter 16010044Speter bsd_args.semid = args->arg1; 16110044Speter bsd_args.sops = (struct sembuf *)args->ptr; 16212675Sjulian bsd_args.nsops = args->arg2; 16312675Sjulian return semop(p, &bsd_args); 16412675Sjulian} 16512826Speter 16612675Sjulianint 16712675Sjulianlinux_semget(struct proc *p, struct linux_ipc_args *args) 16812675Sjulian{ 16913165Speter struct semget_args /* { 17012675Sjulian key_t key; 17110044Speter int nsems; 17212724Sphk int semflg; 17310044Speter } */ bsd_args; 17412174Speter 17510015Speter bsd_args.key = args->arg1; 17610015Speter bsd_args.nsems = args->arg2; 17710015Speter bsd_args.semflg = args->arg3; 17810015Speter return semget(p, &bsd_args); 17910015Speter} 18010015Speter 18110015Speterint 18210015Speterlinux_semctl(struct proc *p, struct linux_ipc_args *args) 18310015Speter{ 18410015Speter struct linux_semid_ds linux_semid; 18510015Speter struct semid_ds bsd_semid; 18610015Speter struct __semctl_args /* { 18710015Speter int semid; 18810015Speter int semnum; 18910015Speter int cmd; 19010015Speter union semun *arg; 19110015Speter } */ bsd_args; 19210015Speter int error; 19310015Speter caddr_t sg, unptr, dsp, ldsp; 19410015Speter 19510015Speter sg = stackgap_init(); 19610015Speter bsd_args.semid = args->arg1; 19710015Speter bsd_args.semnum = args->arg2; 19810015Speter bsd_args.cmd = args->arg3; 19910015Speter bsd_args.arg = (union semun *)args->ptr; 20010015Speter 20110015Speter switch (args->arg3) { 20210015Speter case LINUX_IPC_RMID: 20310015Speter bsd_args.cmd = IPC_RMID; 20410015Speter break; 20510015Speter case LINUX_GETNCNT: 20610015Speter bsd_args.cmd = GETNCNT; 20710015Speter break; 20810015Speter case LINUX_GETPID: 20910015Speter bsd_args.cmd = GETPID; 21010015Speter break; 21110015Speter case LINUX_GETVAL: 21210015Speter bsd_args.cmd = GETVAL; 21310015Speter break; 21410015Speter case LINUX_GETZCNT: 21510015Speter bsd_args.cmd = GETZCNT; 21610015Speter break; 21710015Speter case LINUX_SETVAL: 21810047Speter bsd_args.cmd = SETVAL; 21910047Speter break; 22010047Speter case LINUX_IPC_SET: 22110047Speter bsd_args.cmd = IPC_SET; 22210047Speter error = copyin(args->ptr, &ldsp, sizeof(ldsp)); 22310047Speter if (error) 22410047Speter return error; 22510047Speter error = copyin(ldsp, (caddr_t)&linux_semid, sizeof(linux_semid)); 22610047Speter if (error) 22710047Speter return error; 22810015Speter linux_to_bsd_semid_ds(&linux_semid, &bsd_semid); 22915683Speter unptr = stackgap_alloc(&sg, sizeof(union semun)); 23017547Speter dsp = stackgap_alloc(&sg, sizeof(struct semid_ds)); 23115639Speter error = copyout((caddr_t)&bsd_semid, dsp, sizeof(bsd_semid)); 23216403Speter if (error) 23317547Speter return error; 23415639Speter error = copyout((caddr_t)&dsp, unptr, sizeof(dsp)); 23510015Speter if (error) 23610015Speter return error; 23710015Speter bsd_args.arg = (union semun *)unptr; 23810015Speter return __semctl(p, &bsd_args); 23910015Speter case LINUX_IPC_STAT: 24010015Speter bsd_args.cmd = IPC_STAT; 24110015Speter unptr = stackgap_alloc(&sg, sizeof(union semun *)); 24210015Speter dsp = stackgap_alloc(&sg, sizeof(struct semid_ds)); 24310015Speter error = copyout((caddr_t)&dsp, unptr, sizeof(dsp)); 24410015Speter if (error) 24510015Speter return error; 24610015Speter bsd_args.arg = (union semun *)unptr; 24710015Speter error = __semctl(p, &bsd_args); 24810015Speter if (error) 24910015Speter return error; 25010015Speter error = copyin(dsp, (caddr_t)&bsd_semid, sizeof(bsd_semid)); 25110015Speter if (error) 25212724Sphk return error; 25310015Speter bsd_to_linux_semid_ds(&bsd_semid, &linux_semid); 25410015Speter error = copyin(args->ptr, &ldsp, sizeof(ldsp)); 25510015Speter if (error) 25610015Speter return error; 25710015Speter return copyout((caddr_t)&linux_semid, ldsp, sizeof(linux_semid)); 25810015Speter case LINUX_GETALL: 25910015Speter /* FALLTHROUGH */ 26010015Speter case LINUX_SETALL: 26110015Speter /* FALLTHROUGH */ 26210015Speter default: 26317547Speter uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 26417547Speter return EINVAL; 26517547Speter } 26617547Speter return __semctl(p, &bsd_args); 26715683Speter} 26810015Speter 26910015Speterint 27010015Speterlinux_msgsnd(struct proc *p, struct linux_ipc_args *args) 27112496Speter{ 27212496Speter struct msgsnd_args /* { 27310015Speter int msqid; 27410015Speter void *msgp; 27510015Speter size_t msgsz; 27610015Speter int msgflg; 27710015Speter } */ bsd_args; 27810015Speter 27910015Speter bsd_args.msqid = args->arg1; 28012174Speter bsd_args.msgp = args->ptr; 28112174Speter bsd_args.msgsz = args->arg2; 28210015Speter bsd_args.msgflg = args->arg3; 28310015Speter return msgsnd(p, &bsd_args); 28410015Speter} 28510015Speter 28610015Speterint 28710015Speterlinux_msgrcv(struct proc *p, struct linux_ipc_args *args) 28810015Speter{ 28910015Speter struct msgrcv_args /* { 29010015Speter int msqid; 29110015Speter void *msgp; 29210015Speter size_t msgsz; 29310015Speter long msgtyp; 29410015Speter int msgflg; 29510015Speter } */ bsd_args; 29610015Speter 29710015Speter bsd_args.msqid = args->arg1; 29810015Speter bsd_args.msgp = args->ptr; 29910015Speter bsd_args.msgsz = args->arg2; 30010015Speter bsd_args.msgtyp = 0; 30110015Speter bsd_args.msgflg = args->arg3; 30210015Speter return msgrcv(p, &bsd_args); 30310015Speter} 30410015Speter 30510015Speterint 30610015Speterlinux_msgget(struct proc *p, struct linux_ipc_args *args) 30710015Speter{ 30810015Speter struct msgget_args /* { 30910015Speter key_t key; 31010015Speter int msgflg; 31110015Speter } */ bsd_args; 31210015Speter 31310015Speter bsd_args.key = args->arg1; 31410015Speter bsd_args.msgflg = args->arg2; 31510015Speter return msgget(p, &bsd_args); 31610015Speter} 31710015Speter 31810015Speterint 31910015Speterlinux_msgctl(struct proc *p, struct linux_ipc_args *args) 32010015Speter{ 32110015Speter struct msgctl_args /* { 32210015Speter int msqid; 32312496Speter int cmd; 32410015Speter struct msqid_ds *buf; 32510015Speter } */ bsd_args; 32610015Speter int error; 32710015Speter 32810015Speter bsd_args.msqid = args->arg1; 32910015Speter bsd_args.cmd = args->arg2; 33010015Speter bsd_args.buf = (struct msqid_ds *)args->ptr; 33110015Speter error = msgctl(p, &bsd_args); 33210015Speter return ((args->arg2 == LINUX_IPC_RMID && error == EINVAL) ? 0 : error); 33310015Speter} 33410015Speter 33510015Speterint 33610015Speterlinux_shmat(struct proc *p, struct linux_ipc_args *args) 33710015Speter{ 33810015Speter struct shmat_args /* { 33910015Speter int shmid; 34010015Speter void *shmaddr; 34110015Speter int shmflg; 34210015Speter } */ bsd_args; 34310015Speter int error; 34410015Speter 34510015Speter bsd_args.shmid = args->arg1; 34610015Speter bsd_args.shmaddr = args->ptr; 34710015Speter bsd_args.shmflg = args->arg2; 34810015Speter if ((error = shmat(p, &bsd_args))) 34910015Speter return error; 35010015Speter if ((error = copyout(p->p_retval, (caddr_t)args->arg3, sizeof(int)))) 35110015Speter return error; 35210015Speter p->p_retval[0] = 0; 35310015Speter return 0; 35410015Speter} 35510015Speter 35610015Speterint 35710015Speterlinux_shmdt(struct proc *p, struct linux_ipc_args *args) 35810015Speter{ 35910015Speter struct shmdt_args /* { 36010015Speter void *shmaddr; 36110015Speter } */ bsd_args; 36210015Speter 36310015Speter bsd_args.shmaddr = args->ptr; 36410015Speter return shmdt(p, &bsd_args); 36510015Speter} 36610015Speter 36710015Speterint 36810015Speterlinux_shmget(struct proc *p, struct linux_ipc_args *args) 36910015Speter{ 37010015Speter struct shmget_args /* { 37110015Speter key_t key; 37210015Speter int size; 37310015Speter int shmflg; 37410015Speter } */ bsd_args; 37510015Speter 37610015Speter bsd_args.key = args->arg1; 37710015Speter bsd_args.size = args->arg2; 37810015Speter bsd_args.shmflg = args->arg3; 37910015Speter return shmget(p, &bsd_args); 38010015Speter} 38110015Speter 38210015Speterint 38310015Speterlinux_shmctl(struct proc *p, struct linux_ipc_args *args) 38410015Speter{ 38510015Speter struct shmid_ds bsd_shmid; 38610015Speter struct linux_shmid_ds linux_shmid; 38710015Speter struct shmctl_args /* { 38810015Speter int shmid; 38912496Speter int cmd; 39012496Speter struct shmid_ds *buf; 39110015Speter } */ bsd_args; 39218515Speter int error; 39310015Speter caddr_t sg = stackgap_init(); 39410015Speter 39518515Speter switch (args->arg2) { 39610015Speter case LINUX_IPC_STAT: 39710015Speter bsd_args.shmid = args->arg1; 39810015Speter bsd_args.cmd = IPC_STAT; 39912174Speter bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 40010015Speter if ((error = shmctl(p, &bsd_args))) 40110015Speter return error; 40210015Speter if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid, 40310015Speter sizeof(struct shmid_ds)))) 40410015Speter return error; 40510015Speter bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 40618515Speter return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); 40710015Speter 40810015Speter case LINUX_IPC_SET: 40918515Speter if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 41010015Speter sizeof(linux_shmid)))) 41110015Speter return error; 41210015Speter linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 41312174Speter bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 41410015Speter if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 41510015Speter sizeof(struct shmid_ds)))) 41610015Speter return error; 41710015Speter bsd_args.shmid = args->arg1; 41810015Speter bsd_args.cmd = IPC_SET; 41910015Speter return shmctl(p, &bsd_args); 42010015Speter 42110015Speter case LINUX_IPC_RMID: 42210015Speter bsd_args.shmid = args->arg1; 42310015Speter bsd_args.cmd = IPC_RMID; 42410015Speter if (NULL == args->ptr) 42510015Speter bsd_args.buf = NULL; 42610015Speter else { 42710015Speter if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 42810015Speter sizeof(linux_shmid)))) 42910015Speter return error; 43010015Speter linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 43110015Speter bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 43210015Speter if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 43310015Speter sizeof(struct shmid_ds)))) 43410015Speter return error; 43510015Speter } 43610015Speter return shmctl(p, &bsd_args); 43710015Speter 43810015Speter case LINUX_IPC_INFO: 43910015Speter case LINUX_SHM_STAT: 44010015Speter case LINUX_SHM_INFO: 44110015Speter case LINUX_SHM_LOCK: 44210015Speter case LINUX_SHM_UNLOCK: 44310015Speter default: 44410015Speter uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 44510015Speter return EINVAL; 44610015Speter } 44710015Speter} 44810015Speter