linux_ipc.c revision 13264
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.4 1995/12/29 22:12:14 sos Exp $ 29 */ 30 31#include "opt_sysvipc.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/sysproto.h> 36#include <sys/proc.h> 37#include <sys/shm.h> 38 39#include <i386/linux/linux.h> 40#include <i386/linux/sysproto.h> 41 42struct linux_ipc_perm { 43 linux_key_t key; 44 unsigned short uid; 45 unsigned short gid; 46 unsigned short cuid; 47 unsigned short cgid; 48 unsigned short mode; 49 unsigned short seq; 50}; 51 52static void 53linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) 54{ 55 bpp->key = lpp->key; 56 bpp->uid = lpp->uid; 57 bpp->gid = lpp->gid; 58 bpp->cuid = lpp->cuid; 59 bpp->cgid = lpp->cgid; 60 bpp->mode = lpp->mode; 61 bpp->seq = lpp->seq; 62} 63 64 65static void 66bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) 67{ 68 lpp->key = bpp->key; 69 lpp->uid = bpp->uid; 70 lpp->gid = bpp->gid; 71 lpp->cuid = bpp->cuid; 72 lpp->cgid = bpp->cgid; 73 lpp->mode = bpp->mode; 74 lpp->seq = bpp->seq; 75} 76 77struct linux_shmid_ds { 78 struct linux_ipc_perm shm_perm; 79 int shm_segsz; 80 linux_time_t shm_atime; 81 linux_time_t shm_dtime; 82 linux_time_t shm_ctime; 83 ushort shm_cpid; 84 ushort shm_lpid; 85 short shm_nattch; 86 ushort private1; 87 void *private2; 88 void *private3; 89}; 90 91static void 92linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) 93{ 94 linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); 95 bsp->shm_segsz = lsp->shm_segsz; 96 bsp->shm_lpid = lsp->shm_lpid; 97 bsp->shm_cpid = lsp->shm_cpid; 98 bsp->shm_nattch = lsp->shm_nattch; 99 bsp->shm_atime = lsp->shm_atime; 100 bsp->shm_dtime = lsp->shm_dtime; 101 bsp->shm_ctime = lsp->shm_ctime; 102 bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */ 103} 104 105static void 106bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) 107{ 108 bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); 109 lsp->shm_segsz = bsp->shm_segsz; 110 lsp->shm_lpid = bsp->shm_lpid; 111 lsp->shm_cpid = bsp->shm_cpid; 112 lsp->shm_nattch = bsp->shm_nattch; 113 lsp->shm_atime = bsp->shm_atime; 114 lsp->shm_dtime = bsp->shm_dtime; 115 lsp->shm_ctime = bsp->shm_ctime; 116 lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */ 117} 118 119struct linux_ipc_args { 120 int what; 121 int arg1; 122 int arg2; 123 int arg3; 124 caddr_t ptr; 125}; 126 127int 128linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval) 129{ 130 return ENOSYS; 131} 132 133int 134linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval) 135{ 136 return ENOSYS; 137} 138 139int 140linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval) 141{ 142 return ENOSYS; 143} 144 145int 146linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval) 147{ 148 struct msgsnd_args /* { 149 int msqid; 150 void *msgp; 151 size_t msgsz; 152 int msgflg; 153 } */ bsd_args; 154 155 bsd_args.msqid = args->arg1; 156 bsd_args.msgp = args->ptr; 157 bsd_args.msgsz = args->arg2; 158 bsd_args.msgflg = args->arg3; 159 return msgsnd(p, &bsd_args, retval); 160} 161 162int 163linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval) 164{ 165 struct msgrcv_args /* { 166 int msqid; 167 void *msgp; 168 size_t msgsz; 169 long msgtyp; 170 int msgflg; 171 } */ bsd_args; 172 173 bsd_args.msqid = args->arg1; 174 bsd_args.msgp = args->ptr; 175 bsd_args.msgsz = args->arg2; 176 bsd_args.msgtyp = 0; 177 bsd_args.msgflg = args->arg3; 178 return msgrcv(p, &bsd_args, retval); 179} 180 181int 182linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval) 183{ 184 struct msgget_args /* { 185 key_t key; 186 int msgflg; 187 } */ bsd_args; 188 189 bsd_args.key = args->arg1; 190 bsd_args.msgflg = args->arg2; 191 return msgget(p, &bsd_args, retval); 192} 193 194int 195linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval) 196{ 197 struct msgctl_args /* { 198 int msqid; 199 int cmd; 200 struct msqid_ds *buf; 201 } */ bsd_args; 202 203 bsd_args.msqid = args->arg1; 204 bsd_args.cmd = args->arg2; 205 bsd_args.buf = (struct msqid_ds *)args->ptr; 206 return msgctl(p, &bsd_args, retval); 207} 208 209int 210linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval) 211{ 212 struct shmat_args /* { 213 int shmid; 214 void *shmaddr; 215 int shmflg; 216 } */ bsd_args; 217 int error; 218 219 bsd_args.shmid = args->arg1; 220 bsd_args.shmaddr = args->ptr; 221 bsd_args.shmflg = args->arg2; 222 if ((error = shmat(p, &bsd_args, retval))) 223 return error; 224 if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int)))) 225 return error; 226 retval[0] = 0; 227 return 0; 228} 229 230int 231linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval) 232{ 233 struct shmdt_args /* { 234 void *shmaddr; 235 } */ bsd_args; 236 237 bsd_args.shmaddr = args->ptr; 238 return shmdt(p, &bsd_args, retval); 239} 240 241int 242linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval) 243{ 244 struct shmget_args /* { 245 key_t key; 246 int size; 247 int shmflg; 248 } */ bsd_args; 249 250 bsd_args.key = args->arg1; 251 bsd_args.size = args->arg2; 252 bsd_args.shmflg = args->arg3; 253 return shmget(p, &bsd_args, retval); 254} 255 256int 257linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval) 258{ 259 struct shmid_ds bsd_shmid; 260 struct linux_shmid_ds linux_shmid; 261 struct shmctl_args /* { 262 int shmid; 263 int cmd; 264 struct shmid_ds *buf; 265 } */ bsd_args; 266 int error; 267 268 switch (args->arg2) { 269 case LINUX_IPC_STAT: 270 bsd_args.shmid = args->arg1; 271 bsd_args.cmd = IPC_STAT; 272 bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds)); 273 if ((error = shmctl(p, &bsd_args, retval))) 274 return error; 275 if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 276 sizeof(struct shmid_ds)))) 277 return error; 278 bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); 279 return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); 280 281 case LINUX_IPC_SET: 282 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 283 sizeof(linux_shmid)))) 284 return error; 285 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 286 bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds)); 287 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 288 sizeof(struct shmid_ds)))) 289 return error; 290 bsd_args.shmid = args->arg1; 291 bsd_args.cmd = IPC_SET; 292 return shmctl(p, &bsd_args, retval); 293 294 case LINUX_IPC_RMID: 295 bsd_args.shmid = args->arg1; 296 bsd_args.cmd = IPC_RMID; 297 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, 298 sizeof(linux_shmid)))) 299 return error; 300 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 301 bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds)); 302 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf, 303 sizeof(struct shmid_ds)))) 304 return error; 305 return shmctl(p, &bsd_args, retval); 306 307 case LINUX_IPC_INFO: 308 case LINUX_SHM_STAT: 309 case LINUX_SHM_INFO: 310 case LINUX_SHM_LOCK: 311 case LINUX_SHM_UNLOCK: 312 default: 313 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 314 return EINVAL; 315 } 316} 317 318int 319linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval) 320{ 321 switch (args->what) { 322 case LINUX_SEMOP: 323 return linux_semop(p, args, retval); 324 case LINUX_SEMGET: 325 return linux_semget(p, args, retval); 326 case LINUX_SEMCTL: 327 return linux_semctl(p, args, retval); 328 case LINUX_MSGSND: 329 return linux_msgsnd(p, args, retval); 330 case LINUX_MSGRCV: 331 return linux_msgrcv(p, args, retval); 332 case LINUX_MSGGET: 333 return linux_msgget(p, args, retval); 334 case LINUX_MSGCTL: 335 return linux_msgctl(p, args, retval); 336 case LINUX_SHMAT: 337 return linux_shmat(p, args, retval); 338 case LINUX_SHMDT: 339 return linux_shmdt(p, args, retval); 340 case LINUX_SHMGET: 341 return linux_shmget(p, args, retval); 342 case LINUX_SHMCTL: 343 return linux_shmctl(p, args, retval); 344 default: 345 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what); 346 return ENOSYS; 347 } 348} 349