File:  [Atari MiNT] / MiNT / src / shmfs.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:58:51 2018 UTC (8 years, 1 month ago) by root
Branches: mint, MAIN
CVS tags: mint112, HEAD
MiNT 1.12

/*

Copyright 1992,1993 Eric R. Smith.

Copyright 1993,1994 Atari Corporation.

All rights reserved.

 */



/* Shared memory file system */



#include "mint.h"





static long	ARGS_ON_STACK shm_root	P_((int drv, fcookie *fc));

static long	ARGS_ON_STACK shm_creat	P_((fcookie *dir, const char *name, unsigned mode,

				    int attrib, fcookie *fc));

static long	ARGS_ON_STACK shm_lookup	P_((fcookie *dir, const char *name, fcookie *fc));

static long	ARGS_ON_STACK shm_getxattr	P_((fcookie *fc, XATTR *xattr));

static long	ARGS_ON_STACK shm_chattr	P_((fcookie *fc, int attrib));

static long	ARGS_ON_STACK shm_chown	P_((fcookie *fc, int uid, int gid));

static long	ARGS_ON_STACK shm_chmode	P_((fcookie *fc, unsigned mode));

static long	ARGS_ON_STACK shm_rmdir	P_((fcookie *dir, const char *name));

static long	ARGS_ON_STACK shm_remove	P_((fcookie *dir, const char *name));

static long	ARGS_ON_STACK shm_getname	P_((fcookie *root, fcookie *dir,

						    char *pathname, int size));

static long	ARGS_ON_STACK shm_rename	P_((fcookie *olddir, char *oldname,

				    fcookie *newdir, const char *newname));

static long	ARGS_ON_STACK shm_opendir	P_((DIR *dirh, int flags));

static long	ARGS_ON_STACK shm_readdir	P_((DIR *dirh, char *nm, int nmlen, fcookie *));

static long	ARGS_ON_STACK shm_rewinddir	P_((DIR *dirh));

static long	ARGS_ON_STACK shm_closedir	P_((DIR *dirh));

static long	ARGS_ON_STACK shm_pathconf	P_((fcookie *dir, int which));

static long	ARGS_ON_STACK shm_dfree	P_((fcookie *dir, long *buf));

static DEVDRV *	ARGS_ON_STACK shm_getdev	P_((fcookie *fc, long *devsp));



static long	ARGS_ON_STACK shm_open	P_((FILEPTR *f));

static long	ARGS_ON_STACK shm_write	P_((FILEPTR *f, const char *buf, long bytes));

static long	ARGS_ON_STACK shm_read	P_((FILEPTR *f, char *buf, long bytes));

static long	ARGS_ON_STACK shm_lseek	P_((FILEPTR *f, long where, int whence));

static long	ARGS_ON_STACK shm_ioctl	P_((FILEPTR *f, int mode, void *buf));

static long	ARGS_ON_STACK shm_datime	P_((FILEPTR *f, short *time, int rwflag));

static long	ARGS_ON_STACK shm_close	P_((FILEPTR *f, int pid));



/* dummy routines from biosfs.c */

extern long	ARGS_ON_STACK null_select	P_((FILEPTR *f, long p, int mode));

extern void	ARGS_ON_STACK null_unselect	P_((FILEPTR *f, long p, int mode));



static short shmtime, shmdate;



#define SHMNAME_MAX 15



typedef struct shmfile {

	struct shmfile *next;

	char filename[SHMNAME_MAX+1];

	int uid, gid;

	short time, date;

	unsigned mode;

	int inuse;

	MEMREGION *reg;

} SHMFILE;



SHMFILE *shmroot = 0;



DEVDRV shm_device = {

	shm_open, shm_write, shm_read, shm_lseek, shm_ioctl, shm_datime,

	shm_close, null_select, null_unselect

};



FILESYS shm_filesys = {

	(FILESYS *)0,

	FS_LONGPATH,

	shm_root,

	shm_lookup, shm_creat, shm_getdev, shm_getxattr,

	shm_chattr, shm_chown, shm_chmode,

	nomkdir, shm_rmdir, shm_remove, shm_getname, shm_rename,

	shm_opendir, shm_readdir, shm_rewinddir, shm_closedir,

	shm_pathconf, shm_dfree,

	nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,

	nofscntl, nodskchng

};



long ARGS_ON_STACK 

shm_root(drv, fc)

	int drv;

	fcookie *fc;

{

	if ((unsigned)drv == SHMDRV) {

		fc->fs = &shm_filesys;

		fc->dev = drv;

		fc->index = 0L;

		return 0;

	}

	fc->fs = 0;

	return EINTRN;

}



static long ARGS_ON_STACK 

shm_lookup(dir, name, fc)

	fcookie *dir;

	const char *name;

	fcookie *fc;

{

	SHMFILE *s;



	if (dir->index != 0) {

		DEBUG(("shm_lookup: bad directory"));

		return EPTHNF;

	}



/* special case: an empty name in a directory means that directory */

/* so does "." */

	if (!*name || (name[0] == '.' && name[1] == 0)) {

		*fc = *dir;

		return 0;

	}



/* another special case: ".." could be a mount point */

	if (!strcmp(name, "..")) {

		*fc = *dir;

		return EMOUNT;

	}



	for (s = shmroot; s; s = s->next) {

		if (!stricmp(s->filename,name))

			break;

	}



	if (!s) {

		DEBUG(("shm_lookup: name not found"));

		return EFILNF;

	} else {

		fc->index = (long)s;

		fc->fs = &shm_filesys;

		fc->dev = SHMDRV;

	}

	return 0;

}



static long ARGS_ON_STACK 

shm_getxattr(fc, xattr)

	fcookie *fc;

	XATTR *xattr;

{

	SHMFILE *s;



	xattr->blksize = 1;

	if (fc->index == 0) {

		/* the root directory */

		xattr->index = 0;

		xattr->dev = xattr->rdev = SHMDRV;

		xattr->nlink = 1;

		xattr->uid = xattr->gid = 0;

		xattr->size = xattr->nblocks = 0;

		xattr->mtime = xattr->atime = xattr->ctime = shmtime;

		xattr->mdate = xattr->adate = xattr->cdate = shmdate;

		xattr->mode = S_IFDIR | DEFAULT_DIRMODE;

		xattr->attr = FA_DIR;

		return 0;

	}



	s = (SHMFILE *)fc->index;

	xattr->index = (long) s;

	xattr->dev = SHMDRV;

	xattr->rdev = PROC_RDEV_BASE | 0;

	xattr->uid = s->uid; xattr->gid = s->gid;

	if (s->reg) {

		xattr->size = xattr->nblocks = s->reg->len;

		xattr->nlink = s->reg->links + 1;

	 } else {

		xattr->size = xattr->nblocks = 0;

		xattr->nlink = 1;

	}

	xattr->mtime = xattr->ctime = xattr->atime = s->time;

	xattr->mdate = xattr->cdate = xattr->adate = s->date;

	xattr->mode = s->mode;

	xattr->attr = (s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ? 0 : 

			FA_RDONLY;

	return 0;

}



static long ARGS_ON_STACK 

shm_chattr(fc, attrib)

	fcookie *fc;

	int attrib;

{

	SHMFILE *s;



	s = (SHMFILE *)fc->index;

	if (!s) return EACCDN;



	if (attrib & FA_RDONLY) {

		s->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);

	} else if ( !(s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ) {

		s->mode |= (S_IWUSR|S_IWGRP|S_IWOTH);

	}

	return 0;

}



static long ARGS_ON_STACK 

shm_chown(fc, uid, gid)

	fcookie *fc;

	int uid, gid;

{

	SHMFILE *s;



	s = (SHMFILE *)fc->index;

	if (!s)

		return EACCDN;

	s->uid = uid;

	s->gid = gid;

	return 0;

}



static long ARGS_ON_STACK 

shm_chmode(fc, mode)

	fcookie *fc;

	unsigned mode;

{

	SHMFILE *s;



	s = (SHMFILE *)fc->index;

	if (!s)

		return EINVFN;

	s->mode = mode;

	return 0;

}



static long ARGS_ON_STACK 

shm_rmdir(dir, name)

	fcookie *dir;

	const char *name;

{

	UNUSED(dir); UNUSED(name);



	return EPTHNF;

}



static long ARGS_ON_STACK 

shm_remove(dir, name)

	fcookie *dir;

	const char *name;

{

	SHMFILE *s, **old;



	if (dir->index != 0)

		return EPTHNF;



	old = &shmroot;

	for (s = shmroot; s; s = s->next) {

		if (!stricmp(s->filename, name))

			break;

		old = &s->next;

	}

	if (!s)

		return EFILNF;

	if (s->inuse)

		return EACCDN;

	*old = s->next;



	s->reg->links--;

	if (s->reg->links <= 0) {

		free_region(s->reg);

	}

	kfree(s);

	shmtime = timestamp;

	shmdate = datestamp;

	return 0;

}



static long ARGS_ON_STACK 

shm_getname(root, dir, pathname, size)

	fcookie *root, *dir; char *pathname;

	int size;

{

	UNUSED(root); UNUSED(dir);



/* BUG: 'size' should be used in a more meaningful way */

	if (size <= 0) return ERANGE;

	*pathname = 0;

	return 0;

}



static long ARGS_ON_STACK 

shm_rename(olddir, oldname, newdir, newname)

	fcookie *olddir;

	char *oldname;

	fcookie *newdir;

	const char *newname;

{

	SHMFILE *s;



	if (olddir->index != 0 || newdir->index != 0)

		return EPTHNF;



/* verify that "newname" doesn't exist */

	for (s = shmroot; s; s = s->next)

		if (!stricmp(s->filename, newname))

			return EACCDN;



	for (s = shmroot; s; s = s->next)

		if (!stricmp(s->filename, oldname))

			break;

	if (!s)

		return EFILNF;



	strncpy(s->filename, newname, SHMNAME_MAX);

	shmtime = timestamp;

	shmdate = datestamp;

	return 0;

}



static long ARGS_ON_STACK 

shm_opendir(dirh, flags)

	DIR *dirh;

	int flags;

{

	UNUSED(flags);



	dirh->index = 0;

	return 0;

}



static long ARGS_ON_STACK 

shm_readdir(dirh, name, namelen, fc)

	DIR *dirh;

	char *name;

	int namelen;

	fcookie *fc;

{

	int i;

	int giveindex = (dirh->flags == 0);

	SHMFILE *s;



	s = shmroot;

	i = dirh->index++;

	while (i > 0 && s != 0) {

		s = s->next;

		--i;

	}

	if (!s)

		return ENMFIL;



	fc->index = (long)s;

	fc->fs = &shm_filesys;

	fc->dev = SHMDRV;



	if (giveindex) {

		namelen -= (int)sizeof(long);

		if (namelen <= 0) return ERANGE;

		*((long *)name) = (long)s;

		name += sizeof(long);

	}

	if (namelen < strlen(s->filename))

		return ENAMETOOLONG;

	strcpy(name, s->filename);

	return 0;

}



static long ARGS_ON_STACK 

shm_rewinddir(dirh)

	DIR *dirh;

{

	dirh->index = 0;

	return 0;

}



static long ARGS_ON_STACK 

shm_closedir(dirh)

	DIR *dirh;

{

	UNUSED(dirh);

	return 0;

}



static long ARGS_ON_STACK 

shm_pathconf(dir, which)

	fcookie *dir;

	int which;

{

	UNUSED(dir);



	switch(which) {

	case -1:

		return DP_MAXREQ;

	case DP_IOPEN:

		return UNLIMITED;	/* no internal limit on open files */

	case DP_MAXLINKS:

		return 1;		/* we don't have hard links */

	case DP_PATHMAX:

		return PATH_MAX;	/* max. path length */

	case DP_NAMEMAX:

		return SHMNAME_MAX;	/* max. length of individual name */

	case DP_ATOMIC:

		return UNLIMITED;	/* all writes are atomic */

	case DP_TRUNC:

		return DP_AUTOTRUNC;	/* file names are truncated */

	case DP_CASE:

		return DP_CASEINSENS;	/* case preserved, but ignored */

	case DP_MODEATTR:

		return (0777L << 8)|

				DP_FT_DIR|DP_FT_MEM;

	case DP_XATTRFIELDS:

		return DP_INDEX|DP_DEV|DP_NLINK|DP_UID|DP_GID|DP_BLKSIZE|DP_SIZE|

				DP_NBLOCKS|DP_MTIME;

	default:

		return EINVFN;

	}

}



static long ARGS_ON_STACK 

shm_dfree(dir, buf)

	fcookie *dir;

	long *buf;

{

	long size;

/* "sector" size is the size of the smallest amount of memory that can be

   allocated. see mem.h for the definition of ROUND

 */

	long secsiz = ROUND(1);



	UNUSED(dir);



	size = tot_rsize(core, 0) + tot_rsize(alt, 0);

	*buf++ = size/secsiz;			/* number of free clusters */

	size = tot_rsize(core, 1) + tot_rsize(alt, 1);

	*buf++ = size/secsiz;			/* total number of clusters */

	*buf++ = secsiz;			/* sector size (bytes) */

	*buf = 1;				/* cluster size (in sectors) */

	return 0;

}



static DEVDRV * ARGS_ON_STACK 

shm_getdev(fc, devsp)

	fcookie *fc;

	long *devsp;

{

	SHMFILE *s;



	s = (SHMFILE *)fc->index;



	*devsp = (long)s;

	return &shm_device;

}



/*

 * create a shared memory region

 */



static long ARGS_ON_STACK 

shm_creat(dir, name, mode, attrib, fc)

	fcookie *dir;

	const char *name;

	unsigned mode;

	int attrib;

	fcookie *fc;

{

	SHMFILE *s;



	UNUSED(attrib);

/*

 * see if the name already exists

 */

	for (s = shmroot; s; s = s->next) {

		if (!stricmp(s->filename, name)) {

			DEBUG(("shm_creat: file exists"));

			return EACCDN;

		}

	}



	s = (SHMFILE *)kmalloc(SIZEOF(SHMFILE));

	if (!s)

		return ENSMEM;



	s->inuse = 0;

	strncpy(s->filename, name, SHMNAME_MAX);

	s->filename[SHMNAME_MAX] = 0;

	s->uid = curproc->euid;

	s->gid = curproc->egid;

	s->mode = mode;

	s->next = shmroot;

	s->reg = 0;

	s->time = shmtime = timestamp;

	s->date = shmdate = datestamp;

	shmroot = s;



	fc->fs = &shm_filesys;

	fc->index = (long)s;

	fc->dev = dir->dev;



	return 0;

}



/*

 * Shared memory device driver

 */



/*

 * BUG: file locking and the O_SHMODE restrictions are not implemented

 * for shared memory

 */



static long ARGS_ON_STACK 

shm_open(f)

	FILEPTR *f;

{

	SHMFILE *s;



	s = (SHMFILE *)f->devinfo;

	s->inuse++;

	return 0;

}



static long ARGS_ON_STACK 

shm_write(f, buf, nbytes)

	FILEPTR *f; const char *buf; long nbytes;

{

	SHMFILE *s;

	char *where;

	long bytes_written = 0;



	s = (SHMFILE *)f->devinfo;

	if (!s->reg)

		return 0;



	if (nbytes + f->pos > s->reg->len)

		nbytes = s->reg->len - f->pos;



	where = (char *)s->reg->loc + f->pos;



/* BUG: memory read/writes should check for valid addresses */



TRACE(("shm_write: %ld bytes to %lx", nbytes, where));



	while (nbytes-- > 0) {

		*where++ = *buf++;

		bytes_written++;

	}

	f->pos += bytes_written;

	s->time = timestamp;

	s->date = datestamp;

	return bytes_written;

}



static long ARGS_ON_STACK 

shm_read(f, buf, nbytes)

	FILEPTR *f; char *buf; long nbytes;

{

	SHMFILE *s;

	char *where;

	long bytes_read = 0;



	s = (SHMFILE *)f->devinfo;

	if (!(s->reg))

		return 0;



	if (nbytes + f->pos > s->reg->len)

		nbytes = s->reg->len - f->pos;



	where = (char *)s->reg->loc + f->pos;



TRACE(("shm_read: %ld bytes from %lx", nbytes, where));



	while (nbytes-- > 0) {

		*buf++ = *where++;

		bytes_read++;

	}

	f->pos += bytes_read;

	return bytes_read;

}



/*

 * shm_ioctl: currently, the only IOCTL's available are:

 * SHMSETBLK:  set the address of the shared memory file. This

 *             call may only be made once per region, and then only

 *	       if the region is open for writing.

 * SHMGETBLK:  get the address of the shared memory region. This

 *             call fails (returns 0) if SHMSETBLK has not been

 *             called yet for this shared memory file.

 */



static long ARGS_ON_STACK 

shm_ioctl(f, mode, buf)

	FILEPTR *f; int mode; void *buf;

{

	SHMFILE *s;

	MEMREGION *m;

	int i;

	long r;



	s = (SHMFILE *)f->devinfo;

	switch(mode) {

	case SHMSETBLK:

		if (s->reg) {

			DEBUG(("Fcntl: SHMSETBLK already performed for %s",

				s->filename));

			return ERANGE;

		}

		if ((f->flags & O_RWMODE) == O_RDONLY) {

			DEBUG(("Fcntl: SHMSETBLK: %s was opened read-only",

				s->filename));

			return EACCDN;

		}

	/* find the memory region to be attached */

		m = 0;

		for (i = curproc->num_reg - 1; i >= 0; i--) {

			if (curproc->addr[i] == (virtaddr)buf) {

				m = curproc->mem[i];

				break;

			}

		}

		if (!m || !buf) {

			DEBUG(("Fcntl: SHMSETBLK: bad address %lx", buf));

			return EIMBA;

		}

		m->links++;

		s->reg = m;

		return 0;

	case SHMGETBLK:

		if ((m = s->reg) == 0) {

			DEBUG(("Fcntl: no address for SHMGETBLK"));

			return 0;

		}

	/* check for memory limits */

		if (curproc->maxmem) {

			if (m->len > curproc->maxmem - memused(curproc)) {

				DEBUG(("Fcntl: SHMGETBLK would violate memory limits"));

				return 0;

			}

		}

		return (long)attach_region(curproc, m);

	case FIONREAD:

	case FIONWRITE:

		if (s->reg == 0) {

			r = 0;

		} else {

			r = s->reg->len - f->pos;

			if (r < 0) r = 0;

		}

		*((long *)buf) = r;

		return 0;

	default:

		DEBUG(("shmfs: bad Fcntl command"));

	}

	return EINVFN;

}



static long ARGS_ON_STACK 

shm_lseek(f, where, whence)

	FILEPTR *f; long where; int whence;

{

	long newpos, maxpos;

	SHMFILE *s;



	s = (SHMFILE *)f->devinfo;



	if (s->reg)

		maxpos = s->reg->len;

	else

		maxpos = 0;



	switch(whence) {

	case 0:

		newpos = where;

		break;

	case 1:

		newpos = f->pos + where;

		break;

	case 2:

		newpos = maxpos + where;

		break;

	default:

		return EINVFN;

	}



	if (newpos < 0 || newpos > maxpos)

		return ERANGE;



	f->pos = newpos;

	return newpos;

}



static long ARGS_ON_STACK 

shm_datime(f, timeptr, rwflag)

	FILEPTR *f;

	short *timeptr;

	int rwflag;

{

	SHMFILE *s;



	s = (SHMFILE *)f->devinfo;

	if (rwflag) {

		s->time = *timeptr++;

		s->date = *timeptr;

	} else {

		*timeptr++ = s->time;

		*timeptr = s->date;

	}

	return 0;

}



static long ARGS_ON_STACK 

shm_close(f, pid)

	FILEPTR *f;

	int pid;

{

	SHMFILE *s;



	UNUSED(pid);

	if (f->links <= 0) {

		s = (SHMFILE *)f->devinfo;

		s->inuse--;

	}

	return 0;

}


unix.superglobalmegacorp.com

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