File:  [MW Coherent from dump] / coherent / b / kernel / io.386 / shm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * System V Compatible Shared Memory Device Driver
 *
 *	This device driver provides System V compatible shared memory operations.
 *	Operations are performed through the shared memory device (/dev/shm).
 *	and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
 *	utilities.
 *
 *	Author: Allan Cornish.
 *
 */

#include <sys/coherent.h>
#include <sys/sched.h>
#include <sys/types.h>
#include <sys/uproc.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/con.h>
#include <sys/seg.h>
#include <sys/shm.h>
#include <stdlib.h>

#ifndef	EIDRM
#define	EIDRM	EDOM
#endif


extern	unsigned NSHMID;
extern	struct shmid_ds *shmids;
extern	struct seg **shmsegs;

/*
 * Shmctl - Shared Memory Control Operations.
 */

ushmctl(shmid, cmd, buf)
#ifdef _I386
int shmid, cmd;
#else
unsigned shmid;
int cmd;
#endif
struct shmid_ds *buf;

{
	register struct shmid_ds *idp;
	int ret = 0;

	if (u.u_error)
		return -1;

	if (shmid >= NSHMID) {
		u.u_error = EINVAL;
		return -1;
	}

	idp = &shmids[shmid];

	if ((idp->shm_perm.mode & IPC_ALLOC) == 0) {
		u.u_error = EINVAL;
		return -1;
	}

	switch (cmd) {

	case IPC_STAT:
		if ((ipcaccess(&idp->shm_perm) & SHM_R) == 0) {
			u.u_error = EACCES;
			return -1;
		}
		kucopy(idp, buf, sizeof(struct shmid_ds));
		ret = 0;
		break;

	case IPC_SET:
		if ((u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid)) {
			u.u_error = EPERM;
			ret = -1;
			break;
		}
		idp->shm_perm.uid   = getuwd(&(buf->shm_perm.uid));
		idp->shm_perm.gid   = getuwd(&(buf->shm_perm.gid));
		idp->shm_perm.mode &= ~0777;
		idp->shm_perm.mode |= getuwd(&(buf->shm_perm.mode)) & 0777;
		ret = 0;
		break;

	case IPC_RMID:
		if ((u.u_uid != 0) && (u.u_uid != idp->shm_perm.uid)) {
			u.u_error = EPERM;
			ret = -1;
			break;
		}
		idp->shm_perm.seq++;
		kfree(shmsegs[shmid]);
		idp->shm_perm.mode = 0;
		ret = 0;
		break;

	default:
		u.u_error = EINVAL;
		ret = -1;
	}

	return ret;
}

/*
 * Shmget - Get Shared Memory Segment
 */

ushmget(skey, size, shmflg)

key_t skey;
#ifdef _I386
int size, shmflg;
#else
unsigned size;
int shmflg;
#endif
{
	register struct shmid_ds *idp;
	struct shmid_ds *freeidp = 0;

	if (u.u_error)
		return -1;

	for (idp = &shmids[NSHMID]; --idp >= shmids;) {

		if ((idp->shm_perm.mode & IPC_ALLOC) == 0) {

			if ((freeidp == 0) ||
			    (freeidp->shm_ctime > idp->shm_ctime))
				freeidp = idp;
			continue;
		}

#ifdef	IPC_PRIVATE
		if (skey == IPC_PRIVATE)
			continue;
#endif

		if (skey == idp->shm_perm.key) {		/* found! */

			if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) {

				u.u_error = EEXIST;
				return -1;
			}

			if ((idp->shm_perm.mode & shmflg) != (shmflg&0777)) {

				u.u_error = EACCES;
				return -1;
			}

			if (idp->shm_segsz < size) {

				u.u_error = EINVAL;
				return -1;
			}

			return idp - shmids;
		}
	}

	if (!(shmflg & IPC_CREAT)) {
		u.u_error = ENOENT;
		return -1;
	}

	if (freeidp == 0) { /* error if no structs available */
		u.u_error = ENOSPC;
		return -1;
	}

	idp = freeidp;

	/* allocate space for shared memory segment */
	if ((shmsegs[idp - shmids] = kalloc((size_t) size)) == NULL){
		u.u_error = ENOSPC;
		return -1;
	}


	idp->shm_segsz = size;
	idp->shm_atime = 0;
	idp->shm_dtime = 0;
	idp->shm_ctime = timer.t_time;
	idp->shm_cpid  = SELF->p_pid;
	idp->shm_perm.cuid = idp->shm_perm.uid = u.u_uid;
	idp->shm_perm.cgid = idp->shm_perm.gid = u.u_gid;
	idp->shm_perm.mode = (shmflg & 0777) | IPC_ALLOC;
	idp->shm_perm.key  = skey;

#ifdef	IPC_PRIVATE
	if (skey == IPC_PRIVATE)
		idp->shm_perm.mode |= SHM_DEST;
#endif

	return idp - shmids;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.