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 * $FreeBSD: src/sys/i386/linux/linux_ipc.c,v 1.8.2.3 1999/09/05 08:14:15 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/sem.h>
37 #include <sys/shm.h>
38
39 #include <i386/linux/linux.h>
40 #include <i386/linux/linux_proto.h>
41 #include <i386/linux/linux_util.h>
42
43 static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *));
44 static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *));
45 static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *));
46 static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *));
47 static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *));
48 static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *));
49 static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *));
50 static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *));
51 static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *));
52 static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *));
53
54 struct linux_ipc_perm {
55 linux_key_t key;
56 unsigned short uid;
57 unsigned short gid;
58 unsigned short cuid;
59 unsigned short cgid;
60 unsigned short mode;
61 unsigned short seq;
62 };
63
64 static void
65 linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp)
66 {
67 bpp->key = lpp->key;
68 bpp->uid = lpp->uid;
69 bpp->gid = lpp->gid;
70 bpp->cuid = lpp->cuid;
71 bpp->cgid = lpp->cgid;
72 bpp->mode = lpp->mode;
73 bpp->seq = lpp->seq;
74 }
75
76
77 static void
78 bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp)
79 {
80 lpp->key = bpp->key;
81 lpp->uid = bpp->uid;
82 lpp->gid = bpp->gid;
83 lpp->cuid = bpp->cuid;
84 lpp->cgid = bpp->cgid;
85 lpp->mode = bpp->mode;
86 lpp->seq = bpp->seq;
87 }
88
89 struct linux_semid_ds {
90 struct linux_ipc_perm sem_perm;
91 linux_time_t sem_otime;
92 linux_time_t sem_ctime;
93 void *sem_base;
94 void *sem_pending;
95 void *sem_pending_last;
96 void *undo;
97 ushort sem_nsems;
98 };
99
100 struct linux_shmid_ds {
101 struct linux_ipc_perm shm_perm;
102 int shm_segsz;
103 linux_time_t shm_atime;
104 linux_time_t shm_dtime;
105 linux_time_t shm_ctime;
106 ushort shm_cpid;
107 ushort shm_lpid;
108 short shm_nattch;
109 ushort private1;
110 void *private2;
111 void *private3;
112 };
113
114 static void
115 linux_to_bsd_semid_ds(struct linux_semid_ds *lsp, struct semid_ds *bsp)
116 {
117 linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
118 bsp->sem_otime = lsp->sem_otime;
119 bsp->sem_ctime = lsp->sem_ctime;
120 bsp->sem_nsems = lsp->sem_nsems;
121 bsp->sem_base = lsp->sem_base;
122 }
123
124 static void
125 bsd_to_linux_semid_ds(struct semid_ds *bsp, struct linux_semid_ds *lsp)
126 {
127 bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
128 lsp->sem_otime = bsp->sem_otime;
129 lsp->sem_ctime = bsp->sem_ctime;
130 lsp->sem_nsems = bsp->sem_nsems;
131 lsp->sem_base = bsp->sem_base;
132 }
133
134 static void
135 linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp)
136 {
137 linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
138 bsp->shm_segsz = lsp->shm_segsz;
139 bsp->shm_lpid = lsp->shm_lpid;
140 bsp->shm_cpid = lsp->shm_cpid;
141 bsp->shm_nattch = lsp->shm_nattch;
142 bsp->shm_atime = lsp->shm_atime;
143 bsp->shm_dtime = lsp->shm_dtime;
144 bsp->shm_ctime = lsp->shm_ctime;
145 bsp->shm_internal = lsp->private3; /* this goes (yet) SOS */
146 }
147
148 static void
149 bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
150 {
151 bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
152 lsp->shm_segsz = bsp->shm_segsz;
153 lsp->shm_lpid = bsp->shm_lpid;
154 lsp->shm_cpid = bsp->shm_cpid;
155 lsp->shm_nattch = bsp->shm_nattch;
156 lsp->shm_atime = bsp->shm_atime;
157 lsp->shm_dtime = bsp->shm_dtime;
158 lsp->shm_ctime = bsp->shm_ctime;
159 lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
160 }
161
162 static int
163 linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
164 {
165 struct semop_args /* {
166 int semid;
167 struct sembuf *sops;
168 int nsops;
169 } */ bsd_args;
170
171 bsd_args.semid = args->arg1;
172 bsd_args.sops = (struct sembuf *)args->ptr;
173 bsd_args.nsops = args->arg2;
174 return semop(p, &bsd_args, retval);
175 }
176
177 static int
178 linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
179 {
180 struct semget_args /* {
181 key_t key;
182 int nsems;
183 int semflg;
184 } */ bsd_args;
185
186 bsd_args.key = args->arg1;
187 bsd_args.nsems = args->arg2;
188 bsd_args.semflg = args->arg3;
189 return semget(p, &bsd_args, retval);
190 }
191
192 static int
193 linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
194 {
195 struct linux_semid_ds linux_semid;
196 struct semid_ds bsd_semid;
197 struct __semctl_args /* {
198 int semid;
199 int semnum;
200 int cmd;
201 union semun *arg;
202 } */ bsd_args;
203 int error;
204 caddr_t sg, unptr, dsp, ldsp;
205
206 sg = stackgap_init();
207 bsd_args.semid = args->arg1;
208 bsd_args.semnum = args->arg2;
209 bsd_args.cmd = args->arg3;
210 bsd_args.arg = (union semun *)args->ptr;
211
212 switch (args->arg3) {
213 case LINUX_IPC_RMID:
214 bsd_args.cmd = IPC_RMID;
215 break;
216 case LINUX_GETNCNT:
217 bsd_args.cmd = GETNCNT;
218 break;
219 case LINUX_GETPID:
220 bsd_args.cmd = GETPID;
221 break;
222 case LINUX_GETVAL:
223 bsd_args.cmd = GETVAL;
224 break;
225 case LINUX_GETZCNT:
226 bsd_args.cmd = GETZCNT;
227 break;
228 case LINUX_SETVAL:
229 bsd_args.cmd = SETVAL;
230 break;
231 case LINUX_IPC_SET:
232 bsd_args.cmd = IPC_SET;
233 error = copyin(args->ptr, &ldsp, sizeof(ldsp));
234 if (error)
235 return error;
236 error = copyin(ldsp, (caddr_t)&linux_semid, sizeof(linux_semid));
237 if (error)
238 return error;
239 linux_to_bsd_semid_ds(&linux_semid, &bsd_semid);
240 unptr = stackgap_alloc(&sg, sizeof(union semun));
241 dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
242 error = copyout((caddr_t)&bsd_semid, dsp, sizeof(bsd_semid));
243 if (error)
244 return error;
245 error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
246 if (error)
247 return error;
248 bsd_args.arg = (union semun *)unptr;
249 return __semctl(p, &bsd_args, retval);
250 case LINUX_IPC_STAT:
251 bsd_args.cmd = IPC_STAT;
252 unptr = stackgap_alloc(&sg, sizeof(union semun *));
253 dsp = stackgap_alloc(&sg, sizeof(struct semid_ds));
254 error = copyout((caddr_t)&dsp, unptr, sizeof(dsp));
255 if (error)
256 return error;
257 bsd_args.arg = (union semun *)unptr;
258 error = __semctl(p, &bsd_args, retval);
259 if (error)
260 return error;
261 error = copyin(dsp, (caddr_t)&bsd_semid, sizeof(bsd_semid));
262 if (error)
263 return error;
264 bsd_to_linux_semid_ds(&bsd_semid, &linux_semid);
265 error = copyin(args->ptr, &ldsp, sizeof(ldsp));
266 if (error)
267 return error;
268 return copyout((caddr_t)&linux_semid, ldsp, sizeof(linux_semid));
269 case LINUX_GETALL:
270 /* FALLTHROUGH */
271 case LINUX_SETALL:
272 /* FALLTHROUGH */
273 default:
274 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
275 return EINVAL;
276 }
277 return __semctl(p, &bsd_args, retval);
278 }
279
280 static int
281 linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
282 {
283 struct msgsnd_args /* {
284 int msqid;
285 void *msgp;
286 size_t msgsz;
287 int msgflg;
288 } */ bsd_args;
289
290 bsd_args.msqid = args->arg1;
291 bsd_args.msgp = args->ptr;
292 bsd_args.msgsz = args->arg2;
293 bsd_args.msgflg = args->arg3;
294 return msgsnd(p, &bsd_args, retval);
295 }
296
297 static int
298 linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
299 {
300 struct msgrcv_args /* {
301 int msqid;
302 void *msgp;
303 size_t msgsz;
304 long msgtyp;
305 int msgflg;
306 } */ bsd_args;
307
308 bsd_args.msqid = args->arg1;
309 bsd_args.msgp = args->ptr;
310 bsd_args.msgsz = args->arg2;
311 bsd_args.msgtyp = 0;
312 bsd_args.msgflg = args->arg3;
313 return msgrcv(p, &bsd_args, retval);
314 }
315
316 static int
317 linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
318 {
319 struct msgget_args /* {
320 key_t key;
321 int msgflg;
322 } */ bsd_args;
323
324 bsd_args.key = args->arg1;
325 bsd_args.msgflg = args->arg2;
326 return msgget(p, &bsd_args, retval);
327 }
328
329 static int
330 linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
331 {
332 struct msgctl_args /* {
333 int msqid;
334 int cmd;
335 struct msqid_ds *buf;
336 } */ bsd_args;
337
338 bsd_args.msqid = args->arg1;
339 bsd_args.cmd = args->arg2;
340 bsd_args.buf = (struct msqid_ds *)args->ptr;
341 return msgctl(p, &bsd_args, retval);
342 }
343
344 static int
345 linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
346 {
347 struct shmat_args /* {
348 int shmid;
349 void *shmaddr;
350 int shmflg;
351 } */ bsd_args;
352 int error;
353
354 bsd_args.shmid = args->arg1;
355 bsd_args.shmaddr = args->ptr;
356 bsd_args.shmflg = args->arg2;
357 if ((error = shmat(p, &bsd_args, retval)))
358 return error;
359 if ((error = copyout(retval, (caddr_t)args->arg3, sizeof(int))))
360 return error;
361 retval[0] = 0;
362 return 0;
363 }
364
365 static int
366 linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
367 {
368 struct shmdt_args /* {
369 void *shmaddr;
370 } */ bsd_args;
371
372 bsd_args.shmaddr = args->ptr;
373 return shmdt(p, &bsd_args, retval);
374 }
375
376 static int
377 linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
378 {
379 struct shmget_args /* {
380 key_t key;
381 int size;
382 int shmflg;
383 } */ bsd_args;
384
385 bsd_args.key = args->arg1;
386 bsd_args.size = args->arg2;
387 bsd_args.shmflg = args->arg3;
388 return shmget(p, &bsd_args, retval);
389 }
390
391 static int
392 linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
393 {
394 struct shmid_ds bsd_shmid;
395 struct linux_shmid_ds linux_shmid;
396 struct shmctl_args /* {
397 int shmid;
398 int cmd;
399 struct shmid_ds *buf;
400 } */ bsd_args;
401 int error;
402 caddr_t sg = stackgap_init();
403
404 switch (args->arg2) {
405 case LINUX_IPC_STAT:
406 bsd_args.shmid = args->arg1;
407 bsd_args.cmd = IPC_STAT;
408 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
409 if ((error = shmctl(p, &bsd_args, retval)))
410 return error;
411 if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid,
412 sizeof(struct shmid_ds))))
413 return error;
414 bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
415 return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid));
416
417 case LINUX_IPC_SET:
418 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
419 sizeof(linux_shmid))))
420 return error;
421 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
422 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
423 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
424 sizeof(struct shmid_ds))))
425 return error;
426 bsd_args.shmid = args->arg1;
427 bsd_args.cmd = IPC_SET;
428 return shmctl(p, &bsd_args, retval);
429
430 case LINUX_IPC_RMID:
431 bsd_args.shmid = args->arg1;
432 bsd_args.cmd = IPC_RMID;
433 if (NULL == args->ptr)
434 bsd_args.buf = NULL;
435 else {
436 if ((error = copyin(args->ptr, (caddr_t)&linux_shmid,
437 sizeof(linux_shmid))))
438 return error;
439 linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
440 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
441 if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
442 sizeof(struct shmid_ds))))
443 return error;
444 }
445 return shmctl(p, &bsd_args, retval);
446
447 case LINUX_IPC_INFO:
448 case LINUX_SHM_STAT:
449 case LINUX_SHM_INFO:
450 case LINUX_SHM_LOCK:
451 case LINUX_SHM_UNLOCK:
452 default:
453 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
454 return EINVAL;
455 }
456 }
457
458 int
459 linux_ipc(struct proc *p, struct linux_ipc_args *args, int *retval)
460 {
461 switch (args->what) {
462 case LINUX_SEMOP:
463 return linux_semop(p, args, retval);
464 case LINUX_SEMGET:
465 return linux_semget(p, args, retval);
466 case LINUX_SEMCTL:
467 return linux_semctl(p, args, retval);
468 case LINUX_MSGSND:
469 return linux_msgsnd(p, args, retval);
470 case LINUX_MSGRCV:
471 return linux_msgrcv(p, args, retval);
472 case LINUX_MSGGET:
473 return linux_msgget(p, args, retval);
474 case LINUX_MSGCTL:
475 return linux_msgctl(p, args, retval);
476 case LINUX_SHMAT:
477 return linux_shmat(p, args, retval);
478 case LINUX_SHMDT:
479 return linux_shmdt(p, args, retval);
480 case LINUX_SHMGET:
481 return linux_shmget(p, args, retval);
482 case LINUX_SHMCTL:
483 return linux_shmctl(p, args, retval);
484 default:
485 uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->what);
486 return ENOSYS;
487 }
488 }
Cache object: 9bb21165fbecad0e11301fd9bd52a17a
|