|
|
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.