Various changes, most of them involving the FAT and Ext2 Drivers, adding write support
[tpg/acess2.git] / Modules / Filesystems / FS_Ext2 / write.c
diff --git a/Modules/Filesystems/FS_Ext2/write.c b/Modules/Filesystems/FS_Ext2/write.c
deleted file mode 100644 (file)
index 950f6d5..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Acess OS
- * Ext2 Driver Version 1
- */
-/**
- * \file write.c
- * \brief Second Extended Filesystem Driver
- * \todo Implement file full write support
- */
-#define DEBUG  1
-#define VERBOSE        0
-#include "ext2_common.h"
-
-// === PROTOYPES ===
-Uint64         Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);
-Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);
-void   Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
- int   Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
-
-// === CODE ===
-/**
- * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
- * \brief Write to a file
- */
-Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
-{
-       tExt2_Disk      *disk = Node->ImplPtr;
-       tExt2_Inode     inode;
-       Uint64  base;
-       Uint64  retLen;
-       Uint    block;
-       Uint64  allocSize;
-        int    bNewBlocks = 0;
-       
-       Debug_HexDump("Ext2_Write", Buffer, Length);
-       
-       Ext2_int_ReadInode(disk, Node->Inode, &inode);
-       
-       // Get the ammount of space already allocated
-       // - Round size up to block size
-       // - block size is a power of two, so this will work
-       allocSize = (inode.i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
-       
-       // Are we writing to inside the allocated space?
-       if( Offset < allocSize )
-       {
-               // Will we go out of it?
-               if(Offset + Length > allocSize) {
-                       bNewBlocks = 1;
-                       retLen = allocSize - Offset;
-               } else
-                       retLen = Length;
-               
-               // Within the allocated space
-               block = Offset / disk->BlockSize;
-               Offset %= disk->BlockSize;
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               
-               // Write only block (if only one)
-               if(Offset + retLen <= disk->BlockSize) {
-                       VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);
-                       if(!bNewBlocks) return Length;
-                       goto addBlocks; // Ugh! A goto, but it seems unavoidable
-               }
-               
-               // Write First Block
-               VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);
-               Buffer += disk->BlockSize-Offset;
-               retLen -= disk->BlockSize-Offset;
-               block ++;
-               
-               // Write middle blocks
-               while(retLen > disk->BlockSize)
-               {
-                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-                       VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
-                       Buffer += disk->BlockSize;
-                       retLen -= disk->BlockSize;
-                       block ++;
-               }
-               
-               // Write last block
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
-               VFS_WriteAt(disk->FD, base, retLen, Buffer);
-               if(!bNewBlocks) return Length;  // Writing in only allocated space
-       }
-       
-addBlocks:
-       Warning("[EXT2 ] File extending is untested");
-       
-       // Allocate blocks and copy data to them
-       retLen = Length - allocSize;
-       while( retLen > disk->BlockSize )
-       {
-               // Allocate a block
-               block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
-               if(!block)      return Length - retLen;
-               // Add it to this inode
-               if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
-                       Ext2_int_DeallocateBlock(disk, block);
-                       goto ret;
-               }
-               // Copy data to the node
-               base = block * disk->BlockSize;
-               VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
-               // Update pointer and size remaining
-               inode.i_size += disk->BlockSize;
-               Buffer += disk->BlockSize;
-               retLen -= disk->BlockSize;
-       }
-       // Last block :D
-       block = Ext2_int_AllocateBlock(disk, base/disk->BlockSize);
-       if(!block)      goto ret;
-       if( !Ext2_int_AppendBlock(disk, &inode, block) ) {
-               Ext2_int_DeallocateBlock(disk, block);
-               goto ret;
-       }
-       base = block * disk->BlockSize;
-       VFS_WriteAt(disk->FD, base, retLen, Buffer);
-       inode.i_size += retLen;
-       retLen = 0;
-
-ret:   // Makes sure the changes to the inode are committed
-       Ext2_int_WriteInode(disk, Node->Inode, &inode);
-       return Length - retLen;
-}
-
-/**
- * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
- * \brief Allocate a block from the best possible location
- * \param Disk EXT2 Disk Information Structure
- * \param PrevBlock    Previous block ID in the file
- */
-Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)
-{
-        int    bpg = Disk->SuperBlock.s_blocks_per_group;
-       Uint    blockgroup = PrevBlock / bpg;
-       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];
-       Uint    bitsperblock = 8*Disk->BlockSize;
-        int    i, j = 0;
-       Uint    block;
-       
-       // Are there any free blocks?
-       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;
-       
-       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)
-       {
-               // Search block group's bitmap
-               for(i = 0; i < bpg; i++)
-               {
-                       // Get the block in the bitmap block
-                       j = i & (bitsperblock-1);
-                       
-                       // Read in if needed
-                       if(j == 0) {
-                               VFS_ReadAt(
-                                       Disk->FD,
-                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                                       Disk->BlockSize,
-                                       bitmap
-                                       );
-                       }
-                       
-                       // Fast Check
-                       if( bitmap[j/32] == -1 ) {
-                               j = (j + 31) & ~31;
-                               continue;
-                       }
-                       
-                       // Is the bit set?
-                       if( bitmap[j/32] & (1 << (j%32)) )
-                               continue;
-                       
-                       // Ooh! We found one
-                       break;
-               }
-               if( i < bpg ) {
-                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");
-                       goto    checkAll;       // Search the entire filesystem for a free block
-                       // Goto needed for neatness
-               }
-               
-               // Mark as used
-               bitmap[j/32] |= (1 << (j%32));
-               VFS_WriteAt(
-                       Disk->FD,
-                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,
-                       Disk->BlockSize,
-                       bitmap
-                       );
-               block = i;
-               Disk->Groups[blockgroup].bg_free_blocks_count --;
-               #if EXT2_UPDATE_WRITEBACK
-               //Ext2_int_UpdateBlockGroup(Disk, blockgroup);
-               #endif
-       }
-       else
-       {
-       checkAll:
-               Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");
-               return 0;
-       }
-       
-       // Reduce global count
-       Disk->SuperBlock.s_free_blocks_count --;
-       #if EXT2_UPDATE_WRITEBACK
-       Ext2_int_UpdateSuperblock(Disk);
-       #endif
-       
-       return block;
-}
-
-/**
- * \brief Deallocates a block
- */
-void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block)
-{
-}
-
-/**
- * \brief Append a block to an inode
- */
-int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
-{
-        int    nBlocks;
-        int    dwPerBlock = Disk->BlockSize / 4;
-       Uint32  *blocks;
-       Uint32  id1, id2;
-       
-       nBlocks = (Inode->i_size + Disk->BlockSize - 1) / Disk->BlockSize;
-       
-       // Direct Blocks
-       if( nBlocks < 12 ) {
-               Inode->i_block[nBlocks] = Block;
-               return 0;
-       }
-       
-       blocks = malloc( Disk->BlockSize );
-       if(!blocks)     return 1;
-       
-       nBlocks -= 12;
-       // Single Indirect
-       if( nBlocks < dwPerBlock)
-       {
-               // Allocate/Get Indirect block
-               if( nBlocks == 0 ) {
-                       Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !Inode->i_block[12] ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       memset(blocks, 0, Disk->BlockSize); 
-               }
-               else
-                       VFS_ReadAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
-               
-               blocks[nBlocks] = Block;
-               
-               VFS_WriteAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
-               free(blocks);
-               return 0;
-       }
-       
-       nBlocks += dwPerBlock;
-       // Double Indirect
-       if( nBlocks < dwPerBlock*dwPerBlock )
-       {
-               // Allocate/Get Indirect block
-               if( nBlocks == 0 ) {
-                       Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !Inode->i_block[13] ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else
-                       VFS_ReadAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
-               
-               // Allocate / Get Indirect lvl2 Block
-               if( nBlocks % dwPerBlock == 0 ) {
-                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !id1 ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       blocks[nBlocks/dwPerBlock] = id1;
-                       // Write back indirect 1 block
-                       VFS_WriteAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else {
-                       id1 = blocks[nBlocks / dwPerBlock];
-                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-               }
-               
-               blocks[nBlocks % dwPerBlock] = Block;
-               
-               VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-               free(blocks);
-               return 0;
-       }
-       
-       nBlocks -= dwPerBlock*dwPerBlock;
-       // Triple Indirect
-       if( nBlocks < dwPerBlock*dwPerBlock*dwPerBlock )
-       {
-               // Allocate/Get Indirect block
-               if( nBlocks == 0 ) {
-                       Inode->i_block[14] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !Inode->i_block[14] ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else
-                       VFS_ReadAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
-               
-               // Allocate / Get Indirect lvl2 Block
-               if( (nBlocks/dwPerBlock) % dwPerBlock == 0 && nBlocks % dwPerBlock == 0 )
-               {
-                       id1 = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
-                       if( !id1 ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       blocks[nBlocks/dwPerBlock] = id1;
-                       // Write back indirect 1 block
-                       VFS_WriteAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else {
-                       id1 = blocks[nBlocks / (dwPerBlock*dwPerBlock)];
-                       VFS_ReadAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-               }
-               
-               // Allocate / Get Indirect Level 3 Block
-               if( nBlocks % dwPerBlock == 0 ) {
-                       id2 = Ext2_int_AllocateBlock(Disk, id1);
-                       if( !id2 ) {
-                               free(blocks);
-                               return 1;
-                       }
-                       blocks[(nBlocks/dwPerBlock)%dwPerBlock] = id2;
-                       // Write back indirect 1 block
-                       VFS_WriteAt(Disk->FD, id1*Disk->BlockSize, Disk->BlockSize, blocks);
-                       memset(blocks, 0, Disk->BlockSize);
-               }
-               else {
-                       id2 = blocks[(nBlocks/dwPerBlock)%dwPerBlock];
-                       VFS_ReadAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
-               }
-               
-               blocks[nBlocks % dwPerBlock] = Block;
-               
-               VFS_WriteAt(Disk->FD, id2*Disk->BlockSize, Disk->BlockSize, blocks);
-               free(blocks);
-               return 0;
-       }
-       
-       Warning("[EXT2 ] Inode %i cannot have a block appended to it, all indirects used");
-       free(blocks);
-       return 1;
-}

UCC git Repository :: git.ucc.asn.au