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

/* $Header: /var/lib/cvsd/repos/coherent/coherent/d/PS2_KERNEL/io.286/shm.c,v 1.1.1.1 2019/05/29 04:56:39 root Exp $
 *
 *	The  information  contained herein  is a trade secret  of INETCO
 *	Systems, and is confidential information.   It is provided under
 *	a license agreement,  and may be copied or disclosed  only under
 *	the terms of that agreement.   Any reproduction or disclosure of
 *	this  material  without  the express  written  authorization  of
 *	INETCO Systems or persuant to the license agreement is unlawful.
 *
 *	Copyright (c) 1985, 1984
 *	An unpublished work by INETCO Systems, Ltd.
 *	All rights reserved.
 */

/*
 * 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, INETCO Systems Ltd., Sep 1984
 *
 * $Log: shm.c,v $
 * Revision 1.1.1.1  2019/05/29 04:56:39  root
 * coherent
 *
 * Revision 1.1  92/07/17  15:24:46  bin
 * Initial revision
 * 
 * Revision 2.1	88/09/03  13:12:17	src
 * *** empty log message ***
 * 
 * Revision 1.1	88/03/24  17:06:32	src
 * Initial revision
 * 
 * 85/10/16	Allan Cornish
 * Driver split into shmcon.c, shm.c [driver implementation, System V shm].
 *
 * 85/07/22	Allan Cornish
 * Shmget, shmctl now return immediately if u.u_error is set.
 *
 * 85/07/19	Allan Cornish
 * Separation of io_seek into shmid and off improved through type casting.
 * Errno set to EFAULT if fucopy() or ufcopy() report no bytes transferred.
 * This would occur if an user address fault occurred.
 *
 * 85/07/03	Allan Cornish
 * Replaced use of EDOM with EIDRM.
 * Replaced shmaccess() by calls to ipcaccess(), increasing shared ipc code.
 * Eliminated shmlock() and shmunlock(), as shared memory use is synchronous.
 */

#include <coherent.h>
#include <sched.h>
#include <types.h>
#include <errno.h>
#include <stat.h>
#include <con.h>
#include <seg.h>
#include <shm.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 )

unsigned shmid;
int cmd;
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++;
		sfree(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;
unsigned size;
int shmflg;

{
	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 ) {
		u.u_error = ENOSPC;
		return -1;
	}

	idp = freeidp;

	if ((shmsegs[idp - shmids] = salloc((size_t) size, SFNSWP)) == 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.