-/*
- * read/write a disk block, be sure to update the buffer
- * cache if needed.
- */
-dwrite(bno, b)
-daddr_t bno;
-char *b;
-{
- register i;
-
- for (i = 0; i < NCACHE; i++) {
- if (cache[i].c_bno == bno) {
- copy(b, cache[i].c_block, BSIZE);
- cache[i].c_time = 0;
- break;
- }
- else
- cache[i].c_time++;
- }
- lseek(fi, bno*BSIZE, 0);
- if(write(fi, b, BSIZE) != BSIZE) {
-#ifdef STANDALONE
- printf("disk write error %D\n", bno);
-#else
- fprintf(stderr, "disk write error %ld\n", bno);
-#endif
- exit(1);
- }
-}
-
-dread(bno, buf, cnt)
-daddr_t bno;
-char *buf;
-{
- register i, j;
-
- j = 0;
- for (i = 0; i < NCACHE; i++) {
- if (++curcache >= NCACHE)
- curcache = 0;
- if (cache[curcache].c_bno == bno) {
- copy(cache[curcache].c_block, buf, cnt);
- cache[curcache].c_time = 0;
- return;
- }
- else {
- cache[curcache].c_time++;
- if (cache[j].c_time < cache[curcache].c_time)
- j = curcache;
- }
- }
-
- lseek(fi, bno*BSIZE, 0);
- if (read(fi, cache[j].c_block, BSIZE) != BSIZE) {
-#ifdef STANDALONE
- printf("read error %D\n", bno);
-#else
- printf("read error %ld\n", bno);
-#endif
- exit(1);
- }
- copy(cache[j].c_block, buf, cnt);
- cache[j].c_time = 0;
- cache[j].c_bno = bno;
-}
-
-/*
- * the inode manpulation routines. Like the system.
- *
- * clri zeros the inode
- */
-clri(ip)
-struct dinode *ip;
-{
- int i, *p;
- if (ip->di_mode&IFMT)
- sblock.s_tinode++;
- i = sizeof(struct dinode)/sizeof(int);
- p = (int *)ip;
- do
- *p++ = 0;
- while(--i);
-}
-
-/*
- * itrunc/tloop/bfree free all of the blocks pointed at by the inode
- */
-itrunc(ip)
-register struct dinode *ip;
-{
- register i;
- daddr_t bn, iaddr[NADDR];
-
- if (ip->di_mode == 0)
- return;
- i = ip->di_mode & IFMT;
- if (i != IFDIR && i != IFREG)
- return;
- l3tol(iaddr, ip->di_addr, NADDR);
- for(i=NADDR-1;i>=0;i--) {
- bn = iaddr[i];
- if(bn == 0) continue;
- switch(i) {
-
- default:
- bfree(bn);
- break;
-
- case NADDR-3:
- tloop(bn, 0, 0);
- break;
-
- case NADDR-2:
- tloop(bn, 1, 0);
- break;
-
- case NADDR-1:
- tloop(bn, 1, 1);
- }
- }
- ip->di_size = 0;
-}
-
-tloop(bn, f1, f2)
-daddr_t bn;
-int f1, f2;
-{
- register i;
- daddr_t nb;
- union {
- char data[BSIZE];
- daddr_t indir[NINDIR];
- } ibuf;
-
- dread(bn, ibuf.data, BSIZE);
- for(i=NINDIR-1;i>=0;i--) {
- nb = ibuf.indir[i];
- if(nb) {
- if(f1)
- tloop(nb, f2, 0);
- else
- bfree(nb);
- }
- }
- bfree(bn);
-}
-
-bfree(bn)
-daddr_t bn;
-{
- register i;
- union {
- char data[BSIZE];
- struct fblk frees;
- } fbun;
-#define fbuf fbun.frees
-
- if(sblock.s_nfree >= NICFREE) {
- fbuf.df_nfree = sblock.s_nfree;
- for(i=0;i<NICFREE;i++)
- fbuf.df_free[i] = sblock.s_free[i];
- sblock.s_nfree = 0;
- dwrite(bn, fbun.data);
- }
- sblock.s_free[sblock.s_nfree++] = bn;
- sblock.s_tfree++;
-}
-
-/*
- * allocate a block off the free list.
- */
-daddr_t
-balloc()
-{
- daddr_t bno;
- register i;
- static char zeroes[BSIZE];
- union {
- char data[BSIZE];
- struct fblk frees;
- } fbun;
-#undef fbuf
-#define fbuf fbun.frees
-
- if(sblock.s_nfree == 0 || (bno=sblock.s_free[--sblock.s_nfree]) == 0) {
-#ifdef STANDALONE
- printf("Out of space\n");
-#else
- fprintf(stderr, "Out of space.\n");
-#endif
- exit(1);
- }
- if(sblock.s_nfree == 0) {
- dread(bno, (char * )&fbuf, BSIZE);
- sblock.s_nfree = fbuf.df_nfree;
- for(i=0;i<NICFREE;i++)
- sblock.s_free[i] = fbuf.df_free[i];
- }
- dwrite(bno, zeroes);
- sblock.s_tfree--;
- return(bno);
-}
-
-/*
- * map a block number into a block address, ensuring
- * all of the correct indirect blocks are around. Allocate
- * the block requested.
- */
-daddr_t
-bmap(iaddr, bn)
-daddr_t iaddr[NADDR];
-daddr_t bn;
-{
- register i;
- int j, sh;
- daddr_t nb, nnb;
- daddr_t indir[NINDIR];
-
- /*
- * blocks 0..NADDR-4 are direct blocks
- */
- if(bn < NADDR-3) {
- iaddr[bn] = nb = balloc();
- return(nb);
- }
-
- /*
- * addresses NADDR-3, NADDR-2, and NADDR-1
- * have single, double, triple indirect blocks.
- * the first step is to determine
- * how many levels of indirection.
- */
- sh = 0;
- nb = 1;
- bn -= NADDR-3;
- for(j=3; j>0; j--) {
- sh += NSHIFT;
- nb <<= NSHIFT;
- if(bn < nb)
- break;
- bn -= nb;
- }
- if(j == 0) {
- return((daddr_t)0);
- }
-
- /*
- * fetch the address from the inode
- */
- if((nb = iaddr[NADDR-j]) == 0) {
- iaddr[NADDR-j] = nb = balloc();
- }
-
- /*
- * fetch through the indirect blocks
- */
- for(; j<=3; j++) {
- dread(nb, (char *)indir, BSIZE);
- sh -= NSHIFT;
- i = (bn>>sh) & NMASK;
- nnb = indir[i];
- if(nnb == 0) {
- nnb = balloc();
- indir[i] = nnb;
- dwrite(nb, (char *)indir);
- }
- nb = nnb;
- }
- return(nb);
-}
-