linux emulation - Major update
[dragonfly.git] / sys / emulation / linux / linux_ipc.c
blob5a8b0df4ea2c46adf76c9a9ed1d711e87576d2e8
1 /*-
2 * Copyright (c) 1994-1995 Søren Schmidt
3 * All rights reserved.
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
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.
28 * $FreeBSD: src/sys/compat/linux/linux_ipc.c,v 1.17.2.3 2001/11/05 19:08:22 marcel Exp $
29 * $DragonFly: src/sys/emulation/linux/linux_ipc.c,v 1.8 2006/06/05 07:26:09 dillon Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/sysproto.h>
35 #include <sys/proc.h>
36 #include <sys/msg.h>
37 #include <sys/sem.h>
38 #include <sys/shm.h>
40 #include <arch_linux/linux.h>
41 #include <machine/limits.h>
42 #include <arch_linux/linux_proto.h>
43 #include "linux_ipc.h"
44 #include "linux_util.h"
47 static void
48 bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp)
50 lpp->shmmax = bpp->shmmax;
51 lpp->shmmin = bpp->shmmin;
52 lpp->shmmni = bpp->shmmni;
53 lpp->shmseg = bpp->shmseg;
54 lpp->shmall = bpp->shmall;
57 #if 0
58 static void
59 bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp)
61 lpp->used_ids = bpp->used_ids ;
62 lpp->shm_tot = bpp->shm_tot ;
63 lpp->shm_rss = bpp->shm_rss ;
64 lpp->shm_swp = bpp->shm_swp ;
65 lpp->swap_attempts = bpp->swap_attempts ;
66 lpp->swap_successes = bpp->swap_successes ;
68 #endif
71 * MPSAFE
73 static void
74 linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp)
76 bpp->key = lpp->key;
77 bpp->uid = lpp->uid;
78 bpp->gid = lpp->gid;
79 bpp->cuid = lpp->cuid;
80 bpp->cgid = lpp->cgid;
81 bpp->mode = lpp->mode;
82 bpp->seq = lpp->seq;
86 * MPSAFE
88 static void
89 bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp)
91 lpp->key = bpp->key;
92 lpp->uid = bpp->uid;
93 lpp->gid = bpp->gid;
94 lpp->cuid = bpp->cuid;
95 lpp->cgid = bpp->cgid;
96 lpp->mode = bpp->mode;
97 lpp->seq = bpp->seq;
101 * MPSAFE
103 static void
104 linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp)
106 linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
107 bsp->sem_otime = lsp->sem_otime;
108 bsp->sem_ctime = lsp->sem_ctime;
109 bsp->sem_nsems = lsp->sem_nsems;
110 bsp->sem_base = lsp->sem_base;
114 * MPSAFE
116 static void
117 bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp)
119 bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
120 lsp->sem_otime = bsp->sem_otime;
121 lsp->sem_ctime = bsp->sem_ctime;
122 lsp->sem_nsems = bsp->sem_nsems;
123 lsp->sem_base = bsp->sem_base;
127 * MPSAFE
129 static void
130 linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
132 linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
133 bsp->shm_segsz = lsp->shm_segsz;
134 bsp->shm_lpid = lsp->shm_lpid;
135 bsp->shm_cpid = lsp->shm_cpid;
136 bsp->shm_nattch = lsp->shm_nattch;
137 bsp->shm_atime = lsp->shm_atime;
138 bsp->shm_dtime = lsp->shm_dtime;
139 bsp->shm_ctime = lsp->shm_ctime;
143 * MPSAFE
145 static void
146 bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
148 bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
149 if (bsp->shm_segsz > INT_MAX)
150 lsp->shm_segsz = INT_MAX;
151 else
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 = 0;
162 static void
163 linux_to_bsd_msqid_ds(struct l_msqid_ds *lsp, struct msqid_ds *bsp)
165 linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm);
166 bsp->msg_cbytes = lsp->msg_cbytes;
167 bsp->msg_qnum = lsp->msg_qnum;
168 bsp->msg_qbytes = lsp->msg_qbytes;
169 bsp->msg_lspid = lsp->msg_lspid;
170 bsp->msg_lrpid = lsp->msg_lrpid;
171 bsp->msg_stime = lsp->msg_stime;
172 bsp->msg_rtime = lsp->msg_rtime;
173 bsp->msg_ctime = lsp->msg_ctime;
176 static void
177 bsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid_ds *lsp)
179 bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm);
180 lsp->msg_cbytes = bsp->msg_cbytes;
181 lsp->msg_qnum = bsp->msg_qnum;
182 lsp->msg_qbytes = bsp->msg_qbytes;
183 lsp->msg_lspid = bsp->msg_lspid;
184 lsp->msg_lrpid = bsp->msg_lrpid;
185 lsp->msg_stime = bsp->msg_stime;
186 lsp->msg_rtime = bsp->msg_rtime;
187 lsp->msg_ctime = bsp->msg_ctime;
190 static void
191 linux_ipc_perm_to_ipc64_perm(struct l_ipc_perm *in, struct l_ipc64_perm *out)
194 /* XXX: do we really need to do something here? */
195 out->key = in->key;
196 out->uid = in->uid;
197 out->gid = in->gid;
198 out->cuid = in->cuid;
199 out->cgid = in->cgid;
200 out->mode = in->mode;
201 out->seq = in->seq;
204 static int
205 linux_msqid_pullup(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr)
207 struct l_msqid64_ds linux_msqid64;
208 int error;
210 if (ver == LINUX_IPC_64) {
211 error = copyin(uaddr, &linux_msqid64, sizeof(linux_msqid64));
212 if (error != 0)
213 return (error);
215 bzero(linux_msqid, sizeof(*linux_msqid));
217 linux_msqid->msg_perm.uid = linux_msqid64.msg_perm.uid;
218 linux_msqid->msg_perm.gid = linux_msqid64.msg_perm.gid;
219 linux_msqid->msg_perm.mode = linux_msqid64.msg_perm.mode;
221 if (linux_msqid64.msg_qbytes > USHRT_MAX)
222 linux_msqid->msg_lqbytes = linux_msqid64.msg_qbytes;
223 else
224 linux_msqid->msg_qbytes = linux_msqid64.msg_qbytes;
225 } else {
226 error = copyin(uaddr, linux_msqid, sizeof(*linux_msqid));
228 return (error);
231 static int
232 linux_msqid_pushdown(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr)
234 struct l_msqid64_ds linux_msqid64;
236 if (ver == LINUX_IPC_64) {
237 bzero(&linux_msqid64, sizeof(linux_msqid64));
239 linux_ipc_perm_to_ipc64_perm(&linux_msqid->msg_perm,
240 &linux_msqid64.msg_perm);
242 linux_msqid64.msg_stime = linux_msqid->msg_stime;
243 linux_msqid64.msg_rtime = linux_msqid->msg_rtime;
244 linux_msqid64.msg_ctime = linux_msqid->msg_ctime;
246 if (linux_msqid->msg_cbytes == 0)
247 linux_msqid64.msg_cbytes = linux_msqid->msg_lcbytes;
248 else
249 linux_msqid64.msg_cbytes = linux_msqid->msg_cbytes;
251 linux_msqid64.msg_qnum = linux_msqid->msg_qnum;
253 if (linux_msqid->msg_qbytes == 0)
254 linux_msqid64.msg_qbytes = linux_msqid->msg_lqbytes;
255 else
256 linux_msqid64.msg_qbytes = linux_msqid->msg_qbytes;
258 linux_msqid64.msg_lspid = linux_msqid->msg_lspid;
259 linux_msqid64.msg_lrpid = linux_msqid->msg_lrpid;
261 return (copyout(&linux_msqid64, uaddr, sizeof(linux_msqid64)));
262 } else {
263 return (copyout(linux_msqid, uaddr, sizeof(*linux_msqid)));
267 static int
268 linux_semid_pullup(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr)
270 struct l_semid64_ds linux_semid64;
271 int error;
273 if (ver == LINUX_IPC_64) {
274 error = copyin(uaddr, &linux_semid64, sizeof(linux_semid64));
275 if (error != 0)
276 return (error);
278 bzero(linux_semid, sizeof(*linux_semid));
280 linux_semid->sem_perm.uid = linux_semid64.sem_perm.uid;
281 linux_semid->sem_perm.gid = linux_semid64.sem_perm.gid;
282 linux_semid->sem_perm.mode = linux_semid64.sem_perm.mode;
283 } else {
284 error = copyin(uaddr, linux_semid, sizeof(*linux_semid));
286 return (error);
289 static int
290 linux_semid_pushdown(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr)
292 struct l_semid64_ds linux_semid64;
294 if (ver == LINUX_IPC_64) {
295 bzero(&linux_semid64, sizeof(linux_semid64));
297 linux_ipc_perm_to_ipc64_perm(&linux_semid->sem_perm,
298 &linux_semid64.sem_perm);
300 linux_semid64.sem_otime = linux_semid->sem_otime;
301 linux_semid64.sem_ctime = linux_semid->sem_ctime;
302 linux_semid64.sem_nsems = linux_semid->sem_nsems;
304 return (copyout(&linux_semid64, uaddr, sizeof(linux_semid64)));
305 } else {
306 return (copyout(linux_semid, uaddr, sizeof(*linux_semid)));
310 static int
311 linux_shmid_pullup(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr)
313 struct l_shmid64_ds linux_shmid64;
314 int error;
316 if (ver == LINUX_IPC_64) {
317 error = copyin(uaddr, &linux_shmid64, sizeof(linux_shmid64));
318 if (error != 0)
319 return (error);
321 bzero(linux_shmid, sizeof(*linux_shmid));
323 linux_shmid->shm_perm.uid = linux_shmid64.shm_perm.uid;
324 linux_shmid->shm_perm.gid = linux_shmid64.shm_perm.gid;
325 linux_shmid->shm_perm.mode = linux_shmid64.shm_perm.mode;
326 } else {
327 error = copyin(uaddr, linux_shmid, sizeof(*linux_shmid));
329 return (error);
332 static int
333 linux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr)
335 struct l_shmid64_ds linux_shmid64;
338 * XXX: This is backwards and loses information in shm_nattch
339 * and shm_segsz. We should probably either expose the BSD
340 * shmid structure directly and convert it to either the
341 * non-64 or 64 variant directly or the code should always
342 * convert to the 64 variant and then truncate values into the
343 * non-64 variant if needed since the 64 variant has more
344 * precision.
346 if (ver == LINUX_IPC_64) {
347 bzero(&linux_shmid64, sizeof(linux_shmid64));
349 linux_ipc_perm_to_ipc64_perm(&linux_shmid->shm_perm,
350 &linux_shmid64.shm_perm);
352 linux_shmid64.shm_segsz = linux_shmid->shm_segsz;
353 linux_shmid64.shm_atime = linux_shmid->shm_atime;
354 linux_shmid64.shm_dtime = linux_shmid->shm_dtime;
355 linux_shmid64.shm_ctime = linux_shmid->shm_ctime;
356 linux_shmid64.shm_cpid = linux_shmid->shm_cpid;
357 linux_shmid64.shm_lpid = linux_shmid->shm_lpid;
358 linux_shmid64.shm_nattch = linux_shmid->shm_nattch;
360 return (copyout(&linux_shmid64, uaddr, sizeof(linux_shmid64)));
361 } else {
362 return (copyout(linux_shmid, uaddr, sizeof(*linux_shmid)));
366 static int
367 linux_shminfo_pushdown(l_int ver, struct l_shminfo *linux_shminfo,
368 caddr_t uaddr)
370 struct l_shminfo64 linux_shminfo64;
372 if (ver == LINUX_IPC_64) {
373 bzero(&linux_shminfo64, sizeof(linux_shminfo64));
375 linux_shminfo64.shmmax = linux_shminfo->shmmax;
376 linux_shminfo64.shmmin = linux_shminfo->shmmin;
377 linux_shminfo64.shmmni = linux_shminfo->shmmni;
378 linux_shminfo64.shmseg = linux_shminfo->shmseg;
379 linux_shminfo64.shmall = linux_shminfo->shmall;
381 return (copyout(&linux_shminfo64, uaddr,
382 sizeof(linux_shminfo64)));
383 } else {
384 return (copyout(linux_shminfo, uaddr, sizeof(*linux_shminfo)));
389 * MPSAFE
392 linux_semop(struct linux_semop_args *args)
394 struct semop_args bsd_args;
395 int error;
397 bsd_args.sysmsg_result = 0;
398 bsd_args.semid = args->semid;
399 bsd_args.sops = (struct sembuf *)args->tsops;
400 bsd_args.nsops = args->nsops;
401 error = sys_semop(&bsd_args);
402 args->sysmsg_result = bsd_args.sysmsg_result;
403 return(error);
407 * MPSAFE
410 linux_semget(struct linux_semget_args *args)
412 struct semget_args bsd_args;
413 int error;
415 bsd_args.sysmsg_result = 0;
416 bsd_args.key = args->key;
417 bsd_args.nsems = args->nsems;
418 bsd_args.semflg = args->semflg;
419 error = sys_semget(&bsd_args);
420 args->sysmsg_result = bsd_args.sysmsg_result;
421 return(error);
425 * MPSAFE
428 linux_semctl(struct linux_semctl_args *args)
430 struct l_semid_ds linux_semid;
431 struct __semctl_args bsd_args;
432 struct l_seminfo linux_seminfo;
433 int error;
434 union semun *unptr;
435 caddr_t sg;
437 sg = stackgap_init();
439 /* Make sure the arg parameter can be copied in. */
440 unptr = stackgap_alloc(&sg, sizeof(union semun));
441 bcopy(&args->arg, unptr, sizeof(union semun));
443 bsd_args.sysmsg_result = 0;
444 bsd_args.semid = args->semid;
445 bsd_args.semnum = args->semnum;
446 bsd_args.arg = unptr;
448 switch (args->cmd & ~LINUX_IPC_64) {
449 case LINUX_IPC_RMID:
450 bsd_args.cmd = IPC_RMID;
451 break;
452 case LINUX_GETNCNT:
453 bsd_args.cmd = GETNCNT;
454 break;
455 case LINUX_GETPID:
456 bsd_args.cmd = GETPID;
457 break;
458 case LINUX_GETVAL:
459 bsd_args.cmd = GETVAL;
460 break;
461 case LINUX_GETZCNT:
462 bsd_args.cmd = GETZCNT;
463 break;
464 case LINUX_SETVAL:
465 bsd_args.cmd = SETVAL;
466 break;
467 case LINUX_IPC_SET:
468 bsd_args.cmd = IPC_SET;
469 error = linux_semid_pullup(args->cmd & LINUX_IPC_64,
470 &linux_semid, (caddr_t)args->arg.buf);
471 if (error)
472 return (error);
473 unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
474 linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
475 break;
476 case LINUX_IPC_STAT:
477 case LINUX_SEM_STAT:
478 if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT)
479 bsd_args.cmd = IPC_STAT;
480 else
481 bsd_args.cmd = SEM_STAT;
482 unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
483 error = sys___semctl(&bsd_args);
484 if (error)
485 return error;
486 args->sysmsg_result = IXSEQ_TO_IPCID(bsd_args.semid,
487 unptr->buf->sem_perm);
488 bsd_to_linux_semid_ds(unptr->buf, &linux_semid);
489 error = linux_semid_pushdown(args->cmd & LINUX_IPC_64,
490 &linux_semid, (caddr_t)(args->arg.buf));
491 if (error == 0)
492 args->sysmsg_iresult = ((args->cmd & ~LINUX_IPC_64) == SEM_STAT)
493 ? bsd_args.sysmsg_result : 0;
494 return (error);
495 case LINUX_IPC_INFO:
496 case LINUX_SEM_INFO:
497 error = copyin((caddr_t)args->arg.buf, &linux_seminfo,
498 sizeof(linux_seminfo) );
499 if (error)
500 return error;
501 bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) );
502 /* XXX BSD equivalent?
503 #define used_semids 10
504 #define used_sems 10
505 linux_seminfo.semusz = used_semids;
506 linux_seminfo.semaem = used_sems;
508 error = copyout((caddr_t)&linux_seminfo, (caddr_t)args->arg.buf,
509 sizeof(linux_seminfo) );
510 if (error)
511 return error;
512 args->sysmsg_result = seminfo.semmni;
513 return 0; /* No need for __semctl call */
514 case LINUX_GETALL:
515 bsd_args.cmd = GETALL;
516 break;
517 case LINUX_SETALL:
518 bsd_args.cmd = SETALL;
519 break;
520 default:
521 uprintf("linux: 'ipc' type=%d not implemented\n", args->cmd & ~LINUX_IPC_64);
522 return EINVAL;
524 error = sys___semctl(&bsd_args);
525 args->sysmsg_result = bsd_args.sysmsg_result;
526 return(error);
530 * MPSAFE
533 linux_msgsnd(struct linux_msgsnd_args *args)
535 struct msgsnd_args bsd_args;
536 int error;
538 if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax)
539 return (EINVAL);
540 bsd_args.sysmsg_result = 0;
541 bsd_args.msqid = args->msqid;
542 bsd_args.msgp = args->msgp;
543 bsd_args.msgsz = args->msgsz;
544 bsd_args.msgflg = args->msgflg;
545 error = sys_msgsnd(&bsd_args);
546 args->sysmsg_result = bsd_args.sysmsg_result;
547 return(error);
551 * MPSAFE
554 linux_msgrcv(struct linux_msgrcv_args *args)
556 struct msgrcv_args bsd_args;
557 int error;
558 if ((l_long)args->msgsz < 0 || args->msgsz > (l_long)msginfo.msgmax)
559 return (EINVAL);
560 bsd_args.sysmsg_result = 0;
561 bsd_args.msqid = args->msqid;
562 bsd_args.msgp = args->msgp;
563 bsd_args.msgsz = args->msgsz;
564 bsd_args.msgtyp = 0; /* XXX - args->msgtyp; */
565 bsd_args.msgflg = args->msgflg;
566 error = sys_msgrcv(&bsd_args);
567 args->sysmsg_result = bsd_args.sysmsg_result;
568 return(error);
572 * MPSAFE
575 linux_msgget(struct linux_msgget_args *args)
577 struct msgget_args bsd_args;
578 int error;
580 bsd_args.sysmsg_result = 0;
581 bsd_args.key = args->key;
582 bsd_args.msgflg = args->msgflg;
583 error = sys_msgget(&bsd_args);
584 args->sysmsg_result = bsd_args.sysmsg_result;
585 return(error);
589 * MPSAFE
592 linux_msgctl(struct linux_msgctl_args *args)
594 struct msgctl_args bsd_args;
595 struct l_msqid_ds linux_msqid;
596 int error, bsd_cmd;
597 struct msqid_ds *unptr;
598 caddr_t sg;
600 sg = stackgap_init();
601 /* Make sure the arg parameter can be copied in. */
602 unptr = stackgap_alloc(&sg, sizeof(struct msqid_ds));
603 bcopy(&args->buf, unptr, sizeof(struct msqid_ds));
605 bsd_cmd = args->cmd & ~LINUX_IPC_64;
606 bsd_args.sysmsg_result = 0;
607 bsd_args.msqid = args->msqid;
608 bsd_args.cmd = bsd_cmd;
609 bsd_args.buf = unptr;
610 switch(bsd_cmd) {
611 case LINUX_IPC_INFO:
612 case LINUX_MSG_INFO: {
613 struct l_msginfo linux_msginfo;
616 * XXX MSG_INFO uses the same data structure but returns different
617 * dynamic counters in msgpool, msgmap, and msgtql fields.
619 linux_msginfo.msgpool = (long)msginfo.msgmni *
620 (long)msginfo.msgmnb / 1024L; /* XXX MSG_INFO. */
621 linux_msginfo.msgmap = msginfo.msgmnb; /* XXX MSG_INFO. */
622 linux_msginfo.msgmax = msginfo.msgmax;
623 linux_msginfo.msgmnb = msginfo.msgmnb;
624 linux_msginfo.msgmni = msginfo.msgmni;
625 linux_msginfo.msgssz = msginfo.msgssz;
626 linux_msginfo.msgtql = msginfo.msgtql; /* XXX MSG_INFO. */
627 linux_msginfo.msgseg = msginfo.msgseg;
628 error = copyout(&linux_msginfo, PTRIN(args->buf),
629 sizeof(linux_msginfo));
630 if (error == 0)
631 args->sysmsg_iresult = msginfo.msgmni; /* XXX */
633 return (error);
637 * TODO: implement this
638 * case LINUX_MSG_STAT:
640 case LINUX_IPC_STAT:
641 /* NOTHING */
642 break;
644 case LINUX_IPC_SET:
645 error = linux_msqid_pullup(args->cmd & LINUX_IPC_64,
646 &linux_msqid, (caddr_t)(args->buf));
647 if (error)
648 return (error);
649 linux_to_bsd_msqid_ds(&linux_msqid, unptr);
650 break;
652 case LINUX_IPC_RMID:
653 /* NOTHING */
654 break;
656 default:
657 return (EINVAL);
658 break;
661 error = sys_msgctl(&bsd_args);
662 if (error != 0)
663 if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL)
664 return (error);
665 if (bsd_cmd == LINUX_IPC_STAT) {
666 bsd_to_linux_msqid_ds(bsd_args.buf, &linux_msqid);
667 return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64,
668 &linux_msqid, PTRIN(args->buf)));
670 args->sysmsg_result = bsd_args.sysmsg_result;
671 return ((args->cmd == LINUX_IPC_RMID && error == EINVAL) ? 0 : error);
679 * MPSAFE
682 linux_shmat(struct linux_shmat_args *args)
684 struct shmat_args bsd_args;
685 int error;
687 bsd_args.sysmsg_result = 0;
688 bsd_args.shmid = args->shmid;
689 bsd_args.shmaddr = args->shmaddr;
690 bsd_args.shmflg = args->shmflg;
691 if ((error = sys_shmat(&bsd_args)))
692 return error;
693 #ifdef __i386__
694 if ((error = copyout(&bsd_args.sysmsg_lresult, (caddr_t)args->raddr, sizeof(l_ulong))))
695 return error;
696 args->sysmsg_result = 0;
697 #else
698 args->sysmsg_result = bsd_args.sysmsg_result;
699 #endif
700 return 0;
704 * MPSAFE
707 linux_shmdt(struct linux_shmdt_args *args)
709 struct shmdt_args bsd_args;
710 int error;
712 bsd_args.sysmsg_result = 0;
713 bsd_args.shmaddr = args->shmaddr;
714 error = sys_shmdt(&bsd_args);
715 args->sysmsg_result = bsd_args.sysmsg_result;
716 return(error);
720 * MPSAFE
723 linux_shmget(struct linux_shmget_args *args)
725 struct shmget_args bsd_args;
726 int error;
728 bsd_args.sysmsg_result = 0;
729 bsd_args.key = args->key;
730 bsd_args.size = args->size;
731 bsd_args.shmflg = args->shmflg;
732 error = sys_shmget(&bsd_args);
733 args->sysmsg_result = bsd_args.sysmsg_result;
734 return(error);
738 * MPSAFE
740 extern int shm_nused;
742 linux_shmctl(struct linux_shmctl_args *args)
744 struct l_shmid_ds linux_shmid;
745 struct l_shminfo linux_shminfo;
746 struct l_shm_info linux_shm_info;
747 struct shmctl_args bsd_args;
748 int error;
749 caddr_t sg = stackgap_init();
751 bsd_args.sysmsg_result = 0;
752 switch (args->cmd & ~LINUX_IPC_64) {
753 case LINUX_IPC_STAT:
754 case LINUX_SHM_STAT:
755 bsd_args.shmid = args->shmid;
756 bsd_args.cmd = IPC_STAT;
757 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
758 if ((error = sys_shmctl(&bsd_args)))
759 return error;
760 bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
761 args->sysmsg_result = bsd_args.sysmsg_result;
762 return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
763 &linux_shmid, PTRIN(args->buf)));
765 case LINUX_IPC_SET:
766 if ((error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
767 &linux_shmid, PTRIN(args->buf))))
768 return error;
769 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
770 linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
771 bsd_args.shmid = args->shmid;
772 bsd_args.cmd = IPC_SET;
773 break;
774 case LINUX_IPC_RMID:
775 bsd_args.shmid = args->shmid;
776 bsd_args.cmd = IPC_RMID;
777 if (args->buf == NULL)
778 bsd_args.buf = NULL;
779 else {
780 if ((error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
781 &linux_shmid, PTRIN(args->buf))))
782 return error;
783 bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
784 linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
786 break;
787 case LINUX_IPC_INFO:
788 bsd_to_linux_shminfo(&shminfo, &linux_shminfo);
789 return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
790 &linux_shminfo, PTRIN(args->buf)));
791 break;
792 case LINUX_SHM_INFO:
793 linux_shm_info.used_ids = shm_nused;
794 linux_shm_info.shm_tot = 0;
795 linux_shm_info.shm_rss = 0;
796 linux_shm_info.shm_swp = 0;
797 linux_shm_info.swap_attempts = 0;
798 linux_shm_info.swap_successes = 0;
799 return copyout(&linux_shm_info, PTRIN(args->buf),
800 sizeof(struct l_shm_info));
802 case LINUX_SHM_LOCK:
803 case LINUX_SHM_UNLOCK:
804 default:
805 uprintf("linux: 'ipc' type=%d not implemented\n", args->cmd & ~LINUX_IPC_64);
806 return EINVAL;
808 error = sys_shmctl(&bsd_args);
809 args->sysmsg_result = bsd_args.sysmsg_result;
810 return(error);