|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 9061 (0x2365)
Types: TextFile
Notes: UNIX file
Names: »fs2.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »sys/coh/fs2.c«
/* (-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 (disk inodes).
*/
#include <coherent.h>
#include <acct.h>
#include <buf.h>
#include <canon.h>
#include <con.h>
#include <errno.h>
#include <filsys.h>
#include <ino.h>
#include <inode.h>
#include <io.h>
#include <mount.h>
#include <proc.h>
#include <uproc.h>
/*
* Initialise filesystem.
*/
fsminit()
{
register MOUNT *mp;
if ((mp=fsmount(rootdev, ronflag)) == NULL)
panic("fsminit: no rootdev");
timer.t_time = mp->m_super.s_time;
if ((u.u_rdir=iattach(rootdev, ROOTIN)) == NULL)
panic("fsminit: no /");
u.u_cdir = u.u_rdir;
u.u_cdir->i_refc++;
iunlock(u.u_rdir);
}
/*
* Mount the given device.
*/
MOUNT *
fsmount(dev, f)
register dev_t dev;
{
register MOUNT *mp;
register BUF *bp;
if ((mp=kalloc(sizeof(MOUNT))) == NULL)
return (NULL);
dopen(dev, (f?IPR:IPR|IPW), DFBLK);
if (u.u_error != 0) {
kfree(mp);
return (NULL);
}
if ((bp=bread(dev, (daddr_t)SUPERI, 1)) == NULL) {
dclose(dev);
kfree(mp);
return (NULL);
}
kkcopy(bp->b_vaddr, &mp->m_super, sizeof(struct filsys));
brelease(bp);
cansuper(&mp->m_super);
mp->m_ip = NULL;
mp->m_dev = dev;
mp->m_flag = f;
mp->m_super.s_fmod = 0;
mp->m_next = mountp;
mountp = mp;
return (mp);
}
/*
* Canonize a super block.
*/
cansuper(fsp)
register struct filsys *fsp;
{
register int i;
canint(fsp->s_isize);
candaddr(fsp->s_fsize);
canshort(fsp->s_nfree);
for (i=0; i<NICFREE; i++)
candaddr(fsp->s_free[i]);
canshort(fsp->s_ninode);
for (i=0; i<NICINOD; i++)
canino(fsp->s_inode[i]);
cantime(fsp->s_time);
candaddr(fsp->s_tfree);
canino(fsp->s_tinode);
canshort(fsp->s_m);
canshort(fsp->s_n);
canlong(fsp->s_unique);
}
/*
* Given a pointer to a mount entry, write out all inodes on that device.
*/
msync(mp)
register MOUNT *mp;
{
register struct filsys *sbp;
register BUF *bp;
if ((mp->m_flag&MFRON) != 0)
return;
isync(mp->m_dev);
sbp = &mp->m_super;
if (sbp->s_fmod==0 && mp->m_dev!=rootdev)
return;
bp = bclaim(mp->m_dev, (daddr_t)SUPERI);
sbp->s_time = timer.t_time;
sbp->s_fmod = 0;
kkcopy(sbp, bp->b_vaddr, sizeof(*sbp));
cansuper(bp->b_vaddr);
bwrite(bp, 1);
brelease(bp);
}
/*
* Return the mount entry for the given device. If `f' is not set
* and the device is read only, don't set the error status.
*/
MOUNT *
getment(dev, f)
register dev_t dev;
{
register MOUNT *mp;
for (mp=mountp; mp!=NULL; mp=mp->m_next) {
if (mp->m_dev != dev)
continue;
if ((mp->m_flag&MFRON) != 0) {
if (f != 0)
u.u_error = EROFS;
return (NULL);
}
return (mp);
}
panic("getment: dev=0x%x", dev);
}
/*
* Allocate a new inode with the given mode. The returned inode is locked.
*/
INODE *
ialloc(dev, mode)
dev_t dev;
unsigned mode;
{
register struct dinode *dip;
register struct filsys *sbp;
register ino_t *inop;
register ino_t ino;
register BUF *bp;
register daddr_t b;
register struct dinode *dipe;
register ino_t *inope;
register MOUNT *mp;
register INODE *ip;
if ((mp=getment(dev, 1)) == NULL)
return (NULL);
sbp = &mp->m_super;
for (;;) {
lock(mp->m_ilock);
sbp->s_fmod = 1;
if (sbp->s_ninode == 0) {
ino = 1;
inop = sbp->s_inode;
inope = &sbp->s_inode[NICINOD];
for (b=INODEI; b<sbp->s_isize; b++) {
if (bad(dev, b)) {
ino += INOPB;
continue;
}
if ((bp=bread(dev, b, 1)) == NULL) {
brelease(bp);
ino += INOPB;
continue;
}
dip = bp->b_vaddr;
dipe = &dip[INOPB];
for (; dip<dipe; dip++, ino++) {
if (dip->di_mode != 0)
continue;
if (inop >= inope)
break;
*inop++ = ino;
}
brelease(bp);
if (inop >= inope)
break;
}
sbp->s_ninode = inop - sbp->s_inode;
if (sbp->s_ninode == 0) {
sbp->s_tinode = 0;
unlock(mp->m_ilock);
devmsg(dev, "Out of inodes");
u.u_error = ENOSPC;
return (NULL);
}
}
ino = sbp->s_inode[--sbp->s_ninode];
--sbp->s_tinode;
unlock(mp->m_ilock);
if ((ip=iattach(dev, ino)) != NULL) {
if (ip->i_mode != 0) {
devmsg(dev, "Inode %u busy", ino);
idetach(ip);
continue;
}
ip->i_flag = 0;
ip->i_mode = mode;
ip->i_nlink = 0;
ip->i_uid = u.u_uid;
ip->i_gid = u.u_gid;
}
return (ip);
}
}
/*
* Free the inode `ino' on device `dev'.
*/
ifree(dev, ino)
dev_t dev;
ino_t ino;
{
register struct filsys *sbp;
register MOUNT *mp;
if ((mp=getment(dev, 1)) == NULL)
return;
lock(mp->m_ilock);
sbp = &mp->m_super;
sbp->s_fmod = 1;
if (sbp->s_ninode < NICINOD)
sbp->s_inode[sbp->s_ninode++] = ino;
sbp->s_tinode++;
unlock(mp->m_ilock);
}
/*
* Free all blocks in the indirect block `b' on the device `dev'.
* `l' is the level of indirection.
*/
indfree(dev, b, l)
dev_t dev;
daddr_t b;
register unsigned l;
{
register int i;
register BUF *bp;
daddr_t b1;
if (b == 0)
return;
if (l-->0 && (bp=bread(dev, b, 1))!=NULL) {
i = NBN;
while (i-- > 0) {
if ((b1=((daddr_t *)bp->b_vaddr)[i]) == 0)
continue;
candaddr(b1);
if (l == 0)
bfree(dev, b1);
else
indfree(dev, b1, l);
}
brelease(bp);
}
bfree(dev, b);
}
/*
* Allocate a block from the filesystem mounted of device `dev'.
*/
daddr_t
balloc(dev)
dev_t dev;
{
register struct filsys *sbp;
register struct fblk *fbp;
register daddr_t b;
register BUF *bp;
register MOUNT *mp;
if ((mp=getment(dev, 1)) == NULL)
return (0);
lock(mp->m_flock);
sbp = &mp->m_super;
if (sbp->s_nfree == 0) {
enospc:
sbp->s_nfree = 0;
devmsg(dev, "Out of space");
u.u_error = ENOSPC;
b = 0;
} else {
sbp->s_fmod = 1;
if ((b=sbp->s_free[--sbp->s_nfree]) == 0)
goto enospc;
if (sbp->s_nfree == 0) {
if (b >= sbp->s_fsize
|| b < sbp->s_isize
|| (bp = bread(dev, b, 1)) == NULL) {
ebadflist:
devmsg(dev, "Bad free list");
goto enospc;
}
fbp = bp->b_vaddr;
sbp->s_nfree = fbp->df_nfree;
canshort(sbp->s_nfree);
if ((unsigned)sbp->s_nfree > NICFREE)
goto ebadflist;
kkcopy(fbp->df_free, sbp->s_free, sizeof(sbp->s_free));
canndaddr(sbp->s_free, sbp->s_nfree);
brelease(bp);
}
--sbp->s_tfree;
if (b >= sbp->s_fsize || b < sbp->s_isize)
goto ebadflist;
}
unlock(mp->m_flock);
return (b);
}
/*
* Free the block `b' on the device `dev'.
*/
bfree(dev, b)
dev_t dev;
daddr_t b;
{
register struct filsys *sbp;
register struct fblk *fbp;
register BUF *bp;
register MOUNT *mp;
if ((mp=getment(dev, 1)) == NULL)
return;
sbp = &mp->m_super;
if (b>=sbp->s_fsize || b<sbp->s_isize) {
devmsg(dev, "Bad block %u (free)", (unsigned)b);
return;
}
lock(mp->m_flock);
if (sbp->s_nfree == 0 || sbp->s_nfree == NICFREE) {
bp = bclaim(dev, b);
fbp = bp->b_vaddr;
kclear(fbp, BSIZE);
fbp->df_nfree = sbp->s_nfree;
canshort(fbp->df_nfree);
kkcopy(sbp->s_free, fbp->df_free, sizeof(fbp->df_free));
canndaddr(fbp->df_free, sbp->s_nfree);
bp->b_flag |= BFMOD;
brelease(bp);
sbp->s_nfree = 0;
}
sbp->s_free[sbp->s_nfree++] = b;
sbp->s_tfree++;
sbp->s_fmod = 1;
unlock(mp->m_flock);
}
/*
* Determine if the given block is bad.
*/
bad(dev, b)
dev_t dev;
daddr_t b;
{
register INODE *ip;
register BUF *bp;
register int i;
register int m;
register int n;
daddr_t l;
if ((ip=iattach(dev, 1)) == NULL)
panic("bad()");
n = blockn(ip->i_size);
if ((m=n) > ND)
m = ND;
for (i=0; i<m; i++) {
--n;
if (b == ip->i_a.i_addr[i]) {
idetach(ip);
return (1);
}
}
l = ip->i_a.i_addr[ND];
idetach(ip);
if (n == 0)
return (0);
if ((bp=bread(dev, l, 1)) == NULL)
return (0);
if ((m=n) > NBN)
m = NBN;
for (i=0; i<m; i++) {
l = ((daddr_t *)bp)[i];
candaddr(l);
if (b == l) {
brelease(bp);
return (1);
}
}
brelease(bp);
return (0);
}
/*
* Canonize `n' disk addresses.
*/
canndaddr(dp, n)
register daddr_t *dp;
register int n;
{
while (n--) {
candaddr(*dp);
dp++;
}
}
/*
* Write out an accounting record.
*/
setacct()
{
register PROC *pp;
struct acct acct;
IO acctio;
if (acctip == NULL)
return;
pp = SELF;
kkcopy(u.u_comm, acct.ac_comm, 10);
acct.ac_utime = ltoc(pp->p_utime);
acct.ac_stime = ltoc(pp->p_stime);
acct.ac_etime = ltoc(timer.t_time - u.u_btime);
acct.ac_btime = u.u_btime;
acct.ac_uid = u.u_uid;
acct.ac_gid = u.u_gid;
acct.ac_mem = 0;
acct.ac_io = ltoc(u.u_block);
acct.ac_tty = pp->p_ttdev;
acct.ac_flag = u.u_flag;
ilock(acctip);
acctio.io_seek = acctip->i_size;
acctio.io_ioc = sizeof (acct);
acctio.io_base = &acct;
acctio.io_seg = IOSYS;
iwrite(acctip, &acctio);
iunlock(acctip);
u.u_error = 0;
}