Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sys / emulation / linux / linux_ipc.c
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/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.2 2003/06/17 04:28:19 dillon Exp $
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 <machine/../linux/linux.h>
40 #include <machine/../linux/linux_proto.h>
41 #include <compat/linux/linux_ipc.h>
42 #include <compat/linux/linux_util.h>
43
44 struct l_seminfo {
45         l_int semmap;
46         l_int semmni;
47         l_int semmns;
48         l_int semmnu;
49         l_int semmsl;
50         l_int semopm;
51         l_int semume;
52         l_int semusz;
53         l_int semvmx;
54         l_int semaem;
55 };
56
57 struct l_shminfo {
58         l_int shmmax;
59         l_int shmmin;
60         l_int shmmni;
61         l_int shmseg;
62         l_int shmall;
63 };
64
65 struct l_shm_info {
66         l_int used_ids;
67         l_ulong shm_tot;  /* total allocated shm */
68         l_ulong shm_rss;  /* total resident shm */
69         l_ulong shm_swp;  /* total swapped shm */
70         l_ulong swap_attempts;
71         l_ulong swap_successes;
72 };
73
74 struct l_ipc_perm {
75         l_key_t         key;
76         l_uid16_t       uid;
77         l_gid16_t       gid;
78         l_uid16_t       cuid;
79         l_gid16_t       cgid;
80         l_ushort        mode;
81         l_ushort        seq;
82 };
83
84 static void
85 linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp)
86 {
87     bpp->key = lpp->key;
88     bpp->uid = lpp->uid;
89     bpp->gid = lpp->gid;
90     bpp->cuid = lpp->cuid;
91     bpp->cgid = lpp->cgid;
92     bpp->mode = lpp->mode;
93     bpp->seq = lpp->seq;
94 }
95
96
97 static void
98 bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp)
99 {
100     lpp->key = bpp->key;
101     lpp->uid = bpp->uid;
102     lpp->gid = bpp->gid;
103     lpp->cuid = bpp->cuid;
104     lpp->cgid = bpp->cgid;
105     lpp->mode = bpp->mode;
106     lpp->seq = bpp->seq;
107 }
108
109 struct l_semid_ds {
110         struct l_ipc_perm       sem_perm;
111         l_time_t                sem_otime;
112         l_time_t                sem_ctime;
113         void                    *sem_base;
114         void                    *sem_pending;
115         void                    *sem_pending_last;
116         void                    *undo;
117         l_ushort                sem_nsems;
118 };
119
120 struct l_shmid_ds {
121         struct l_ipc_perm       shm_perm;
122         l_int                   shm_segsz;
123         l_time_t                shm_atime;
124         l_time_t                shm_dtime;
125         l_time_t                shm_ctime;
126         l_ushort                shm_cpid;
127         l_ushort                shm_lpid;
128         l_short                 shm_nattch;
129         l_ushort                private1;
130         void                    *private2;
131         void                    *private3;
132 };
133
134 static void
135 linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp)
136 {
137     linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm);
138     bsp->sem_otime = lsp->sem_otime;
139     bsp->sem_ctime = lsp->sem_ctime;
140     bsp->sem_nsems = lsp->sem_nsems;
141     bsp->sem_base = lsp->sem_base;
142 }
143
144 static void
145 bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp)
146 {
147         bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
148         lsp->sem_otime = bsp->sem_otime;
149         lsp->sem_ctime = bsp->sem_ctime;
150         lsp->sem_nsems = bsp->sem_nsems;
151         lsp->sem_base = bsp->sem_base;
152 }
153
154 static void
155 linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
156 {
157     linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
158     bsp->shm_segsz = lsp->shm_segsz;
159     bsp->shm_lpid = lsp->shm_lpid;
160     bsp->shm_cpid = lsp->shm_cpid;
161     bsp->shm_nattch = lsp->shm_nattch;
162     bsp->shm_atime = lsp->shm_atime;
163     bsp->shm_dtime = lsp->shm_dtime;
164     bsp->shm_ctime = lsp->shm_ctime;
165     bsp->shm_internal = lsp->private3;  /* this goes (yet) SOS */
166 }
167
168 static void
169 bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
170 {
171     bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm);
172     lsp->shm_segsz = bsp->shm_segsz;
173     lsp->shm_lpid = bsp->shm_lpid;
174     lsp->shm_cpid = bsp->shm_cpid;
175     lsp->shm_nattch = bsp->shm_nattch;
176     lsp->shm_atime = bsp->shm_atime;
177     lsp->shm_dtime = bsp->shm_dtime;
178     lsp->shm_ctime = bsp->shm_ctime;
179     lsp->private3 = bsp->shm_internal;  /* this goes (yet) SOS */
180 }
181
182 int
183 linux_semop(struct proc *p, struct linux_semop_args *args)
184 {
185         struct semop_args /* {
186         int     semid;
187         struct  sembuf *sops;
188         int             nsops;
189         } */ bsd_args;
190
191         bsd_args.semid = args->semid;
192         bsd_args.sops = (struct sembuf *)args->tsops;
193         bsd_args.nsops = args->nsops;
194         return semop(p, &bsd_args);
195 }
196
197 int
198 linux_semget(struct proc *p, struct linux_semget_args *args)
199 {
200         struct semget_args /* {
201         key_t   key;
202         int             nsems;
203         int             semflg;
204         } */ bsd_args;
205
206         bsd_args.key = args->key;
207         bsd_args.nsems = args->nsems;
208         bsd_args.semflg = args->semflg;
209         return semget(p, &bsd_args);
210 }
211
212 int
213 linux_semctl(struct proc *p, struct linux_semctl_args *args)
214 {
215         struct l_semid_ds linux_semid;
216         struct __semctl_args /* {
217                 int             semid;
218                 int             semnum;
219                 int             cmd;
220                 union semun     *arg;
221         } */ bsd_args;
222         struct l_seminfo linux_seminfo;
223         int error;
224         union semun *unptr;
225         caddr_t sg;
226
227         sg = stackgap_init();
228
229         /* Make sure the arg parameter can be copied in. */
230         unptr = stackgap_alloc(&sg, sizeof(union semun));
231         bcopy(&args->arg, unptr, sizeof(union semun));
232
233         bsd_args.semid = args->semid;
234         bsd_args.semnum = args->semnum;
235         bsd_args.arg = unptr;
236
237         switch (args->cmd) {
238         case LINUX_IPC_RMID:
239                 bsd_args.cmd = IPC_RMID;
240                 break;
241         case LINUX_GETNCNT:
242                 bsd_args.cmd = GETNCNT;
243                 break;
244         case LINUX_GETPID:
245                 bsd_args.cmd = GETPID;
246                 break;
247         case LINUX_GETVAL:
248                 bsd_args.cmd = GETVAL;
249                 break;
250         case LINUX_GETZCNT:
251                 bsd_args.cmd = GETZCNT;
252                 break;
253         case LINUX_SETVAL:
254                 bsd_args.cmd = SETVAL;
255                 break;
256         case LINUX_IPC_SET:
257                 bsd_args.cmd = IPC_SET;
258                 error = copyin((caddr_t)args->arg.buf, &linux_semid,
259                     sizeof(linux_semid));
260                 if (error)
261                         return (error);
262                 unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
263                 linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
264                 return __semctl(p, &bsd_args);
265         case LINUX_IPC_STAT:
266                 bsd_args.cmd = IPC_STAT;
267                 unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
268                 error = __semctl(p, &bsd_args);
269                 if (error)
270                         return error;
271                 p->p_retval[0] = IXSEQ_TO_IPCID(bsd_args.semid, 
272                                                         unptr->buf->sem_perm);
273                 bsd_to_linux_semid_ds(unptr->buf, &linux_semid);
274                 return copyout(&linux_semid, (caddr_t)args->arg.buf,
275                                             sizeof(linux_semid));
276         case LINUX_IPC_INFO:
277         case LINUX_SEM_INFO:
278                 error = copyin((caddr_t)args->arg.buf, &linux_seminfo, 
279                                                 sizeof(linux_seminfo) );
280                 if (error)
281                         return error;
282                 bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) );
283 /* XXX BSD equivalent?
284 #define used_semids 10
285 #define used_sems 10
286                 linux_seminfo.semusz = used_semids;
287                 linux_seminfo.semaem = used_sems;
288 */
289                 error = copyout((caddr_t)&linux_seminfo, (caddr_t)args->arg.buf,
290                                                 sizeof(linux_seminfo) );
291                 if (error)
292                         return error;
293                 p->p_retval[0] = seminfo.semmni;
294                 return 0;                       /* No need for __semctl call */
295         case LINUX_GETALL:
296                 /* FALLTHROUGH */
297         case LINUX_SETALL:
298                 /* FALLTHROUGH */
299         default:
300                 uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd);
301                 return EINVAL;
302         }
303         return __semctl(p, &bsd_args);
304 }
305
306 int
307 linux_msgsnd(struct proc *p, struct linux_msgsnd_args *args)
308 {
309     struct msgsnd_args /* {
310         int     msqid;   
311         void    *msgp;   
312         size_t  msgsz;   
313         int     msgflg; 
314     } */ bsd_args;
315
316     bsd_args.msqid = args->msqid;
317     bsd_args.msgp = args->msgp;
318     bsd_args.msgsz = args->msgsz;
319     bsd_args.msgflg = args->msgflg;
320     return msgsnd(p, &bsd_args);
321 }
322
323 int
324 linux_msgrcv(struct proc *p, struct linux_msgrcv_args *args)
325 {
326     struct msgrcv_args /* {     
327         int     msqid;   
328         void    *msgp;   
329         size_t  msgsz;   
330         long    msgtyp; 
331         int     msgflg; 
332     } */ bsd_args; 
333
334     bsd_args.msqid = args->msqid;
335     bsd_args.msgp = args->msgp;
336     bsd_args.msgsz = args->msgsz;
337     bsd_args.msgtyp = 0; /* XXX - args->msgtyp; */
338     bsd_args.msgflg = args->msgflg;
339     return msgrcv(p, &bsd_args);
340 }
341
342 int
343 linux_msgget(struct proc *p, struct linux_msgget_args *args)
344 {
345     struct msgget_args /* {
346         key_t   key;
347         int     msgflg;
348     } */ bsd_args;
349
350     bsd_args.key = args->key;
351     bsd_args.msgflg = args->msgflg;
352     return msgget(p, &bsd_args);
353 }
354
355 int
356 linux_msgctl(struct proc *p, struct linux_msgctl_args *args)
357 {
358     struct msgctl_args /* {
359         int     msqid; 
360         int     cmd;
361         struct  msqid_ds *buf;
362     } */ bsd_args;
363     int error;
364
365     bsd_args.msqid = args->msqid;
366     bsd_args.cmd = args->cmd;
367     bsd_args.buf = (struct msqid_ds *)args->buf;
368     error = msgctl(p, &bsd_args);
369     return ((args->cmd == LINUX_IPC_RMID && error == EINVAL) ? 0 : error);
370 }
371
372 int
373 linux_shmat(struct proc *p, struct linux_shmat_args *args)
374 {
375     struct shmat_args /* {
376         int shmid;
377         void *shmaddr;
378         int shmflg;
379     } */ bsd_args;
380     int error;
381
382     bsd_args.shmid = args->shmid;
383     bsd_args.shmaddr = args->shmaddr;
384     bsd_args.shmflg = args->shmflg;
385     if ((error = shmat(p, &bsd_args)))
386         return error;
387 #ifdef __i386__
388     if ((error = copyout(p->p_retval, (caddr_t)args->raddr, sizeof(l_ulong))))
389         return error;
390     p->p_retval[0] = 0;
391 #endif
392     return 0;
393 }
394
395 int
396 linux_shmdt(struct proc *p, struct linux_shmdt_args *args)
397 {
398     struct shmdt_args /* {
399         void *shmaddr;
400     } */ bsd_args;
401
402     bsd_args.shmaddr = args->shmaddr;
403     return shmdt(p, &bsd_args);
404 }
405
406 int
407 linux_shmget(struct proc *p, struct linux_shmget_args *args)
408 {
409     struct shmget_args /* {
410         key_t key;
411         int size;
412         int shmflg;
413     } */ bsd_args;
414
415     bsd_args.key = args->key;
416     bsd_args.size = args->size;
417     bsd_args.shmflg = args->shmflg;
418     return shmget(p, &bsd_args);
419 }
420
421 int
422 linux_shmctl(struct proc *p, struct linux_shmctl_args *args)
423 {
424     struct l_shmid_ds linux_shmid;
425     struct shmctl_args /* {
426         int shmid;
427         int cmd;
428         struct shmid_ds *buf;
429     } */ bsd_args;
430     int error;
431     caddr_t sg = stackgap_init();
432
433     switch (args->cmd) {
434     case LINUX_IPC_STAT:
435         bsd_args.shmid = args->shmid;
436         bsd_args.cmd = IPC_STAT;
437         bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
438         if ((error = shmctl(p, &bsd_args)))
439             return error;
440         bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
441         return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
442
443     case LINUX_IPC_SET:
444         if ((error = copyin((caddr_t)args->buf, &linux_shmid,
445                 sizeof(linux_shmid))))
446             return error;
447         bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
448         linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
449         bsd_args.shmid = args->shmid;
450         bsd_args.cmd = IPC_SET;
451         return shmctl(p, &bsd_args);
452
453     case LINUX_IPC_RMID:
454         bsd_args.shmid = args->shmid;
455         bsd_args.cmd = IPC_RMID;
456         if (args->buf == NULL)
457             bsd_args.buf = NULL;
458         else {
459             if ((error = copyin((caddr_t)args->buf, &linux_shmid, 
460                                 sizeof(linux_shmid))))
461                 return error;
462             bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
463             linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
464         }
465         return shmctl(p, &bsd_args);
466
467     case LINUX_IPC_INFO:
468     case LINUX_SHM_STAT:
469     case LINUX_SHM_INFO:
470     case LINUX_SHM_LOCK:
471     case LINUX_SHM_UNLOCK:
472     default:
473         uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd);
474         return EINVAL;
475     }
476 }