DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦d65bbf496⟧ TextFile

    Length: 8631 (0x21b7)
    Types: TextFile
    Notes: UNIX file
    Names: »fs3.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦2d53db1df⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »sys/coh/fs3.c« 

TextFile

/* (-lgl
 * 	The information contained herein is a trade secret of Mark Williams
 * 	Company, 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 Mark Williams
 * 	Company or persuant to the license agreement is unlawful.
 * 
 * 	COHERENT Version 0.7.3
 * 	Copyright (c) 1982, 1983, 1984.
 * 	An unpublished work by Mark Williams Company, Chicago.
 * 	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Filesystem (I/O).
 */
#include <coherent.h>
#include <buf.h>
#include <canon.h>
#include <con.h>
#include <errno.h>
#include <filsys.h>
#include <mount.h>
#include <io.h>
#include <ino.h>
#include <inode.h>
#include <uproc.h>
#include <stat.h>

/*
 * Given an inode, open it.
 */
iopen(ip, mode)
register INODE *ip;
{
	register int type;

	type = ip->i_mode & IFMT;
	switch (type) {
	case IFCHR:
	case IFBLK:
		iunlock(ip);
		dopen(ip->i_a.i_rdev, mode, type==IFCHR ? DFCHR : DFBLK);
		ilock(ip);
		break;
	case IFDIR:
		if ((mode&IPW) != 0) {
			if (super() == 0)
				return;
			if (mode == IPW) {
				u.u_error = EISDIR;
				return;
			}
		}
		break;
	case IFPIPE:
		popen(ip, mode);
		break;
	}
}

/*
 * Given an inode, close it.
 */
iclose(ip)
register INODE *ip;
{
	ilock(ip);
	switch (ip->i_mode&IFMT) {
	case IFBLK:
		bflush(ip->i_a.i_rdev);
	case IFCHR:
		iunlock(ip);
		dclose(ip->i_a.i_rdev);
		ilock(ip);
		break;
	case IFPIPE:
		pclose(ip);
		break;
	}
	idetach(ip);
}

/*
 * Read from a file described by an inode and an io strucuture.
 */
iread(ip, iop)
register INODE *ip;
register IO *iop;
{
	if (iop->io_ioc == 0)
		return;
	switch (ip->i_mode&IFMT) {
	case IFCHR:
		dread(ip->i_a.i_rdev, iop);
		break;
	case IFBLK:
	case IFREG:
	case IFDIR:
		fread(ip, iop);
		break;
	case IFPIPE:
		pread(ip, iop);
		break;
	default:
		u.u_error = ENXIO;
		break;
	}
}

/*
 * Write to a file described by an inode and io structure.
 */
iwrite(ip, iop)
register INODE *ip;
register IO *iop;
{
	imod(ip);	/* write - mtime */
	icrt(ip);	/* write - ctime */
	if (iop->io_ioc == 0)
		return;
	switch (ip->i_mode&IFMT) {
	case IFCHR:
		dwrite(ip->i_a.i_rdev, iop);
		break;
	case IFBLK:
		fwrite(ip, iop);
		break;
	case IFREG:
	case IFDIR:
		if (getment(ip->i_dev, 1) == NULL)
			return;
		fwrite(ip, iop);
		break;
	case IFPIPE:
		pwrite(ip, iop);
		break;
	default:
		u.u_error = ENXIO;
		break;
	}
}

/*
 * Read from a regular or block special file.
 */
fread(ip, iop)
INODE *ip;
register IO *iop;
{
#ifdef TINY
	register unsigned n;
	register size_t res;
	register unsigned off;
	register daddr_t lbn;
	register BUF *bp;
	register int blk;

	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	blk = (ip->i_mode&IFMT) == IFBLK;
	res = ip->i_size - iop->io_seek;
	if (blk!=0 || res>iop->io_ioc)
		res = iop->io_ioc;
	while (res > 0) {
		bp = blk ? bread(ip->i_a.i_rdev, lbn, 1) : vread(ip, lbn);
		if (bp == NULL)
			return;
		n = BSIZE - off;
		if (n > res)
			n = res;
		iowrite(iop, bp->b_vaddr+off, n);
		brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		res -= n;
	}
/*
 * Start of daring read ahead code.
 * Altered to not read ahead on block devices
 * due to 20% time penalty incurred for such.
 */
#if 0
	if ( ! blk) {
		lbn = vmap(ip, lbn);
		if (lbn > 0)
			bread(ip->i_dev, lbn, 0);
	}
#endif
/*
 * End of daring read ahead code.
 */
#else
	register unsigned n;
	register unsigned i;
	register size_t res;
	register unsigned off;
	register dev_t dev;
	register daddr_t lbn;
	register daddr_t pbn;
	register daddr_t abn;
	register daddr_t zbn;
	register BUF *bp;
	register int blk;
	daddr_t list[NEXREAD];

	if ((ip->i_mode&IFMT) == IFBLK) {
		blk = 1;
		dev = ip->i_a.i_rdev;
	} else {
		blk = 0;
		dev = ip->i_dev;
	}
	abn = 0;
	zbn = 0;
	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	res = ip->i_size - iop->io_seek;
	if (blk!=0 || res>iop->io_ioc)
		res = iop->io_ioc;
	if (res <= 0)
		return;
	if (res+off <= BSIZE) {
		bp = blk ? bread(dev, lbn, 1) : vread(ip, lbn);
		if (bp == NULL)
			return;
		iowrite(iop, bp->b_vaddr+off, (unsigned)res);
		brelease(bp);
		return;
	}
	while (res > 0) {
		if (lbn >= zbn) {
			if ((n=blockn(res+BSIZE-1)) > NEXREAD)
				n = NEXREAD;
			if (n <= 0)
				n = 1;
			abn = lbn;
			for (i=0, zbn=lbn; i<n; i++, zbn++) {
				if (blk != 0)
					pbn = zbn;
				else {
					if ((pbn=vmap(ip, zbn)) < 0)
						return;
					if (pbn == 0) {
						list[i] = -1;
						continue;
					}
				}
				list[i] = pbn;
				bread(dev, pbn, 0);
			}
		}
		if ((pbn=list[lbn-abn]) < 0) {
			bp = bclaim(NODEV, (daddr_t)0);
			kclear(bp->b_vaddr, BSIZE);
		} else {
			if ((bp=bread(dev, pbn, 1)) == NULL)
				return;
		}
		n = BSIZE - off;
		n = res>n ? n : res;
		iowrite(iop, bp->b_vaddr+off, n);
		brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		res -= n;
	}
#endif
}

/*
 * Write to a regular or block special file.
 */
fwrite(ip, iop)
INODE *ip;
register IO *iop;
{
	register unsigned n;
	register unsigned off;
	register daddr_t lbn;
	register BUF *bp;
	register int blk;
	register int com;

	lbn = blockn(iop->io_seek);
	off = blocko(iop->io_seek);
	blk = (ip->i_mode&IFMT) == IFBLK;
	while (iop->io_ioc > 0) {
		n = BSIZE - off;
		n = iop->io_ioc>n ? n : iop->io_ioc;
		com = off==0 && n==BSIZE;
		if (blk == 0)
			bp = aread(ip, lbn, com);
		else {
			if (com)
				bp = bclaim(ip->i_a.i_rdev, lbn);
			else
				bp = bread(ip->i_a.i_rdev, lbn, 1);
		}
		if (bp == NULL)
			return;
		ioread(iop, bp->b_vaddr+off, n);
		bp->b_flag |= BFMOD;
		if (com)
			bwrite(bp, 0);
		else
			brelease(bp);
		if (u.u_error)
			return;
		lbn++;
		off = 0;
		if ((iop->io_seek+=n) > ip->i_size)
			if (blk == 0)
				ip->i_size = iop->io_seek;
	}
}

/*
 * Given an inode pointer, read the requested virtual block and return
 * a buffer with the data.
 */
BUF *
vread(ip, lb)
register INODE *ip;
daddr_t lb;
{
	register daddr_t pb;
	register BUF *bp;

	if ((pb=vmap(ip, lb)) < 0)
		return (NULL);
	if (pb != 0)
		return (bread(ip->i_dev, pb, 1));
	bp = bclaim(NODEV, (daddr_t)0);
	kclear(bp->b_vaddr, BSIZE);
	return (bp);
}

/*
 * Convert the given virtual block to a physical block for the given inode.
 * If the block does not map onto a physical block because the file is sparse
 * but it does exist, 0 is returned.  If an error is encountered, -1 is
 * returned.
 */
daddr_t
vmap(ip, lb)
register INODE *ip;
daddr_t lb;
{
	register BUF *bp;
	register int *lp;
	daddr_t pb;
	int list[1+NI];

	if ((lp=lmap(lb, list)) == NULL)
		return (-1);
	pb = ip->i_a.i_addr[*--lp];
	for (;;) {
		if (pb==0 || lp==list)
			return (pb);
		if ((bp=bread(ip->i_dev, pb, 1)) == NULL)
			return (0);
		pb = ((daddr_t *)bp->b_vaddr)[*--lp];
		brelease(bp);
		candaddr(pb);
	}
}

/*
 * Given an inode pointer, read the requested virtual block and return a
 * buffer with the data.  In sparse files, the necessary blocks are allocated.
 * If the flag, `fflag' is set, the final buffer is just claimed rather than
 * read as we are going to change it's contents completely.
 */
BUF *
aread(ip, lb, fflag)
register INODE *ip;
daddr_t lb;
{
	register BUF *bp;
	register int *lp;
	register dev_t dev;
	register int l;
	register int aflag;
	register int lflag;
	daddr_t pb;
	int list[1+NI];

	if ((lp=lmap(lb, list)) == NULL)
		return (NULL);
	aflag = 0;
	dev = ip->i_dev;
	pb = ip->i_a.i_addr[l=*--lp];
	if (pb == 0) {
		aflag = 1;
		if ((pb=balloc(dev)) == 0)
			return (NULL);
		ip->i_a.i_addr[l] = pb;
	}
	for (;;) {
		lflag = lp==list;
		if (aflag==0  &&  (fflag==0 || lflag==0)) {
			if ((bp=bread(dev, pb, 1)) == NULL)
				return (NULL);
		} else {
			bp = bclaim(dev, pb);
			kclear(bp->b_vaddr, BSIZE);
			bp->b_flag |= BFMOD;
		}
		if (lflag)
			return (bp);

		aflag = 0;
		pb = ((daddr_t *)bp->b_vaddr)[l=*--lp];
		candaddr(pb);
		if (pb == 0) {
			aflag = 1;
			if ((pb=balloc(dev)) == 0) {
				brelease(bp);
				return (NULL);
			}
			((daddr_t *)bp->b_vaddr)[l] = pb;
			candaddr(((daddr_t *)bp->b_vaddr)[l]);
			bp->b_flag |= BFMOD;
		}
		brelease(bp);
	}
}

/*
 * Given a block number, `b', store the offsets for the indirect blocks
 * backwards in the array, `lp', and return a pointer just after the
 * position where the first offset is stored.
 */
int *
lmap(b, lp)
register daddr_t b;
register int *lp;
{
	register int n;

	if (b < ND) {
		*lp++ = b;
		return (lp);
	}
	b -= ND;
	n = NI;
	do {
		if (n-- == 0) {
			u.u_error = EFBIG;
			return (NULL);
		}
		*lp = nbnrem(b);
		++lp;
		b = nbndiv(b);
	} while (b--);
	*lp++ = ND+NI-1-n;
	return (lp);
}