|
|
1.1 root 1: /*
2: * System V Compatible Shared Memory Device Driver
3: *
4: * This device driver provides System V compatible shared memory operations.
5: * Operations are performed through the shared memory device (/dev/shm).
6: * and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
7: * utilities.
8: *
9: * Author: Allan Cornish.
10: *
11: */
12:
13: #include <sys/coherent.h>
14: #include <sys/sched.h>
15: #include <sys/types.h>
16: #include <sys/uproc.h>
17: #include <errno.h>
18: #include <sys/stat.h>
19: #include <sys/con.h>
20: #include <sys/seg.h>
21: #include <sys/shm.h>
22: #include <stdlib.h>
23:
24: #ifndef EIDRM
25: #define EIDRM EDOM
26: #endif
27:
28:
29: extern unsigned NSHMID;
30: extern struct shmid_ds *shmids;
31: extern struct seg **shmsegs;
32:
33: /*
34: * Shmctl - Shared Memory Control Operations.
35: */
36:
37: ushmctl(shmid, cmd, buf)
38: #ifdef _I386
39: int shmid, cmd;
40: #else
41: unsigned shmid;
42: int cmd;
43: #endif
44: struct shmid_ds *buf;
45:
46: {
47: register struct shmid_ds *idp;
48: int ret = 0;
49:
50: if (u.u_error)
51: return -1;
52:
53: if (shmid >= NSHMID) {
54: u.u_error = EINVAL;
55: return -1;
56: }
57:
58: idp = &shmids[shmid];
59:
60: if ((idp->shm_perm.mode & IPC_ALLOC) == 0) {
61: u.u_error = EINVAL;
62: return -1;
63: }
64:
65: switch (cmd) {
66:
67: case IPC_STAT:
68: if ((ipcaccess(&idp->shm_perm) & SHM_R) == 0) {
69: u.u_error = EACCES;
70: return -1;
71: }
72: kucopy(idp, buf, sizeof(struct shmid_ds));
73: ret = 0;
74: break;
75:
76: case IPC_SET:
77: if ((u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid)) {
78: u.u_error = EPERM;
79: ret = -1;
80: break;
81: }
82: idp->shm_perm.uid = getuwd(&(buf->shm_perm.uid));
83: idp->shm_perm.gid = getuwd(&(buf->shm_perm.gid));
84: idp->shm_perm.mode &= ~0777;
85: idp->shm_perm.mode |= getuwd(&(buf->shm_perm.mode)) & 0777;
86: ret = 0;
87: break;
88:
89: case IPC_RMID:
90: if ((u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid)) {
91: u.u_error = EPERM;
92: ret = -1;
93: break;
94: }
95: idp->shm_perm.seq++;
96: kfree(shmsegs[shmid]);
97: idp->shm_perm.mode = 0;
98: ret = 0;
99: break;
100:
101: default:
102: u.u_error = EINVAL;
103: ret = -1;
104: }
105:
106: return ret;
107: }
108:
109: /*
110: * Shmget - Get Shared Memory Segment
111: */
112:
113: ushmget(skey, size, shmflg)
114:
115: key_t skey;
116: #ifdef _I386
117: int size, shmflg;
118: #else
119: unsigned size;
120: int shmflg;
121: #endif
122: {
123: register struct shmid_ds *idp;
124: struct shmid_ds *freeidp = 0;
125:
126: if (u.u_error)
127: return -1;
128:
129: for (idp = &shmids[NSHMID]; --idp >= shmids;) {
130:
131: if ((idp->shm_perm.mode & IPC_ALLOC) == 0) {
132:
133: if ((freeidp == 0) ||
134: (freeidp->shm_ctime > idp->shm_ctime))
135: freeidp = idp;
136: continue;
137: }
138:
139: #ifdef IPC_PRIVATE
140: if (skey == IPC_PRIVATE)
141: continue;
142: #endif
143:
144: if (skey == idp->shm_perm.key) { /* found! */
145:
146: if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) {
147:
148: u.u_error = EEXIST;
149: return -1;
150: }
151:
152: if ((idp->shm_perm.mode & shmflg) != (shmflg&0777)) {
153:
154: u.u_error = EACCES;
155: return -1;
156: }
157:
158: if (idp->shm_segsz < size) {
159:
160: u.u_error = EINVAL;
161: return -1;
162: }
163:
164: return idp - shmids;
165: }
166: }
167:
168: if (!(shmflg & IPC_CREAT)) {
169: u.u_error = ENOENT;
170: return -1;
171: }
172:
173: if (freeidp == 0) { /* error if no structs available */
174: u.u_error = ENOSPC;
175: return -1;
176: }
177:
178: idp = freeidp;
179:
180: /* allocate space for shared memory segment */
181: if ((shmsegs[idp - shmids] = kalloc((size_t) size)) == NULL){
182: u.u_error = ENOSPC;
183: return -1;
184: }
185:
186:
187: idp->shm_segsz = size;
188: idp->shm_atime = 0;
189: idp->shm_dtime = 0;
190: idp->shm_ctime = timer.t_time;
191: idp->shm_cpid = SELF->p_pid;
192: idp->shm_perm.cuid = idp->shm_perm.uid = u.u_uid;
193: idp->shm_perm.cgid = idp->shm_perm.gid = u.u_gid;
194: idp->shm_perm.mode = (shmflg & 0777) | IPC_ALLOC;
195: idp->shm_perm.key = skey;
196:
197: #ifdef IPC_PRIVATE
198: if (skey == IPC_PRIVATE)
199: idp->shm_perm.mode |= SHM_DEST;
200: #endif
201:
202: return idp - shmids;
203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.