linux_ipc.c revision 16322
1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: linux_ipc.c,v 1.7 1996/03/02 19:37:56 peter Exp $ 29 */ 30 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/sysproto.h> 35#include <sys/proc.h> 36#include <sys/shm.h> 37 38#include <i386/linux/linux.h> 39#include <i386/linux/linux_proto.h> 40#include <i386/linux/linux_util.h> 41 42static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *)); 43static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *)); 44static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *)); 45static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *)); 46static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *)); 47static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *)); 48static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *)); 49static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *)); 50static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *)); 51static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *)); 52 53struct linux_ipc_perm { 54 linux_key_t key; 55 unsigned short uid; 56 unsigned short gid; 57 unsigned short cuid; 58 unsigned short cgid; 59 unsigned short mode; 60 unsigned short seq; 61}; 62 63static void 64linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) 65{ 66 bpp->key = lpp->key; 67 bpp->uid = lpp->uid; 68 bpp->gid = lpp->gid; 69 bpp->cuid = lpp->cuid; 70 bpp->cgid = lpp->cgid; 71 bpp->mode = lpp->mode; 72 bpp->seq = lpp->seq; 73} 74 75 76static void 77bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) 78{ 79 lpp->key = bpp->key; 80 lpp->uid = bpp->uid; 81 lpp->gid = bpp->gid; 82 lpp->cuid = bpp->cuid; 83 lpp->cgid = bpp->cgid; 84 lpp->mode = bpp->mode; 85 lpp->seq = bpp->seq; 86} 87 88struct linux_shmid_ds { 89 struct linux_ipc_perm shm_perm; 90 int shm_segsz; 91 linux_time_t shm_atime; 92 linux_time_t shm_dtime; 93 linux_time_t shm_ctime; 94 ushort shm_cpid; 95 ushort shm_lpid; 96 short shm_nattch; 97 ushort private1; 98 void *private2; 99 void *private3; 100}; 101 102static void 103linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) 104{ 105 linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 106 bsp->shm_segsz = lsp->shm_segsz; 107 bsp->shm_lpid = lsp->shm_lpid; 108 bsp->shm_cpid = lsp->shm_cpid; 109 bsp->shm_nattch = lsp->shm_nattch; 110 bsp->shm_atime = lsp->shm_atime; 111 bsp->shm_dtime = lsp->shm_dtime; 112 bsp->shm_ctime = lsp->shm_ctime; 113 bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ 114} 115 116static void 117bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) 118{ 119 bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 120 lsp->shm_segsz = bsp->shm_segsz; 121 lsp->shm_lpid = bsp->shm_lpid; 122 lsp->shm_cpid = bsp->shm_cpid; 123 lsp->shm_nattch = bsp->shm_nattch; 124 lsp->shm_atime = bsp->shm_atime; 125 lsp->shm_dtime = bsp->shm_dtime; 126 lsp->shm_ctime = bsp->shm_ctime; 127 lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ 128} 129 130static int 131linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval) 132{ 133 return ENOSYS; 134} 135 136static int 137linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval) 138{ 139 return ENOSYS; 140} 141 142static int 143linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval) 144{ 145 return ENOSYS; 146} 147 148static int 149linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval) 150{ 151 struct msgsnd_args /* { 152 int msqid; 153 void *msgp; 154 size_t msgsz; 155 int msgflg; 156 } */ bsd_args; 157 158 bsd_args.msqid = args->arg1; 159 bsd_args.msgp = args->ptr; 160 bsd_args.msgsz = args->arg2; 161 bsd_args.msgflg = args->arg3; 162 return msgsnd(p, &bsd_args, retval); 163} 164 165static int 166linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) 167{ 168 struct msgrcv_args /* { 169 int msqid; 170 void *msgp; 171 size_t msgsz; 172 long msgtyp; 173 int msgflg; 174 } */ bsd_args; 175 176 bsd_args.msqid = args->arg1; 177 bsd_args.msgp = args->ptr; 178 bsd_args.msgsz = args->arg2; 179 bsd_args.msgtyp = 0; 180 bsd_args.msgflg = args->arg3; 181 return msgrcv(p, &bsd_args, retval); 182} 183 184static int 185linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) 186{ 187 struct msgget_args /* { 188 key_t key; 189 int msgflg; 190 } */ bsd_args; 191 192 bsd_args.key = args->arg1; 193 bsd_args.msgflg = args->arg2; 194 return msgget(p, &bsd_args, retval); 195} 196 197static int 198linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) 199{ 200 struct msgctl_args /* { 201 int msqid; 202 int cmd; 203 struct msqid_ds *buf; 204 } */ bsd_args; 205 206 bsd_args.msqid = args->arg1; 207 bsd_args.cmd = args->arg2; 208 bsd_args.buf = (struct msqid_ds *)args->ptr; 209 return msgctl(p, &bsd_args, retval); 210} 211 212static int 213linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) 214{ 215 struct shmat_args /* { 216 int shmid; 217 void *shmaddr; 218 int shmflg; 219 } */ bsd_args; 220 int error; 221 222 bsd_args.shmid = args->arg1; 223 bsd_args.shmaddr = args->ptr; 224 bsd_args.shmflg = args->arg2; 225 if ((error = shmat(p, &bsd_args, retval))) 226 return error; 227 if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int)))) 228 return error; 229 retval[0] = 0; 230 return 0; 231} 232 233static int 234linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) 235{ 236 struct shmdt_args /* { 237 void *shmaddr; 238 } */ bsd_args; 239 240 bsd_args.shmaddr = args->ptr; 241 return shmdt(p, &bsd_args, retval); 242} 243 244static int 245linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) 246{ 247 struct shmget_args /* { 248 key_t key; 249 int size; 250 int shmflg; 251 } */ bsd_args; 252 253 bsd_args.key = args->arg1; 254 bsd_args.size = args->arg2; 255 bsd_args.shmflg = args->arg3; 256 return shmget(p, &bsd_args, retval); 257} 258 259static int 260linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) 261{ 262 struct shmid_ds bsd_shmid; 263 struct linux_shmid_ds linux_shmid; 264 struct shmctl_args /* { 265 int shmid; 266 int cmd; 267 struct shmid_ds *buf; 268 } */ bsd_args; 269 int error; 270 caddr_t sg = stackgap_init(); 271 272 switch (args->arg2) { 273 case LINUX_IPC_STAT: 274 bsd_args.shmid = args->arg1; 275 bsd_args.cmd = IPC_STAT; 276 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 277 if ((error = shmctl(p, &bsd_args, retval))) 278 return error; 279 if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 280 sizeof(struct shmid_ds)))) 281 return error; 282 bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 283 return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); 284 285 case LINUX_IPC_SET: 286 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 287 sizeof(linux_shmid)))) 288 return error; 289 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 290 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 291 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 292 sizeof(struct shmid_ds)))) 293 return error; 294 bsd_args.shmid = args->arg1; 295 bsd_args.cmd = IPC_SET; 296 return shmctl(p, &bsd_args, retval); 297 298 case LINUX_IPC_RMID: 299 bsd_args.shmid = args->arg1; 300 bsd_args.cmd = IPC_RMID; 301 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 302 sizeof(linux_shmid)))) 303 return error; 304 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 305 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); 306 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 307 sizeof(struct shmid_ds)))) 308 return error; 309 return shmctl(p, &bsd_args, retval); 310 311 case LINUX_IPC_INFO: 312 case LINUX_SHM_STAT: 313 case LINUX_SHM_INFO: 314 case LINUX_SHM_LOCK: 315 case LINUX_SHM_UNLOCK: 316 default: 317 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 318 return EINVAL; 319 } 320} 321 322int 323linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval) 324{ 325 switch (args->what) { 326 case LINUX_SEMOP: 327 return linux_semop(p, args, retval); 328 case LINUX_SEMGET: 329 return linux_semget(p, args, retval); 330 case LINUX_SEMCTL: 331 return linux_semctl(p, args, retval); 332 case LINUX_MSGSND: 333 return linux_msgsnd(p, args, retval); 334 case LINUX_MSGRCV: 335 return linux_msgrcv(p, args, retval); 336 case LINUX_MSGGET: 337 return linux_msgget(p, args, retval); 338 case LINUX_MSGCTL: 339 return linux_msgctl(p, args, retval); 340 case LINUX_SHMAT: 341 return linux_shmat(p, args, retval); 342 case LINUX_SHMDT: 343 return linux_shmdt(p, args, retval); 344 case LINUX_SHMGET: 345 return linux_shmget(p, args, retval); 346 case LINUX_SHMCTL: 347 return linux_shmctl(p, args, retval); 348 default: 349 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 350 return ENOSYS; 351 } 352} 353