home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff236.lzh
/
DiskHandler
/
bitmap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-09
|
9KB
|
278 lines
/* BitMap.c - BitMap support routines */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* |_o_o|\\ Copyright (c) 1987 The Software Distillery. All Rights Reserved */
/* |. o.| || This program may not be distributed without the permission of */
/* | . | || the author. BBS: */
/* | o | || John Toebes Dave Baker Jim Cooper (919)-471-6436 */
/* | . |// */
/* ====== */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "handler.h"
#define BMSIZE ((((global->dskenv.de_numblks)-(global->dskenv.de_reservedblks))/32)+1)
int AllocBitMap(global)
GLOBAL global;
{
struct RootBlock *tmpRoot;
char *tmpblk;
register int i, size = BMSIZE*4;
/* allocate memory for the bit map in long words */
if ((global->bitmap.bm_bitmap = (ULONG *)
AllocMem(size,MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
BUG(("AllocBitMap Failed\n"));
return(NULL);
}
BUG(("AllocBitMap - root %ld - bitmap %08lx - size %ld\n",
global->Root,global->bitmap.bm_bitmap,BMSIZE));
tmpRoot = (struct RootBlock *)GetBlock(global,global->Root);
if (tmpRoot->rb_BitMapFlag == 0)
{
/* OH NO! The bitmap is INVALID!! Let's call the disk validator */
return(NULL);
}
for (i=0; (i<BITMAPSIZE) && (tmpRoot->rb_BitMapPages[i]); i++)
{
tmpblk = GetBlock(global,tmpRoot->rb_BitMapPages[i]);
memcpy((char *)&global->bitmap.bm_bitmap[i*127],&tmpblk[4],min(508,size));
size -= 508;
}
global->bitmap.bm_blocks = i;
return(-1);
}
int FreeBitMap(global)
GLOBAL global;
{
if (global->bitmap.bm_bitmap) {
FreeMem((char *)global->bitmap.bm_bitmap,(BMSIZE*4));
global->bitmap.bm_blocks = 0;
global->bitmap.bm_dirty = 0;
global->bitmap.bm_bitmap = NULL;
return(-1);
}
return(NULL);
}
int CountBlocks(global)
GLOBAL global;
{
register int block, bit, count = 0;
/* count number of used blocks. bit is 0 if used, 1 if free */
for (block=0; block<BMSIZE; block++)
for (bit=0; bit<32; bit++) {
if ((block == BMSIZE-1) && (bit > 29)) continue;
if (!(global->bitmap.bm_bitmap[block] & (1<<bit))) {
count++;
}
}
return(count);
}
void DoCheckSum(global,block)
GLOBAL global;
char *block;
{
struct DirBlock *dblock;
register ULONG *ptr;
register ULONG checksum;
dblock = (struct DirBlock *)block;
dblock->db_CheckSum = checksum = 0;
for (ptr = (ULONG *)dblock; ptr < (ULONG *)(dblock+1);)
checksum -= *ptr++;
dblock->db_CheckSum = checksum;
}
void WriteBitMap(global)
GLOBAL global;
{
register int i, j, block;
long oldbitmap;
KEY key;
struct RootBlock *tmproot;
ULONG *tmpblk;
int size = BMSIZE*4;
if (global->bitmap.bm_dirty)
{
tmproot = (struct RootBlock *)ModBlock(global,global->Root);
if (tmproot == NULL)
{
BUG(("Unable to locate the Root block\n"));
return;
}
/* Now update the root block to reset the bitmap valid flag */
oldbitmap = tmproot->rb_BitMapFlag;
tmproot->rb_BitMapFlag = 0;
/* Next we need to force the root block out to disk. Note that we can */
/* actually get away with not doing this IF it was already invalid on */
/* disk */
if (oldbitmap == NULL)
{
/* Ok, so it hasn't been updated - put it out there */
FlushOne(global, FindBuffer(global,global->Root,0));
}
/* Next we get to allocate a new bitmap */
for (block=0; block<global->bitmap.bm_blocks; block++)
{
#if 0
key = AllocateBlock(global,global->Root,0);
if (key == 0)
{
/* For some reason there was no room on the disk so we can't put */
/* the bitmap onto the disk. Gee, what's a person to do. This */
/* can occur with the standard file handler. */
BUG(("No room to put bitmap on disk\n"));
return;
}
#endif
/* I know its not kosher to do this brute force, but I'd like to */
/* see it WORK before I get fancy */
tmproot = (struct RootBlock *)GetBlock(global,global->Root);
if (tmproot == NULL)
{
BUG(("Unable to get root block\n"));
return;
}
key = tmproot->rb_BitMapPages[block];
i = FindBuffer(global, key, 0); /* do not read from disk */
if (i == -1)
{
/* Some catastrophic error finding a buffer for the bitmap */
/* Just propagate the error. However this error is quite */
/* unlikely as we are not asking for any I/O */
BUG(("How can this happen? can't find buffer for bitmap\n"));
return;
}
global->blkbuf[i].bb_used = ST_BITMAP; /* Prevent the checksum */
global->blkbuf[i].bb_dirty = 1; /* make sure it gets written */
tmpblk = (ULONG *)global->blkbuf[i].bb_blk;
/* clear the destination block (in case we don't use the whole thing) */
memset((char *)tmpblk,0,sizeof(struct DataBlock));
/* now copy the bitmap to the destination */
memcpy((char *)&tmpblk[1],
(char *)&global->bitmap.bm_bitmap[block*127],
min(508, size));
/* Calculate the checksum for the bitmap block we just created */
for (j=min(127, size/4); j; j--)
{
tmpblk[0] -= tmpblk[j];
}
/* And cause it to be output IMMEDIATELY */
FlushOne(global, i);
size -= 508;
}
global->bitmap.bm_dirty = 0;
tmproot = (struct RootBlock *)ModBlock(global, global->Root);
if (tmproot == NULL)
{
BUG(("Unable to get Root block again!\n"));
return;
}
tmproot->rb_BitMapFlag = -1;
FlushOne(global, FindBuffer(global,global->Root,0));
}
}
void SetBlock(global,key)
GLOBAL global;
KEY key;
{
ULONG bmindex;
ULONG bmbit;
bmindex = ((key-global->dskenv.de_reservedblks) >> 5);
bmbit = ((key-global->dskenv.de_reservedblks) & 0x1f);
if (!((global->bitmap.bm_bitmap[bmindex]) & (1<<bmbit)))
{
request(global, REQ_GENERAL, "Attempt to allocate used block");
}
(global->bitmap.bm_bitmap[bmindex]) &= ~(1<<bmbit);
global->bitmap.bm_dirty = 1;
}
void FreeBlock(global,key)
GLOBAL global;
KEY key;
{
ULONG bmindex;
ULONG bmbit;
BUG(("FreeBlock: %ld\n", key));
bmindex = ((key-global->dskenv.de_reservedblks) >> 5);
bmbit = ((key-global->dskenv.de_reservedblks) & 0x1f);
if ((global->bitmap.bm_bitmap[bmindex]) & (1<<bmbit))
{
request(global, REQ_GENERAL, "Attempt to free unused block");
}
(global->bitmap.bm_bitmap[bmindex]) |= (1<<bmbit);
global->bitmap.bm_dirty = 1;
}
KEY AllocateBlock(global,key,type)
GLOBAL global;
KEY key;
int type;
{
KEY trkstart, newkey = 0;
ULONG bmindex;
ULONG bmbit;
register ULONG bmsize = BMSIZE;
if (!(global->bitmap.bm_bitmap))
AllocBitMap(global);
trkstart = (key - (key - ((key / global->dskenv.de_blkspertrk) * global->dskenv.de_blkspertrk)));
bmindex = ((trkstart - global->dskenv.de_reservedblks) >> 5);
bmbit = ((trkstart - global->dskenv.de_reservedblks) & 0x1f);
while (bmindex<bmsize) {
if (global->bitmap.bm_bitmap[bmindex] & (1<<bmbit)) break;
if (++bmbit > 31) bmbit = 0, bmindex++;
}
if (bmindex == bmsize) {
bmbit=0; bmindex=0;
while (bmindex<bmsize) {
if (global->bitmap.bm_bitmap[bmindex] & (1<<bmbit)) break;
if (++bmbit > 31) bmbit = 0, bmindex++;
}
if (bmindex == bmsize) {
request(global,REQ_GENERAL,"Disk FULL on volume");
return(newkey);
}
}
newkey = (((bmindex)<<5)+bmbit+global->dskenv.de_reservedblks);
SetBlock(global, newkey);
/* Force the buffer to be allocated without reading from disk */
FindBuffer(global, newkey, 0); /* Don't read it in from disk */
BUG(("AllocateBlock: Key %ld\n", newkey));
if ((newkey < global->dskenv.de_reservedblks) ||
(newkey == global->Root) ||
(newkey > global->dskenv.de_numblks))
{
BUG(("Allocated block %ld out of range %ld-%ld\n", newkey, global->dskenv.de_reservedblks,global->dskenv.de_numblks));
request(global, REQ_GENERAL, "Key out of range on volume");
}
return(newkey);
}