|
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: 8631 (0x21b7) Types: TextFile Notes: UNIX file Names: »fs3.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦2d53db1df⟧ UNIX Filesystem └─⟦this⟧ »sys/coh/fs3.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 (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); }