home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 274.lha / DiskHandler / bitmap.c < prev    next >
C/C++ Source or Header  |  1989-07-25  |  9KB  |  278 lines

  1. /* BitMap.c - BitMap support routines */
  2.  
  3. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  4. /* |_o_o|\\ Copyright (c) 1987 The Software Distillery.  All Rights Reserved */
  5. /* |. o.| || This program may not be distributed without the permission of   */
  6. /* | .  | || the author.                                           BBS:      */
  7. /* | o  | ||   John Toebes    Dave Baker    Jim Cooper       (919)-471-6436  */
  8. /* |  . |//                                                                  */
  9. /* ======                                                                    */
  10. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  11.  
  12. #include "handler.h"
  13.  
  14. #define BMSIZE ((((global->dskenv.de_numblks)-(global->dskenv.de_reservedblks))/32)+1)
  15.  
  16. int AllocBitMap(global)
  17. GLOBAL global;
  18. {
  19.   struct RootBlock *tmpRoot;
  20.   char *tmpblk;
  21.   register int i, size = BMSIZE*4;
  22.  
  23.   /* allocate memory for the bit map in long words */
  24.   if ((global->bitmap.bm_bitmap = (ULONG *)
  25.        AllocMem(size,MEMF_PUBLIC|MEMF_CLEAR))==NULL) {
  26.     BUG(("AllocBitMap Failed\n"));
  27.     return(NULL);
  28.   }
  29.   BUG(("AllocBitMap - root %ld - bitmap %08lx - size %ld\n",
  30.         global->Root,global->bitmap.bm_bitmap,BMSIZE));
  31.   tmpRoot = (struct RootBlock *)GetBlock(global,global->Root);
  32.   if (tmpRoot->rb_BitMapFlag == 0)
  33.     {
  34.     /* OH NO!  The bitmap is INVALID!!  Let's call the disk validator */
  35.     return(NULL);
  36.     }
  37.  
  38.   for (i=0; (i<BITMAPSIZE) && (tmpRoot->rb_BitMapPages[i]); i++)
  39.      {
  40.      tmpblk = GetBlock(global,tmpRoot->rb_BitMapPages[i]);
  41.      memcpy((char *)&global->bitmap.bm_bitmap[i*127],&tmpblk[4],min(508,size));
  42.      size -= 508;
  43.      }
  44.   global->bitmap.bm_blocks = i;
  45.   return(-1);
  46. }
  47.  
  48. int FreeBitMap(global)
  49. GLOBAL global;
  50. {
  51.   if (global->bitmap.bm_bitmap) {
  52.     FreeMem((char *)global->bitmap.bm_bitmap,(BMSIZE*4));
  53.     global->bitmap.bm_blocks = 0;
  54.     global->bitmap.bm_dirty = 0;
  55.     global->bitmap.bm_bitmap = NULL;
  56.     return(-1);
  57.   }
  58.   return(NULL);
  59. }
  60.  
  61. int CountBlocks(global)
  62. GLOBAL global;
  63. {
  64.   register int block, bit, count = 0;
  65.  
  66.   /* count number of used blocks.  bit is 0 if used, 1 if free */
  67.   for (block=0; block<BMSIZE; block++)
  68.     for (bit=0; bit<32; bit++) {
  69.       if ((block == BMSIZE-1) && (bit > 29)) continue;
  70.       if (!(global->bitmap.bm_bitmap[block] & (1<<bit))) {
  71.         count++;
  72.       }
  73.     }
  74.   return(count);
  75. }
  76.  
  77. void DoCheckSum(global,block)
  78. GLOBAL global;
  79. char *block;
  80. {
  81.   struct DirBlock *dblock;
  82.   register ULONG *ptr;
  83.   register ULONG checksum;
  84.  
  85.   dblock = (struct DirBlock *)block;
  86.   dblock->db_CheckSum = checksum = 0;
  87.   for (ptr = (ULONG *)dblock; ptr < (ULONG *)(dblock+1);)
  88.      checksum -= *ptr++;
  89.   dblock->db_CheckSum = checksum;
  90. }
  91.  
  92. void WriteBitMap(global)
  93. GLOBAL global;
  94. {
  95.    register int i, j, block;
  96.    long oldbitmap;
  97.    KEY key;
  98.    struct RootBlock *tmproot;
  99.    ULONG *tmpblk;
  100.    int size = BMSIZE*4;
  101.  
  102.    if (global->bitmap.bm_dirty)
  103.       {
  104.       tmproot = (struct RootBlock *)ModBlock(global,global->Root);
  105.       if (tmproot == NULL)
  106.          {
  107.          BUG(("Unable to locate the Root block\n"));
  108.          return;
  109.          }
  110.  
  111.       /* Now update the root block to reset the bitmap valid flag */
  112.       oldbitmap = tmproot->rb_BitMapFlag;
  113.       tmproot->rb_BitMapFlag = 0;
  114.  
  115.       /* Next we need to force the root block out to disk.  Note that we can */
  116.       /* actually get away with not doing this IF it was already invalid on  */
  117.       /* disk */
  118.       if (oldbitmap == NULL)
  119.          {
  120.          /* Ok, so it hasn't been updated - put it out there */
  121.          FlushOne(global, FindBuffer(global,global->Root,0));
  122.          }
  123.  
  124.       /* Next we get to allocate a new bitmap */
  125.       for (block=0; block<global->bitmap.bm_blocks; block++)
  126.          {
  127. #if 0
  128.          key = AllocateBlock(global,global->Root,0);
  129.          if (key == 0)
  130.             {
  131.             /* For some reason there was no room on the disk so we can't put */
  132.             /* the bitmap onto the disk.  Gee, what's a person to do.  This  */
  133.             /* can occur with the standard file handler.                     */
  134.             BUG(("No room to put bitmap on disk\n"));
  135.             return;
  136.             }
  137.  
  138. #endif
  139.          /* I know its not kosher to do this brute force, but I'd like to   */
  140.          /* see it WORK before I get fancy                                  */
  141.          tmproot = (struct RootBlock *)GetBlock(global,global->Root);
  142.          if (tmproot == NULL)
  143.             {
  144.             BUG(("Unable to get root block\n"));
  145.             return;
  146.             }
  147.          
  148.          key = tmproot->rb_BitMapPages[block];
  149.          i = FindBuffer(global, key, 0);  /* do not read from disk */
  150.          if (i == -1)
  151.             {
  152.             /* Some catastrophic error finding a buffer for the bitmap       */
  153.             /* Just propagate the error.  However this error is quite        */
  154.             /* unlikely as we are not asking for any I/O                     */
  155.             BUG(("How can this happen? can't find buffer for bitmap\n"));
  156.             return;
  157.             }
  158.          global->blkbuf[i].bb_used = ST_BITMAP;  /* Prevent the checksum */
  159.          global->blkbuf[i].bb_dirty = 1;         /* make sure it gets written */
  160.          tmpblk = (ULONG *)global->blkbuf[i].bb_blk;
  161.  
  162.          /* clear the destination block (in case we don't use the whole thing) */
  163.          memset((char *)tmpblk,0,sizeof(struct DataBlock));
  164.  
  165.          /* now copy the bitmap to the destination */
  166.          memcpy((char *)&tmpblk[1],
  167.                 (char *)&global->bitmap.bm_bitmap[block*127],
  168.                 min(508, size));
  169.  
  170.          /* Calculate the checksum for the bitmap block we just created */
  171.          for (j=min(127, size/4); j; j--)
  172.             {
  173.             tmpblk[0] -= tmpblk[j];
  174.             }
  175.  
  176.          /* And cause it to be output IMMEDIATELY */
  177.          FlushOne(global, i);
  178.  
  179.          size -= 508;
  180.          }
  181.  
  182.       global->bitmap.bm_dirty = 0;
  183.       tmproot = (struct RootBlock *)ModBlock(global, global->Root);
  184.       if (tmproot == NULL)
  185.          {
  186.          BUG(("Unable to get Root block again!\n"));
  187.          return;
  188.          }
  189.       tmproot->rb_BitMapFlag = -1;
  190.       FlushOne(global, FindBuffer(global,global->Root,0));
  191.    }
  192. }
  193.  
  194.  
  195. void SetBlock(global,key)
  196. GLOBAL global;
  197. KEY key;
  198. {
  199.   ULONG bmindex;
  200.   ULONG bmbit;
  201.  
  202.   bmindex = ((key-global->dskenv.de_reservedblks) >> 5);
  203.   bmbit   = ((key-global->dskenv.de_reservedblks) & 0x1f);
  204.   if (!((global->bitmap.bm_bitmap[bmindex]) & (1<<bmbit)))
  205.      {
  206.      request(global, REQ_GENERAL, "Attempt to allocate used block");
  207.      }
  208.   (global->bitmap.bm_bitmap[bmindex]) &= ~(1<<bmbit);
  209.   global->bitmap.bm_dirty = 1;
  210. }
  211.  
  212. void FreeBlock(global,key)
  213. GLOBAL global;
  214. KEY key;
  215. {
  216.   ULONG bmindex;
  217.   ULONG bmbit;
  218.  
  219.   BUG(("FreeBlock: %ld\n", key));
  220.   bmindex = ((key-global->dskenv.de_reservedblks) >> 5);
  221.   bmbit   = ((key-global->dskenv.de_reservedblks) & 0x1f);
  222.   if ((global->bitmap.bm_bitmap[bmindex]) & (1<<bmbit))
  223.      {
  224.      request(global, REQ_GENERAL, "Attempt to free unused block");
  225.      }
  226.   (global->bitmap.bm_bitmap[bmindex]) |= (1<<bmbit);
  227.   global->bitmap.bm_dirty = 1;
  228. }
  229.  
  230. KEY AllocateBlock(global,key,type)
  231. GLOBAL global;
  232. KEY key;
  233. int type;
  234. {
  235.   KEY trkstart, newkey = 0;
  236.   ULONG bmindex;
  237.   ULONG bmbit;
  238.   register ULONG bmsize = BMSIZE;
  239.  
  240.   if (!(global->bitmap.bm_bitmap))
  241.     AllocBitMap(global);
  242.  
  243.   trkstart = (key - (key - ((key / global->dskenv.de_blkspertrk) * global->dskenv.de_blkspertrk)));
  244.   bmindex = ((trkstart - global->dskenv.de_reservedblks) >> 5);
  245.   bmbit   = ((trkstart - global->dskenv.de_reservedblks) & 0x1f);
  246.  
  247.   while (bmindex<bmsize) {
  248.     if (global->bitmap.bm_bitmap[bmindex] & (1<<bmbit)) break;
  249.     if (++bmbit > 31) bmbit = 0, bmindex++;
  250.   }
  251.   if (bmindex == bmsize) {
  252.     bmbit=0; bmindex=0;
  253.     while (bmindex<bmsize) {
  254.       if (global->bitmap.bm_bitmap[bmindex] & (1<<bmbit)) break;
  255.       if (++bmbit > 31) bmbit = 0, bmindex++;
  256.     }
  257.     if (bmindex == bmsize) {
  258.       request(global,REQ_GENERAL,"Disk FULL on volume");
  259.       return(newkey);
  260.     }
  261.   }
  262.   newkey = (((bmindex)<<5)+bmbit+global->dskenv.de_reservedblks);
  263.   SetBlock(global, newkey);
  264.   /* Force the buffer to be allocated without reading from disk */
  265.   FindBuffer(global, newkey, 0); /* Don't read it in from disk */
  266.  
  267.   BUG(("AllocateBlock: Key %ld\n", newkey));
  268.  
  269.   if ((newkey < global->dskenv.de_reservedblks) ||
  270.       (newkey == global->Root)                  ||
  271.       (newkey > global->dskenv.de_numblks))
  272.      {
  273.      BUG(("Allocated block %ld out of range %ld-%ld\n", newkey, global->dskenv.de_reservedblks,global->dskenv.de_numblks));
  274.      request(global, REQ_GENERAL, "Key out of range on volume");
  275.      }
  276.   return(newkey);
  277. }
  278.