home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / ramfs102.zip / src / block.c < prev    next >
C/C++ Source or Header  |  2002-03-21  |  10KB  |  410 lines

  1. #include "includes.h"
  2.  
  3.  
  4.  
  5. #define MIN(a,b)    ((a) < (b) ? (a) : (b))
  6.  
  7. #define GRANULARITY    4096     /* Smallest allocation unit */
  8.  
  9.  
  10.  
  11. /* The data pertinent to a position within a block */
  12. struct bop
  13. {
  14.   unsigned long block_num;      /* Block number */
  15.   unsigned long offset;         /* Offset from beginning of block */
  16.   unsigned long block_size;     /* Size of block */
  17. };
  18.  
  19.  
  20. /* Variable-length clusters */
  21. static struct
  22. {
  23.   unsigned char multiplier;
  24.   unsigned long count;          /* 0 = final block size */
  25. }
  26. blk_size[]=
  27. {
  28.   {1, 2},                       /* First 8K in 4K blocks */
  29.   {4, 4},                       /* Then 16K up to 72K */
  30.   {8, 0},                       /* Switch to 32K till the end */
  31.   /* Marker */
  32.   {0, 0}
  33. };
  34.  
  35.  
  36.  
  37.  
  38. void BlockDirCopy (PVOLUME pVolume, FLAT flatDest, FLAT flatSrc, ULONG cbLen)
  39. {
  40.   LONG      lDelta;
  41.   FLAT      flatSrcEnd;
  42.   POPENFILE pCurOpenfile;
  43.   PCURDIR   pCurCurdir;
  44.   PSEARCH   pCurSearch;
  45.  
  46.   if (cbLen == 0)
  47.     return;
  48.  
  49.   VMCopy (flatDest, flatSrc, cbLen);
  50.  
  51.   flatSrcEnd = flatSrc + cbLen;
  52.   lDelta = flatDest - flatSrc;
  53.  
  54.   pCurOpenfile = pVolume->pFirstOpenfile;
  55.   while (pCurOpenfile != 0)
  56.   {
  57.     if (pCurOpenfile->flatEntry >= flatSrc  &&  pCurOpenfile->flatEntry < flatSrcEnd)
  58.       pCurOpenfile->flatEntry += lDelta;
  59.     pCurOpenfile = pCurOpenfile->pNextOpenfile;
  60.   }
  61.  
  62.   pCurCurdir = pVolume->pFirstCurdir;
  63.   while (pCurCurdir != 0)
  64.   {
  65.     if (pCurCurdir->flatBlkDir >= flatSrc  &&  pCurCurdir->flatBlkDir < flatSrcEnd)
  66.       pCurCurdir->flatBlkDir += lDelta;
  67.     pCurCurdir = pCurCurdir->pNextCurdir;
  68.   }
  69.  
  70.   pCurSearch = pVolume->pFirstSearch;
  71.   while (pCurSearch != 0)
  72.   {
  73.     if (pCurSearch->flatBlkDir >= flatSrc  &&  pCurSearch->flatBlkDir < flatSrcEnd)
  74.       pCurSearch->flatBlkDir += lDelta;
  75.     if (pCurSearch->flatEntry >= flatSrc  &&  pCurSearch->flatEntry < flatSrcEnd)
  76.       pCurSearch->flatEntry += lDelta;
  77.     pCurSearch = pCurSearch->pNextSearch;
  78.   }
  79. }
  80.  
  81.  
  82.  
  83.  
  84. int BlockAlloc (PBLOCK pBlk, ULONG cbSize)
  85. {
  86.   FLAT flat;
  87.  
  88.   flat = 0;
  89.   if (cbSize != 0)
  90.   {
  91.     flat = VMAlloc (ROUNDUP (cbSize));
  92.     if (flat == 0)
  93.       return ERROR_DISK_FULL;
  94.   }
  95.   pBlk->flatAddr = flat;
  96.   pBlk->cbSize = cbSize;
  97.   return NO_ERROR;
  98. }
  99.  
  100.  
  101.  
  102.  
  103. int BlockFree (PBLOCK pBlk)
  104. {
  105.   if (pBlk->cbSize != 0)
  106.     VMFree (pBlk->flatAddr);
  107.   pBlk->flatAddr = 0;
  108.   pBlk->cbSize = 0;
  109.   return NO_ERROR;
  110. }
  111.  
  112.  
  113.  
  114.  
  115. int BlockRealloc (PBLOCK pBlk, ULONG cbNewSize)
  116. {
  117.   if (pBlk->cbSize == 0)
  118.     return BlockAlloc (pBlk, cbNewSize);
  119.  
  120.   if (cbNewSize == 0)
  121.     return BlockFree (pBlk);
  122.  
  123.   if (ROUNDUP(cbNewSize) != ROUNDUP(pBlk->cbSize))
  124.   {
  125.     FLAT flatNew;
  126.  
  127.     flatNew = VMAlloc (ROUNDUP (cbNewSize));
  128.     if (flatNew == 0)
  129.       return ERROR_DISK_FULL;
  130.     VMCopy (flatNew, pBlk->flatAddr, MIN (pBlk->cbSize, cbNewSize));
  131.     VMFree (pBlk->flatAddr);
  132.     pBlk->flatAddr = flatNew;
  133.   }
  134.  
  135.   pBlk->cbSize = cbNewSize;
  136.   return NO_ERROR;
  137. }
  138.  
  139.  
  140.  
  141.  
  142. int BlockReallocDir (PVOLUME pVolume, PBLOCK pBlk, ULONG cbNewSize)
  143. {
  144.  
  145. #ifdef DEBUG
  146.   if (pBlk->cbSize < DIR_DOTSSIZE  ||  cbNewSize < DIR_DOTSSIZE)
  147.   {
  148.     debugging = TRUE;
  149.     DEBUG_PRINTF2 ("\r\n!!! BlockReallocDir oldsize=%lu newsize=%lu\r\n",
  150.            pBlk->cbSize, cbNewSize);
  151.     INT3;
  152.   }
  153. #endif
  154.  
  155.   if (ROUNDUP(cbNewSize) != ROUNDUP(pBlk->cbSize))
  156.   {
  157.     FLAT flatNew;
  158.  
  159.     flatNew = VMAlloc (ROUNDUP (cbNewSize));
  160.     if (flatNew == 0)
  161.       return ERROR_DISK_FULL;
  162.     BlockDirCopy (pVolume, flatNew, pBlk->flatAddr, MIN (pBlk->cbSize, cbNewSize));
  163.     VMFree (pBlk->flatAddr);
  164.     pBlk->flatAddr = flatNew;
  165.   }
  166.  
  167.   pBlk->cbSize = cbNewSize;
  168.   return NO_ERROR;
  169. }
  170.  
  171.  
  172.  
  173.  
  174. int BlockMakeEmptyDir (PBLOCK pBlk)
  175. {
  176.   DIRENTRY Entry;
  177.   ULONG    datiNow;
  178.  
  179.   if (BlockAlloc (pBlk, DIR_DOTSSIZE))
  180.     return ERROR_DISK_FULL;
  181.  
  182.   datiNow = UtilGetDateTime();
  183.  
  184.   Entry.fDOSattr = DOSATTR_DIRECTORY;
  185.   fblock_init(&Entry.fblkFile);
  186.   Entry.blkEA.flatAddr = 0;
  187.   Entry.blkEA.cbSize = 0;
  188.   Entry.datiCreate = datiNow;
  189.   Entry.datiAccess = datiNow;
  190.   Entry.datiWrite  = datiNow;
  191.  
  192.   /* make "." entry */
  193.   Entry.cbName = 1;
  194.   Entry.achName[0] = '.';
  195.   VMWrite (pBlk->flatAddr, &Entry, sizeof(Entry)-sizeof(Entry.achName)+1);
  196.  
  197.   /* make ".." entry */
  198.   Entry.cbName = 2;
  199.   Entry.achName[1] = '.';
  200.   VMWrite (pBlk->flatAddr + sizeof(Entry)-sizeof(Entry.achName)+1, &Entry,
  201.        sizeof(Entry)-sizeof(Entry.achName)+2);
  202.  
  203.   return NO_ERROR;
  204. }
  205.  
  206.  
  207. static void byte_to_block (long b, struct bop *bop)
  208. {
  209.   unsigned long res;
  210.   unsigned int  i = 0;
  211.   unsigned long k, j = 0;
  212.  
  213.   res = b%GRANULARITY;          /* residue */
  214.   b /= GRANULARITY;
  215.   while (1)
  216.   {
  217.     k = b / blk_size[i].multiplier;
  218.     if (k < blk_size[i].count || blk_size[i].count == 0)
  219.     {
  220.       bop->block_size = (unsigned long) blk_size[i].multiplier * GRANULARITY;
  221.       bop->offset=res + (unsigned long) GRANULARITY * (b % blk_size[i].multiplier);
  222.       bop->block_num  = k+j;
  223.       break;
  224.     }
  225.     else
  226.     {
  227.       j += blk_size[i].count;
  228.       b -= (long) blk_size[i].multiplier * blk_size[i].count;
  229.     }
  230.     i++;
  231.   }
  232.   /* bop should be filled at this point */
  233.   return;
  234. }
  235.  
  236.  
  237.  
  238.  
  239. static unsigned long query_block_size (unsigned long num)
  240. {
  241.   unsigned int  i=0;
  242.  
  243.   while (num >= blk_size[i].count && blk_size[i].count != 0)
  244.   {
  245.     num -= blk_size[i].count;
  246.     i++;
  247.   }
  248.   return ((unsigned long) GRANULARITY * blk_size[i].multiplier);
  249. }
  250.  
  251.  
  252.  
  253.  
  254. static FLAT get_blkaddr (FLAT blks, unsigned long blk_num)
  255. {
  256.   FLAT  rc;
  257.  
  258.   VMRead (&rc, blks + (blk_num << 2), 4);
  259.   return rc;
  260. }
  261.  
  262.  
  263.  
  264.  
  265. static void set_blkaddr (FLAT blks, unsigned long blk_num, FLAT value)
  266. {
  267.    VMWrite (blks + (blk_num << 2), &value, 4);
  268. }
  269.  
  270.  
  271.  
  272.  
  273. void read_fblocks (char far *dest, PFBLOCK fblk, unsigned long first, unsigned long len)
  274. {
  275.   struct bop    bop;
  276.   FLAT          addr;
  277.   unsigned long fetch;
  278.  
  279.   while (len > 0)
  280.   {
  281.     byte_to_block(first, &bop);
  282.     /* If the block is not present, panic! */
  283. #ifdef DEBUG
  284.     if (fblk->clusters.cbSize <= (bop.block_num << 2))
  285.     {
  286.       debugging = TRUE;
  287.       DEBUG_PRINTF2 ("\r\n!!! read_fblocks() accesses block %lu outside of %lu bound\r\n",
  288.                      bop.block_num, fblk->clusters.cbSize >> 2);
  289.       INT3;
  290.     }
  291. #endif
  292.     fetch = bop.block_size - bop.offset;
  293.     if(fetch > len)
  294.       fetch=len;
  295.     addr=get_blkaddr (fblk->clusters.flatAddr, bop.block_num);
  296.     DEBUG_PRINTF4 ("\r\nVMRead %lu bytes at blk#%lu (0x%08lx+%lu)", fetch, bop.block_num, addr, bop.offset);
  297.     VMRead(dest, addr + bop.offset, fetch);
  298.     dest  += (unsigned short) fetch;
  299.     first += fetch;
  300.     len   -= fetch;
  301.  }
  302. }
  303.  
  304.  
  305.  
  306.  
  307. void write_fblocks (char far *src, PFBLOCK fblk, unsigned long first, unsigned long len)
  308. {
  309.   struct bop    bop;
  310.   FLAT          addr;
  311.   unsigned long fetch;
  312.  
  313.   while (len > 0)
  314.   {
  315.     byte_to_block (first, &bop);
  316.     /* If the block is not present, panic! */
  317. #ifdef DEBUG
  318.     if(fblk->clusters.cbSize<=(bop.block_num<<2))
  319.     {
  320.       debugging = TRUE;
  321.       DEBUG_PRINTF2 ("\r\n!!! write_fblocks() accesses block %lu outside of %lu bound\r\n",
  322.                      bop.block_num, fblk->clusters.cbSize>>2);
  323.       INT3;
  324.     }
  325. #endif
  326.     fetch = bop.block_size - bop.offset;
  327.     if(fetch > len)
  328.       fetch = len;
  329.     addr = get_blkaddr (fblk->clusters.flatAddr, bop.block_num);
  330.     DEBUG_PRINTF4 ("\r\nVMWrite %lu bytes at blk#%lu (0x%08lx+%lu)", fetch, bop.block_num, addr, bop.offset);
  331.     VMWrite (addr + bop.offset, src, fetch);
  332.     src   += (unsigned short) fetch;
  333.     first += fetch;
  334.     len   -= fetch;
  335.   }
  336. }
  337.  
  338.  
  339.  
  340.  
  341. int chsize_helper (PFBLOCK fblk, unsigned long newsize)
  342. {
  343.   struct bop    bop_old, bop_new;
  344.   unsigned long oldcnt, newcnt; /* block count */
  345.   unsigned long i;
  346.  
  347.   byte_to_block (fblk->fSize, &bop_old);
  348.   byte_to_block (newsize, &bop_new);
  349. #ifdef DEBUG
  350.   if(fblk->clusters.cbSize & 3)
  351.   {
  352.     debugging = TRUE;
  353.     DEBUG_PRINTF1 ("\r\n!!! chsize_helper() detected a misaligned cluster map (size=0x%08lx)\r\n",
  354.                    fblk->clusters);
  355.     INT3;
  356.   }
  357. #endif
  358.   oldcnt = fblk->clusters.cbSize >> 2;
  359.   /* If the last block has 0 bytes, consider it to be empty */
  360.   newcnt = bop_new.block_num + ((bop_new.offset == 0) ? 0 : 1);
  361.   DEBUG_PRINTF3 ("\r\nchsize_helper()  newsize=%lu, oldcnt=%lu, newcnt=%lu",
  362.              newsize, oldcnt, newcnt);
  363.   if(newcnt < oldcnt)
  364.   {
  365.     /* Drop unneeded clusters in case when we don't need more */
  366.     for(i = newcnt; i < oldcnt; i++)
  367.     {
  368.       DEBUG_PRINTF2 ("\r\nVMFree blk#%lu (0x%08lx)", i, get_blkaddr (fblk->clusters.flatAddr, i));
  369.       VMFree(get_blkaddr(fblk->clusters.flatAddr, i));
  370.     }
  371.     if (BlockRealloc (&fblk->clusters, newcnt << 2))
  372.       return ERROR_DISK_FULL;
  373.   }
  374.   else if (newcnt > oldcnt)
  375.   {
  376.     if (BlockRealloc (&fblk->clusters, newcnt<<2))
  377.       return ERROR_DISK_FULL;
  378.     /* Allocate new clusters */
  379.     for (i = oldcnt; i < newcnt; i++)
  380.     {
  381.       set_blkaddr(fblk->clusters.flatAddr, i, VMAlloc (query_block_size (i)));
  382.       DEBUG_PRINTF3 ("\r\nVMAlloc %lu bytes for blk#%lu = 0x%08lx", query_block_size (i), i, get_blkaddr (fblk->clusters.flatAddr, i));
  383.     }
  384.   }
  385.   /* Set the new file size */
  386.   fblk->fSize = newsize;
  387.   return NO_ERROR;
  388. }
  389.  
  390.  
  391.  
  392.  
  393. int fblock_init (PFBLOCK fblk)
  394. {
  395.   fblk->fSize = 0;
  396.   DEBUG_PRINTF1 ("\r\nfblock_init(), new block at 0x%08lx", fblk);
  397.   return (BlockAlloc (&fblk->clusters, 0));
  398. }
  399.  
  400.  
  401.  
  402.  
  403. void fblock_shutdown (PFBLOCK fblk)
  404. {
  405.   DEBUG_PRINTF1 ("\r\nfblock_shutdown(), launching chsize_helper(0x%08lx, 0) for cleanup", fblk);
  406.   chsize_helper (fblk, 0);
  407.   BlockFree (&fblk->clusters);
  408.   fblk->fSize=0;
  409. }
  410.