X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FFilesystems%2FFS_Ext2%2Fwrite.c;fp=Modules%2FFilesystems%2FFS_Ext2%2Fwrite.c;h=0000000000000000000000000000000000000000;hb=923a9dc473851ec2bb1c94021bbf139724e7e8a5;hp=950f6d59d7720109126ecf712ba4fe36bdae3c8c;hpb=f4646f2b6d64e42d1eec1d97877ae23eac6863f6;p=tpg%2Facess2.git diff --git a/Modules/Filesystems/FS_Ext2/write.c b/Modules/Filesystems/FS_Ext2/write.c deleted file mode 100644 index 950f6d59..00000000 --- a/Modules/Filesystems/FS_Ext2/write.c +++ /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; -}