Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $ |
2 | * ipc.c: Solaris IPC emulation | |
3 | * | |
4 | * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | |
5 | */ | |
6 | ||
7 | #include <linux/kernel.h> | |
8 | #include <linux/types.h> | |
1da177e4 LT |
9 | #include <linux/wait.h> |
10 | #include <linux/mm.h> | |
11 | #include <linux/shm.h> | |
12 | #include <linux/sem.h> | |
13 | #include <linux/msg.h> | |
cba4fbbf | 14 | #include <linux/ipc.h> |
1da177e4 LT |
15 | |
16 | #include <asm/uaccess.h> | |
17 | #include <asm/string.h> | |
1da177e4 LT |
18 | |
19 | #include "conv.h" | |
20 | ||
21 | struct solaris_ipc_perm { | |
22 | s32 uid; | |
23 | s32 gid; | |
24 | s32 cuid; | |
25 | s32 cgid; | |
26 | u32 mode; | |
27 | u32 seq; | |
28 | int key; | |
29 | s32 pad[4]; | |
30 | }; | |
31 | ||
32 | struct solaris_shmid_ds { | |
33 | struct solaris_ipc_perm shm_perm; | |
34 | int shm_segsz; | |
35 | u32 shm_amp; | |
36 | unsigned short shm_lkcnt; | |
37 | char __padxx[2]; | |
38 | s32 shm_lpid; | |
39 | s32 shm_cpid; | |
40 | u32 shm_nattch; | |
41 | u32 shm_cnattch; | |
42 | s32 shm_atime; | |
43 | s32 shm_pad1; | |
44 | s32 shm_dtime; | |
45 | s32 shm_pad2; | |
46 | s32 shm_ctime; | |
47 | s32 shm_pad3; | |
48 | unsigned short shm_cv; | |
49 | char shm_pad4[2]; | |
50 | u32 shm_sptas; | |
51 | s32 shm_pad5[2]; | |
52 | }; | |
53 | ||
54 | asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3) | |
55 | { | |
56 | int (*sys_ipc)(unsigned,int,int,unsigned long,void __user *,long) = | |
57 | (int (*)(unsigned,int,int,unsigned long,void __user *,long))SYS(ipc); | |
58 | mm_segment_t old_fs; | |
59 | unsigned long raddr; | |
60 | int ret; | |
61 | ||
62 | switch (cmd) { | |
63 | case 0: /* shmat */ | |
64 | old_fs = get_fs(); | |
65 | set_fs(KERNEL_DS); | |
66 | ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, A(arg2), 0); | |
67 | set_fs(old_fs); | |
68 | if (ret >= 0) return (u32)raddr; | |
69 | else return ret; | |
70 | case 1: /* shmctl */ | |
71 | switch (arg2) { | |
72 | case 3: /* SHM_LOCK */ | |
73 | case 4: /* SHM_UNLOCK */ | |
74 | return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0); | |
75 | case 10: /* IPC_RMID */ | |
76 | return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0); | |
77 | case 11: /* IPC_SET */ | |
78 | { | |
79 | struct shmid_ds s; | |
80 | struct solaris_shmid_ds __user *p = A(arg3); | |
81 | ||
82 | if (get_user (s.shm_perm.uid, &p->shm_perm.uid) || | |
83 | __get_user (s.shm_perm.gid, &p->shm_perm.gid) || | |
84 | __get_user (s.shm_perm.mode, &p->shm_perm.mode)) | |
85 | return -EFAULT; | |
86 | old_fs = get_fs(); | |
87 | set_fs(KERNEL_DS); | |
88 | ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); | |
89 | set_fs(old_fs); | |
90 | return ret; | |
91 | } | |
92 | case 12: /* IPC_STAT */ | |
93 | { | |
94 | struct shmid_ds s; | |
95 | struct solaris_shmid_ds __user *p = A(arg3); | |
96 | ||
97 | old_fs = get_fs(); | |
98 | set_fs(KERNEL_DS); | |
99 | ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); | |
100 | set_fs(old_fs); | |
101 | if (put_user (s.shm_perm.uid, &(p->shm_perm.uid)) || | |
102 | __put_user (s.shm_perm.gid, &(p->shm_perm.gid)) || | |
103 | __put_user (s.shm_perm.cuid, &(p->shm_perm.cuid)) || | |
104 | __put_user (s.shm_perm.cgid, &(p->shm_perm.cgid)) || | |
105 | __put_user (s.shm_perm.mode, &(p->shm_perm.mode)) || | |
106 | __put_user (s.shm_perm.seq, &(p->shm_perm.seq)) || | |
107 | __put_user (s.shm_perm.key, &(p->shm_perm.key)) || | |
108 | __put_user (s.shm_segsz, &(p->shm_segsz)) || | |
109 | __put_user (s.shm_lpid, &(p->shm_lpid)) || | |
110 | __put_user (s.shm_cpid, &(p->shm_cpid)) || | |
111 | __put_user (s.shm_nattch, &(p->shm_nattch)) || | |
112 | __put_user (s.shm_atime, &(p->shm_atime)) || | |
113 | __put_user (s.shm_dtime, &(p->shm_dtime)) || | |
114 | __put_user (s.shm_ctime, &(p->shm_ctime))) | |
115 | return -EFAULT; | |
116 | return ret; | |
117 | } | |
118 | default: return -EINVAL; | |
119 | } | |
120 | case 2: /* shmdt */ | |
121 | return sys_ipc(SHMDT, 0, 0, 0, A(arg1), 0); | |
122 | case 3: /* shmget */ | |
123 | return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0); | |
124 | } | |
125 | return -EINVAL; | |
126 | } |