Annotation of sys/compat/linux/linux_ipc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: linux_ipc.c,v 1.10 2007/05/29 10:44:29 sturm Exp $ */
2: /* $NetBSD: linux_ipc.c,v 1.10 1996/04/05 00:01:44 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Frank van der Linden
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project
19: * by Frank van der Linden
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: #include <sys/types.h>
36: #include <sys/param.h>
37: #include <sys/kernel.h>
38: #include <sys/shm.h>
39: #include <sys/sem.h>
40: #include <sys/msg.h>
41: #include <sys/proc.h>
42: #include <sys/uio.h>
43: #include <sys/time.h>
44: #include <sys/malloc.h>
45: #include <sys/mman.h>
46: #include <sys/systm.h>
47: #include <sys/stat.h>
48:
49: #include <sys/mount.h>
50: #include <sys/syscallargs.h>
51:
52: #include <compat/linux/linux_types.h>
53: #include <compat/linux/linux_signal.h>
54: #include <compat/linux/linux_syscallargs.h>
55: #include <compat/linux/linux_util.h>
56: #include <compat/linux/linux_ipc.h>
57: #include <compat/linux/linux_msg.h>
58: #include <compat/linux/linux_shm.h>
59: #include <compat/linux/linux_sem.h>
60: #include <compat/linux/linux_ipccall.h>
61:
62: /*
63: * Stuff to deal with the SysV ipc/shm/semaphore interface in Linux.
64: * The main difference is, that Linux handles it all via one
65: * system call, which has the usual maximum amount of 5 arguments.
66: * This results in a kludge for calls that take 6 of them.
67: *
68: * The SYSVXXXX options have to be enabled to get the appropriate
69: * functions to work.
70: */
71:
72: #ifdef SYSVSEM
73: int linux_semop(struct proc *, void *, register_t *);
74: int linux_semget(struct proc *, void *, register_t *);
75: int linux_semctl(struct proc *, void *, register_t *);
76: void bsd_to_linux_semid_ds(struct semid_ds *, struct linux_semid_ds *);
77: void linux_to_bsd_semid_ds(struct linux_semid_ds *, struct semid_ds *);
78: #endif
79:
80: #ifdef SYSVMSG
81: int linux_msgsnd(struct proc *, void *, register_t *);
82: int linux_msgrcv(struct proc *, void *, register_t *);
83: int linux_msgget(struct proc *, void *, register_t *);
84: int linux_msgctl(struct proc *, void *, register_t *);
85: void linux_to_bsd_msqid_ds(struct linux_msqid_ds *, struct msqid_ds *);
86: void bsd_to_linux_msqid_ds(struct msqid_ds *, struct linux_msqid_ds *);
87: #endif
88:
89: #ifdef SYSVSHM
90: int linux_shmat(struct proc *, void *, register_t *);
91: int linux_shmdt(struct proc *, void *, register_t *);
92: int linux_shmget(struct proc *, void *, register_t *);
93: int linux_shmctl(struct proc *, void *, register_t *);
94: void linux_to_bsd_shmid_ds(struct linux_shmid_ds *, struct shmid_ds *);
95: void bsd_to_linux_shmid_ds(struct shmid_ds *, struct linux_shmid_ds *);
96: #endif
97:
98: #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
99: void linux_to_bsd_ipc_perm(struct linux_ipc_perm *, struct ipc_perm *);
100: void bsd_to_linux_ipc_perm(struct ipc_perm *, struct linux_ipc_perm *);
101: #endif
102:
103: int
104: linux_sys_ipc(p, v, retval)
105: struct proc *p;
106: void *v;
107: register_t *retval;
108: {
109: struct linux_sys_ipc_args /* {
110: syscallarg(int) what;
111: syscallarg(int) a1;
112: syscallarg(int) a2;
113: syscallarg(int) a3;
114: syscallarg(caddr_t) ptr;
115: } */ *uap = v;
116:
117: switch (SCARG(uap, what)) {
118: #ifdef SYSVSEM
119: case LINUX_SYS_semop:
120: return linux_semop(p, uap, retval);
121: case LINUX_SYS_semget:
122: return linux_semget(p, uap, retval);
123: case LINUX_SYS_semctl:
124: return linux_semctl(p, uap, retval);
125: #endif
126: #ifdef SYSVMSG
127: case LINUX_SYS_msgsnd:
128: return linux_msgsnd(p, uap, retval);
129: case LINUX_SYS_msgrcv:
130: return linux_msgrcv(p, uap, retval);
131: case LINUX_SYS_msgget:
132: return linux_msgget(p, uap, retval);
133: case LINUX_SYS_msgctl:
134: return linux_msgctl(p, uap, retval);
135: #endif
136: #ifdef SYSVSHM
137: case LINUX_SYS_shmat:
138: return linux_shmat(p, uap, retval);
139: case LINUX_SYS_shmdt:
140: return linux_shmdt(p, uap, retval);
141: case LINUX_SYS_shmget:
142: return linux_shmget(p, uap, retval);
143: case LINUX_SYS_shmctl:
144: return linux_shmctl(p, uap, retval);
145: #endif
146: default:
147: return ENOSYS;
148: }
149: }
150:
151: #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
152: /*
153: * Convert between Linux and OpenBSD ipc_perm structures. Only the
154: * order of the fields is different.
155: */
156: void
157: linux_to_bsd_ipc_perm(lpp, bpp)
158: struct linux_ipc_perm *lpp;
159: struct ipc_perm *bpp;
160: {
161:
162: bpp->key = lpp->l_key;
163: bpp->uid = lpp->l_uid;
164: bpp->gid = lpp->l_gid;
165: bpp->cuid = lpp->l_cuid;
166: bpp->cgid = lpp->l_cgid;
167: bpp->mode = lpp->l_mode;
168: bpp->seq = lpp->l_seq;
169: }
170:
171: void
172: bsd_to_linux_ipc_perm(bpp, lpp)
173: struct ipc_perm *bpp;
174: struct linux_ipc_perm *lpp;
175: {
176:
177: lpp->l_key = bpp->key;
178: lpp->l_uid = bpp->uid;
179: lpp->l_gid = bpp->gid;
180: lpp->l_cuid = bpp->cuid;
181: lpp->l_cgid = bpp->cgid;
182: lpp->l_mode = bpp->mode;
183: lpp->l_seq = bpp->seq;
184: }
185: #endif
186:
187: #ifdef SYSVSEM
188: /*
189: * Semaphore operations. Most constants and structures are the same on
190: * both systems. Only semctl() needs some extra work.
191: */
192:
193: /*
194: * Convert between Linux and OpenBSD semid_ds structures.
195: */
196: void
197: bsd_to_linux_semid_ds(bs, ls)
198: struct semid_ds *bs;
199: struct linux_semid_ds *ls;
200: {
201:
202: bsd_to_linux_ipc_perm(&bs->sem_perm, &ls->l_sem_perm);
203: ls->l_sem_otime = bs->sem_otime;
204: ls->l_sem_ctime = bs->sem_ctime;
205: ls->l_sem_nsems = bs->sem_nsems;
206: ls->l_sem_base = bs->sem_base;
207: }
208:
209: void
210: linux_to_bsd_semid_ds(ls, bs)
211: struct linux_semid_ds *ls;
212: struct semid_ds *bs;
213: {
214:
215: linux_to_bsd_ipc_perm(&ls->l_sem_perm, &bs->sem_perm);
216: bs->sem_otime = ls->l_sem_otime;
217: bs->sem_ctime = ls->l_sem_ctime;
218: bs->sem_nsems = ls->l_sem_nsems;
219: bs->sem_base = ls->l_sem_base;
220: }
221:
222: int
223: linux_semop(p, v, retval)
224: struct proc *p;
225: void *v;
226: register_t *retval;
227: {
228: struct linux_sys_ipc_args /* {
229: syscallarg(int) what;
230: syscallarg(int) a1;
231: syscallarg(int) a2;
232: syscallarg(int) a3;
233: syscallarg(caddr_t) ptr;
234: } */ *uap = v;
235: struct sys_semop_args bsa;
236:
237: SCARG(&bsa, semid) = SCARG(uap, a1);
238: SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
239: SCARG(&bsa, nsops) = SCARG(uap, a2);
240:
241: return sys_semop(p, &bsa, retval);
242: }
243:
244: int
245: linux_semget(p, v, retval)
246: struct proc *p;
247: void *v;
248: register_t *retval;
249: {
250: struct linux_sys_ipc_args /* {
251: syscallarg(int) what;
252: syscallarg(int) a1;
253: syscallarg(int) a2;
254: syscallarg(int) a3;
255: syscallarg(caddr_t) ptr;
256: } */ *uap = v;
257: struct sys_semget_args bsa;
258:
259: SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
260: SCARG(&bsa, nsems) = SCARG(uap, a2);
261: SCARG(&bsa, semflg) = SCARG(uap, a3);
262:
263: return sys_semget(p, &bsa, retval);
264: }
265:
266: /*
267: * Most of this can be handled by directly passing the arguments on,
268: * buf IPC_* require a lot of copy{in,out} because of the extra indirection
269: * (we are passed a pointer to a union cointaining a pointer to a semid_ds
270: * structure.
271: */
272: int
273: linux_semctl(p, v, retval)
274: struct proc *p;
275: void *v;
276: register_t *retval;
277: {
278: struct linux_sys_ipc_args /* {
279: syscallarg(int) what;
280: syscallarg(int) a1;
281: syscallarg(int) a2;
282: syscallarg(int) a3;
283: syscallarg(caddr_t) ptr;
284: } */ *uap = v;
285: caddr_t sg, unptr, dsp, ldsp;
286: int error, cmd;
287: struct sys___semctl_args bsa;
288: struct linux_semid_ds lm;
289: struct semid_ds bm;
290:
291: SCARG(&bsa, semid) = SCARG(uap, a1);
292: SCARG(&bsa, semnum) = SCARG(uap, a2);
293: SCARG(&bsa, cmd) = SCARG(uap, a3);
294: SCARG(&bsa, arg) = (union semun *)SCARG(uap, ptr);
295: switch(SCARG(uap, a3)) {
296: case LINUX_GETVAL:
297: cmd = GETVAL;
298: break;
299: case LINUX_GETPID:
300: cmd = GETPID;
301: break;
302: case LINUX_GETNCNT:
303: cmd = GETNCNT;
304: break;
305: case LINUX_GETZCNT:
306: cmd = GETZCNT;
307: break;
308: case LINUX_SETVAL:
309: cmd = SETVAL;
310: break;
311: case LINUX_IPC_RMID:
312: cmd = IPC_RMID;
313: break;
314: case LINUX_IPC_SET:
315: if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
316: return error;
317: if ((error = copyin(ldsp, (caddr_t)&lm, sizeof lm)))
318: return error;
319: linux_to_bsd_semid_ds(&lm, &bm);
320: sg = stackgap_init(p->p_emul);
321: unptr = stackgap_alloc(&sg, sizeof (union semun));
322: dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
323: if ((error = copyout((caddr_t)&bm, dsp, sizeof bm)))
324: return error;
325: if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
326: return error;
327: SCARG(&bsa, arg) = (union semun *)unptr;
328: return sys___semctl(p, &bsa, retval);
329: case LINUX_IPC_STAT:
330: sg = stackgap_init(p->p_emul);
331: unptr = stackgap_alloc(&sg, sizeof (union semun *));
332: dsp = stackgap_alloc(&sg, sizeof (struct semid_ds));
333: if ((error = copyout((caddr_t)&dsp, unptr, sizeof dsp)))
334: return error;
335: SCARG(&bsa, arg) = (union semun *)unptr;
336: if ((error = sys___semctl(p, &bsa, retval)))
337: return error;
338: if ((error = copyin(dsp, (caddr_t)&bm, sizeof bm)))
339: return error;
340: bsd_to_linux_semid_ds(&bm, &lm);
341: if ((error = copyin(SCARG(uap, ptr), &ldsp, sizeof ldsp)))
342: return error;
343: return copyout((caddr_t)&lm, ldsp, sizeof lm);
344: default:
345: return EINVAL;
346: }
347: SCARG(&bsa, cmd) = cmd;
348:
349: return sys___semctl(p, &bsa, retval);
350: }
351: #endif /* SYSVSEM */
352:
353: #ifdef SYSVMSG
354:
355: void
356: linux_to_bsd_msqid_ds(lmp, bmp)
357: struct linux_msqid_ds *lmp;
358: struct msqid_ds *bmp;
359: {
360:
361: linux_to_bsd_ipc_perm(&lmp->l_msg_perm, &bmp->msg_perm);
362: bmp->msg_first = lmp->l_msg_first;
363: bmp->msg_last = lmp->l_msg_last;
364: bmp->msg_cbytes = lmp->l_msg_cbytes;
365: bmp->msg_qnum = lmp->l_msg_qnum;
366: bmp->msg_qbytes = lmp->l_msg_qbytes;
367: bmp->msg_lspid = lmp->l_msg_lspid;
368: bmp->msg_lrpid = lmp->l_msg_lrpid;
369: bmp->msg_stime = lmp->l_msg_stime;
370: bmp->msg_rtime = lmp->l_msg_rtime;
371: bmp->msg_ctime = lmp->l_msg_ctime;
372: }
373:
374: void
375: bsd_to_linux_msqid_ds(bmp, lmp)
376: struct msqid_ds *bmp;
377: struct linux_msqid_ds *lmp;
378: {
379:
380: bsd_to_linux_ipc_perm(&bmp->msg_perm, &lmp->l_msg_perm);
381: lmp->l_msg_first = bmp->msg_first;
382: lmp->l_msg_last = bmp->msg_last;
383: lmp->l_msg_cbytes = bmp->msg_cbytes;
384: lmp->l_msg_qnum = bmp->msg_qnum;
385: lmp->l_msg_qbytes = bmp->msg_qbytes;
386: lmp->l_msg_lspid = bmp->msg_lspid;
387: lmp->l_msg_lrpid = bmp->msg_lrpid;
388: lmp->l_msg_stime = bmp->msg_stime;
389: lmp->l_msg_rtime = bmp->msg_rtime;
390: lmp->l_msg_ctime = bmp->msg_ctime;
391: }
392:
393: int
394: linux_msgsnd(p, v, retval)
395: struct proc *p;
396: void *v;
397: register_t *retval;
398: {
399: struct linux_sys_ipc_args /* {
400: syscallarg(int) what;
401: syscallarg(int) a1;
402: syscallarg(int) a2;
403: syscallarg(int) a3;
404: syscallarg(caddr_t) ptr;
405: } */ *uap = v;
406: struct sys_msgsnd_args bma;
407:
408: SCARG(&bma, msqid) = SCARG(uap, a1);
409: SCARG(&bma, msgp) = SCARG(uap, ptr);
410: SCARG(&bma, msgsz) = SCARG(uap, a2);
411: SCARG(&bma, msgflg) = SCARG(uap, a3);
412:
413: return sys_msgsnd(p, &bma, retval);
414: }
415:
416: int
417: linux_msgrcv(p, v, retval)
418: struct proc *p;
419: void *v;
420: register_t *retval;
421: {
422: struct linux_sys_ipc_args /* {
423: syscallarg(int) what;
424: syscallarg(int) a1;
425: syscallarg(int) a2;
426: syscallarg(int) a3;
427: syscallarg(caddr_t) ptr;
428: } */ *uap = v;
429: struct sys_msgrcv_args bma;
430: struct linux_msgrcv_msgarg kluge;
431: int error;
432:
433: if ((error = copyin(SCARG(uap, ptr), &kluge, sizeof kluge)))
434: return error;
435:
436: SCARG(&bma, msqid) = SCARG(uap, a1);
437: SCARG(&bma, msgp) = kluge.msg;
438: SCARG(&bma, msgsz) = SCARG(uap, a2);
439: SCARG(&bma, msgtyp) = kluge.type;
440: SCARG(&bma, msgflg) = SCARG(uap, a3);
441:
442: return sys_msgrcv(p, &bma, retval);
443: }
444:
445: int
446: linux_msgget(p, v, retval)
447: struct proc *p;
448: void *v;
449: register_t *retval;
450: {
451: struct linux_sys_ipc_args /* {
452: syscallarg(int) what;
453: syscallarg(int) a1;
454: syscallarg(int) a2;
455: syscallarg(int) a3;
456: syscallarg(caddr_t) ptr;
457: } */ *uap = v;
458: struct sys_msgget_args bma;
459:
460: SCARG(&bma, key) = (key_t)SCARG(uap, a1);
461: SCARG(&bma, msgflg) = SCARG(uap, a2);
462:
463: return sys_msgget(p, &bma, retval);
464: }
465:
466: int
467: linux_msgctl(p, v, retval)
468: struct proc *p;
469: void *v;
470: register_t *retval;
471: {
472: struct linux_sys_ipc_args /* {
473: syscallarg(int) what;
474: syscallarg(int) a1;
475: syscallarg(int) a2;
476: syscallarg(int) a3;
477: syscallarg(caddr_t) ptr;
478: } */ *uap = v;
479: struct sys_msgctl_args bma;
480: caddr_t umsgptr, sg;
481: struct linux_msqid_ds lm;
482: struct msqid_ds bm;
483: int error;
484:
485: SCARG(&bma, msqid) = SCARG(uap, a1);
486: SCARG(&bma, cmd) = SCARG(uap, a2);
487: switch (SCARG(uap, a2)) {
488: case LINUX_IPC_RMID:
489: return sys_msgctl(p, &bma, retval);
490: case LINUX_IPC_SET:
491: if ((error = copyin(SCARG(uap, ptr), (caddr_t)&lm, sizeof lm)))
492: return error;
493: linux_to_bsd_msqid_ds(&lm, &bm);
494: sg = stackgap_init(p->p_emul);
495: umsgptr = stackgap_alloc(&sg, sizeof bm);
496: if ((error = copyout((caddr_t)&bm, umsgptr, sizeof bm)))
497: return error;
498: SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
499: return sys_msgctl(p, &bma, retval);
500: case LINUX_IPC_STAT:
501: sg = stackgap_init(p->p_emul);
502: umsgptr = stackgap_alloc(&sg, sizeof (struct msqid_ds));
503: SCARG(&bma, buf) = (struct msqid_ds *)umsgptr;
504: if ((error = sys_msgctl(p, &bma, retval)))
505: return error;
506: if ((error = copyin(umsgptr, (caddr_t)&bm, sizeof bm)))
507: return error;
508: bsd_to_linux_msqid_ds(&bm, &lm);
509: return copyout((caddr_t)&lm, SCARG(uap, ptr), sizeof lm);
510: }
511: return EINVAL;
512: }
513: #endif /* SYSVMSG */
514:
515: #ifdef SYSVSHM
516: /*
517: * shmat(2). Very straightforward, except that Linux passes a pointer
518: * in which the return value is to be passed. This is subsequently
519: * handled by libc, apparently.
520: */
521: int
522: linux_shmat(p, v, retval)
523: struct proc *p;
524: void *v;
525: register_t *retval;
526: {
527: struct linux_sys_ipc_args /* {
528: syscallarg(int) what;
529: syscallarg(int) a1;
530: syscallarg(int) a2;
531: syscallarg(int) a3;
532: syscallarg(caddr_t) ptr;
533: } */ *uap = v;
534: struct sys_shmat_args bsa;
535: int error;
536:
537: SCARG(&bsa, shmid) = SCARG(uap, a1);
538: SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
539: SCARG(&bsa, shmflg) = SCARG(uap, a2);
540:
541: if ((error = sys_shmat(p, &bsa, retval)))
542: return error;
543:
544: if ((error = copyout(&retval[0], (caddr_t) SCARG(uap, a3),
545: sizeof retval[0])))
546: return error;
547:
548: retval[0] = 0;
549: return 0;
550: }
551:
552: /*
553: * shmdt(): this could have been mapped directly, if it wasn't for
554: * the extra indirection by the linux_ipc system call.
555: */
556: int
557: linux_shmdt(p, v, retval)
558: struct proc *p;
559: void *v;
560: register_t *retval;
561: {
562: struct linux_sys_ipc_args /* {
563: syscallarg(int) what;
564: syscallarg(int) a1;
565: syscallarg(int) a2;
566: syscallarg(int) a3;
567: syscallarg(caddr_t) ptr;
568: } */ *uap = v;
569: struct sys_shmdt_args bsa;
570:
571: SCARG(&bsa, shmaddr) = SCARG(uap, ptr);
572:
573: return sys_shmdt(p, &bsa, retval);
574: }
575:
576: /*
577: * Same story as shmdt.
578: */
579: int
580: linux_shmget(p, v, retval)
581: struct proc *p;
582: void *v;
583: register_t *retval;
584: {
585: struct linux_sys_ipc_args /* {
586: syscallarg(int) what;
587: syscallarg(int) a1;
588: syscallarg(int) a2;
589: syscallarg(int) a3;
590: syscallarg(caddr_t) ptr;
591: } */ *uap = v;
592: struct sys_shmget_args bsa;
593:
594: SCARG(&bsa, key) = SCARG(uap, a1);
595: SCARG(&bsa, size) = SCARG(uap, a2);
596: SCARG(&bsa, shmflg) = SCARG(uap, a3);
597:
598: SCARG(&bsa, shmflg) |= _SHM_RMLINGER;
599:
600: return sys_shmget(p, &bsa, retval);
601: }
602:
603: /*
604: * Convert between Linux and OpenBSD shmid_ds structures.
605: * The order of the fields is once again the difference, and
606: * we also need a place to store the internal data pointer
607: * in, which is unfortunately stored in this structure.
608: *
609: * We abuse a Linux internal field for that.
610: */
611: void
612: linux_to_bsd_shmid_ds(lsp, bsp)
613: struct linux_shmid_ds *lsp;
614: struct shmid_ds *bsp;
615: {
616:
617: linux_to_bsd_ipc_perm(&lsp->l_shm_perm, &bsp->shm_perm);
618: bsp->shm_segsz = lsp->l_shm_segsz;
619: bsp->shm_lpid = lsp->l_shm_lpid;
620: bsp->shm_cpid = lsp->l_shm_cpid;
621: bsp->shm_nattch = lsp->l_shm_nattch;
622: bsp->shm_atime = lsp->l_shm_atime;
623: bsp->shm_dtime = lsp->l_shm_dtime;
624: bsp->shm_ctime = lsp->l_shm_ctime;
625: bsp->shm_internal = lsp->l_private2; /* XXX Oh well. */
626: }
627:
628: void
629: bsd_to_linux_shmid_ds(bsp, lsp)
630: struct shmid_ds *bsp;
631: struct linux_shmid_ds *lsp;
632: {
633:
634: bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->l_shm_perm);
635: lsp->l_shm_segsz = bsp->shm_segsz;
636: lsp->l_shm_lpid = bsp->shm_lpid;
637: lsp->l_shm_cpid = bsp->shm_cpid;
638: lsp->l_shm_nattch = bsp->shm_nattch;
639: lsp->l_shm_atime = bsp->shm_atime;
640: lsp->l_shm_dtime = bsp->shm_dtime;
641: lsp->l_shm_ctime = bsp->shm_ctime;
642: lsp->l_private2 = bsp->shm_internal; /* XXX */
643: }
644:
645: /*
646: * shmctl. Not implemented (for now): IPC_INFO, SHM_INFO, SHM_STAT
647: * SHM_LOCK and SHM_UNLOCK are passed on, but currently not implemented
648: * by OpenBSD itself.
649: *
650: * The usual structure conversion and massaging is done.
651: */
652: int
653: linux_shmctl(p, v, retval)
654: struct proc *p;
655: void *v;
656: register_t *retval;
657: {
658: struct linux_sys_ipc_args /* {
659: syscallarg(int) what;
660: syscallarg(int) a1;
661: syscallarg(int) a2;
662: syscallarg(int) a3;
663: syscallarg(caddr_t) ptr;
664: } */ *uap = v;
665: int error;
666: caddr_t sg;
667: struct sys_shmctl_args bsa;
668: struct shmid_ds *bsp, bs;
669: struct linux_shmid_ds lseg;
670:
671: switch (SCARG(uap, a2)) {
672: case LINUX_IPC_STAT:
673: sg = stackgap_init(p->p_emul);
674: bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
675: SCARG(&bsa, shmid) = SCARG(uap, a1);
676: SCARG(&bsa, cmd) = IPC_STAT;
677: SCARG(&bsa, buf) = bsp;
678: if ((error = sys_shmctl(p, &bsa, retval)))
679: return error;
680: if ((error = copyin((caddr_t) bsp, (caddr_t) &bs, sizeof bs)))
681: return error;
682: bsd_to_linux_shmid_ds(&bs, &lseg);
683: return copyout((caddr_t) &lseg, SCARG(uap, ptr), sizeof lseg);
684: case LINUX_IPC_SET:
685: if ((error = copyin(SCARG(uap, ptr), (caddr_t) &lseg,
686: sizeof lseg)))
687: return error;
688: linux_to_bsd_shmid_ds(&lseg, &bs);
689: sg = stackgap_init(p->p_emul);
690: bsp = stackgap_alloc(&sg, sizeof (struct shmid_ds));
691: if ((error = copyout((caddr_t) &bs, (caddr_t) bsp, sizeof bs)))
692: return error;
693: SCARG(&bsa, shmid) = SCARG(uap, a1);
694: SCARG(&bsa, cmd) = IPC_SET;
695: SCARG(&bsa, buf) = bsp;
696: return sys_shmctl(p, &bsa, retval);
697: case LINUX_IPC_RMID:
698: case LINUX_SHM_LOCK:
699: case LINUX_SHM_UNLOCK:
700: SCARG(&bsa, shmid) = SCARG(uap, a1);
701: switch (SCARG(uap, a2)) {
702: case LINUX_IPC_RMID:
703: SCARG(&bsa, cmd) = IPC_RMID;
704: break;
705: case LINUX_SHM_LOCK:
706: SCARG(&bsa, cmd) = SHM_LOCK;
707: break;
708: case LINUX_SHM_UNLOCK:
709: SCARG(&bsa, cmd) = SHM_UNLOCK;
710: break;
711: }
712: SCARG(&bsa, buf) = NULL;
713: return sys_shmctl(p, &bsa, retval);
714: case LINUX_IPC_INFO:
715: case LINUX_SHM_STAT:
716: case LINUX_SHM_INFO:
717: default:
718: return EINVAL;
719: }
720: }
721: #endif /* SYSVSHM */
CVSweb