Fixes and Cleanup
[tpg/acess2.git] / Kernel / vfs / fs / ext2.c
diff --git a/Kernel/vfs/fs/ext2.c b/Kernel/vfs/fs/ext2.c
deleted file mode 100644 (file)
index 0b60e54..0000000
+++ /dev/null
@@ -1,744 +0,0 @@
-/*\r
- * Acess OS\r
- * Ext2 Driver Version 1\r
- */\r
-/**\r
- * \file fs/ext2.c\r
- * \brief Second Extended Filesystem Driver\r
- * \todo Implement file full write support\r
- */\r
-#define DEBUG  1\r
-#define VERBOSE        0\r
-#include <common.h>\r
-#include <vfs.h>\r
-#include <modules.h>\r
-#include "fs_ext2.h"\r
-\r
-#define EXT2_UPDATE_WRITEBACK  1\r
-\r
-// === STRUCTURES ===\r
-typedef struct {\r
-        int    FD;\r
-        int    CacheID;\r
-       tVFS_Node       RootNode;\r
-       \r
-       tExt2_SuperBlock        SuperBlock;\r
-        int    BlockSize;\r
-        \r
-        int    GroupCount;\r
-       tExt2_Group             Groups[];\r
-} tExt2_Disk;\r
-\r
-// === PROTOTYPES ===\r
- int   Ext2_Install(char **Arguments);\r
-// Interface Functions\r
-tVFS_Node      *Ext2_InitDevice(char *Device, char **Options);\r
-void           Ext2_Unmount(tVFS_Node *Node);\r
-Uint64         Ext2_Read(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-Uint64         Ext2_Write(tVFS_Node *node, Uint64 offset, Uint64 length, void *buffer);\r
-void           Ext2_CloseFile(tVFS_Node *Node);\r
-char           *Ext2_ReadDir(tVFS_Node *Node, int Pos);\r
-tVFS_Node      *Ext2_FindDir(tVFS_Node *Node, char *FileName);\r
- int           Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);\r
-// Internal Helpers\r
- int           Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
-tVFS_Node      *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);\r
- int           Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode);\r
-Uint64         Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum);\r
-Uint32         Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent);\r
-Uint32         Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock);\r
-void           Ext2_int_UpdateSuperblock(tExt2_Disk *Disk);\r
-\r
-// === SEMI-GLOBALS ===\r
-MODULE_DEFINE(0, 0x5B /*v0.90*/, EXT2, Ext2_Install, NULL);\r
-tExt2_Disk     gExt2_disks[6];\r
- int   giExt2_count = 0;\r
-tVFS_Driver    gExt2_FSInfo = {\r
-       "ext2", 0, Ext2_InitDevice, Ext2_Unmount, NULL\r
-       };\r
-\r
-// === CODE ===\r
-\r
-/**\r
- * \fn int Ext2_Install(char **Arguments)\r
- * \brief Install the Ext2 Filesystem Driver\r
- */\r
-int Ext2_Install(char **Arguments)\r
-{\r
-       VFS_AddDriver( &gExt2_FSInfo );\r
-       return 1;\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
- \brief Initializes a device to be read by by the driver\r
- \param Device String - Device to read from\r
- \param Options        NULL Terminated array of option strings\r
- \return Root Node\r
-*/\r
-tVFS_Node *Ext2_InitDevice(char *Device, char **Options)\r
-{\r
-       tExt2_Disk      *disk;\r
-        int    fd;\r
-        int    groupCount;\r
-       tExt2_SuperBlock        sb;\r
-       tExt2_Inode     inode;\r
-       \r
-       ENTER("sDevice pOptions", Device, Options);\r
-       \r
-       // Open Disk\r
-       fd = VFS_Open(Device, VFS_OPENFLAG_READ|VFS_OPENFLAG_WRITE);            //Open Device\r
-       if(fd == -1) {\r
-               Warning("[EXT2 ] Unable to open '%s'", Device);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Read Superblock at offset 1024\r
-       VFS_ReadAt(fd, 1024, 1024, &sb);        // Read Superblock\r
-       \r
-       // Sanity Check Magic value\r
-       if(sb.s_magic != 0xEF53) {\r
-               Warning("[EXT2 ] Volume '%s' is not an EXT2 volume", Device);\r
-               VFS_Close(fd);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Get Group count\r
-       groupCount = DivUp(sb.s_blocks_count, sb.s_blocks_per_group);\r
-       LOG("groupCount = %i", groupCount);\r
-       \r
-       // Allocate Disk Information\r
-       disk = malloc(sizeof(tExt2_Disk) + sizeof(tExt2_Group)*groupCount);\r
-       if(!disk) {\r
-               Warning("[EXT2 ] Unable to allocate disk structure");\r
-               VFS_Close(fd);\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       disk->FD = fd;\r
-       memcpy(&disk->SuperBlock, &sb, 1024);\r
-       disk->GroupCount = groupCount;\r
-       \r
-       // Get an inode cache handle\r
-       disk->CacheID = Inode_GetHandle();\r
-       \r
-       // Get Block Size\r
-       LOG("s_log_block_size = 0x%x", sb.s_log_block_size);\r
-       disk->BlockSize = 1024 << sb.s_log_block_size;\r
-       \r
-       // Read Group Information\r
-       VFS_ReadAt(\r
-               disk->FD,\r
-               sb.s_first_data_block * disk->BlockSize + 1024,\r
-               sizeof(tExt2_Group)*groupCount,\r
-               disk->Groups\r
-               );\r
-       \r
-       #if VERBOSE\r
-       LOG("Block Group 0");\r
-       LOG(".bg_block_bitmap = 0x%x", disk->Groups[0].bg_block_bitmap);\r
-       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[0].bg_inode_bitmap);\r
-       LOG(".bg_inode_table = 0x%x", disk->Groups[0].bg_inode_table);\r
-       LOG("Block Group 1");\r
-       LOG(".bg_block_bitmap = 0x%x", disk->Groups[1].bg_block_bitmap);\r
-       LOG(".bg_inode_bitmap = 0x%x", disk->Groups[1].bg_inode_bitmap);\r
-       LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
-       #endif\r
-       \r
-       // Get root Inode\r
-       Ext2_int_ReadInode(disk, 2, &inode);\r
-       \r
-       // Create Root Node\r
-       memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
-       disk->RootNode.Inode = 2;       // Root inode ID\r
-       disk->RootNode.ImplPtr = disk;  // Save disk pointer\r
-       disk->RootNode.Size = -1;       // Fill in later (on readdir)\r
-       disk->RootNode.Flags = VFS_FFLAG_DIRECTORY;\r
-       \r
-       disk->RootNode.ReadDir = Ext2_ReadDir;\r
-       disk->RootNode.FindDir = Ext2_FindDir;\r
-       //disk->RootNode.Relink = Ext2_Relink;\r
-       \r
-       // Complete root node\r
-       disk->RootNode.UID = inode.i_uid;\r
-       disk->RootNode.GID = inode.i_gid;\r
-       disk->RootNode.NumACLs = 1;\r
-       disk->RootNode.ACLs = &gVFS_ACL_EveryoneRW;\r
-       \r
-       #if DEBUG\r
-       LOG("inode.i_size = 0x%x", inode.i_size);\r
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
-       #endif\r
-       \r
-       LEAVE('p', &disk->RootNode);\r
-       return &disk->RootNode;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_Unmount(tVFS_Node *Node)\r
- * \brief Close a mounted device\r
- */\r
-void Ext2_Unmount(tVFS_Node *Node)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       \r
-       VFS_Close( disk->FD );\r
-       Inode_ClearCache( disk->CacheID );\r
-       memset(disk, 0, sizeof(tExt2_Disk)+disk->GroupCount*sizeof(tExt2_Group));\r
-       free(disk);\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
- * \brief Read from a file\r
- */\r
-Uint64 Ext2_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       tExt2_Inode     inode;\r
-       Uint64  base;\r
-       Uint    block;\r
-       Uint64  remLen;\r
-       \r
-       ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);\r
-       \r
-       // Get Inode\r
-       Ext2_int_GetInode(Node, &inode);\r
-       \r
-       // Sanity Checks\r
-       if(Offset >= inode.i_size) {\r
-               LEAVE('i', 0);\r
-               return 0;\r
-       }\r
-       if(Offset + Length > inode.i_size)\r
-               Length = inode.i_size - Offset;\r
-       \r
-       block = Offset / disk->BlockSize;\r
-       Offset = Offset / disk->BlockSize;\r
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
-       if(base == 0) {\r
-               Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);\r
-               LEAVE('i', 0);\r
-               return 0;\r
-       }\r
-       \r
-       // Read only block\r
-       if(Length <= disk->BlockSize - Offset)\r
-       {\r
-               VFS_ReadAt( disk->FD, base+Offset, Length, Buffer);\r
-               LEAVE('X', Length);\r
-               return Length;\r
-       }\r
-       \r
-       // Read first block\r
-       remLen = Length;\r
-       VFS_ReadAt( disk->FD, base + Offset, disk->BlockSize - Offset, Buffer);\r
-       remLen -= disk->BlockSize - Offset;\r
-       Buffer += disk->BlockSize - Offset;\r
-       block ++;\r
-       \r
-       // Read middle blocks\r
-       while(remLen > disk->BlockSize)\r
-       {\r
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
-               if(base == 0) {\r
-                       Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);\r
-                       LEAVE('i', 0);\r
-                       return 0;\r
-               }\r
-               VFS_ReadAt( disk->FD, base, disk->BlockSize, Buffer);\r
-               Buffer += disk->BlockSize;\r
-               remLen -= disk->BlockSize;\r
-               block ++;\r
-       }\r
-       \r
-       // Read last block\r
-       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
-       VFS_ReadAt( disk->FD, base, remLen, Buffer);\r
-       \r
-       LEAVE('X', Length);\r
-       return Length;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
- * \brief Write to a file\r
- */\r
-Uint64 Ext2_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       tExt2_Inode     inode;\r
-       Uint64  base;\r
-       Uint64  retLen;\r
-       Uint    block;\r
-       Uint64  allocSize;\r
-        int    bNewBlocks = 0;\r
-       \r
-       Debug_HexDump("Ext2_Write", Buffer, Length);\r
-       \r
-       Ext2_int_GetInode(Node, &inode);\r
-       \r
-       // Get the ammount of space already allocated\r
-       // - Round size up to block size\r
-       // - block size is a power of two, so this will work\r
-       allocSize = (inode.i_size + disk->BlockSize) & ~(disk->BlockSize-1);\r
-       \r
-       // Are we writing to inside the allocated space?\r
-       if( Offset < allocSize )\r
-       {\r
-               // Will we go out of it?\r
-               if(Offset + Length > allocSize) {\r
-                       bNewBlocks = 1;\r
-                       retLen = allocSize - Offset;\r
-               } else\r
-                       retLen = Length;\r
-               \r
-               // Within the allocated space\r
-               block = Offset / disk->BlockSize;\r
-               Offset %= disk->BlockSize;\r
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
-               \r
-               // Write only block (if only one)\r
-               if(Offset + retLen <= disk->BlockSize) {\r
-                       VFS_WriteAt(disk->FD, base+Offset, retLen, Buffer);\r
-                       if(!bNewBlocks) return Length;\r
-                       goto addBlocks; // Ugh! A goto, but it seems unavoidable\r
-               }\r
-               \r
-               // Write First Block\r
-               VFS_WriteAt(disk->FD, base+Offset, disk->BlockSize-Offset, Buffer);\r
-               Buffer += disk->BlockSize-Offset;\r
-               retLen -= disk->BlockSize-Offset;\r
-               block ++;\r
-               \r
-               // Write middle blocks\r
-               while(retLen > disk->BlockSize)\r
-               {\r
-                       base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
-                       VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);\r
-                       Buffer += disk->BlockSize;\r
-                       retLen -= disk->BlockSize;\r
-                       block ++;\r
-               }\r
-               \r
-               // Write last block\r
-               base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);\r
-               VFS_WriteAt(disk->FD, base, retLen, Buffer);\r
-               if(!bNewBlocks) return Length;  // Writing in only allocated space\r
-       }\r
-       \r
-addBlocks:\r
-       ///\todo Implement block allocation\r
-       Warning("[EXT2] File extending is not yet supported");\r
-       \r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_CloseFile(tVFS_Node *Node)\r
- * \brief Close a file (Remove it from the cache)\r
- */\r
-void Ext2_CloseFile(tVFS_Node *Node)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       Inode_UncacheNode(disk->CacheID, Node->Inode);\r
-       return ;\r
-}\r
-\r
-/**\r
- \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)\r
- \brief Reads a directory entry\r
-*/\r
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos)\r
-{\r
-       tExt2_Inode     inode;\r
-       char    namebuf[EXT2_NAME_LEN+1];\r
-       tExt2_DirEnt    dirent;\r
-       Uint64  Base;   // Block's Base Address\r
-        int    block = 0, ofs = 0;\r
-        int    entNum = 0;\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       Uint    size;\r
-       \r
-       ENTER("pNode iPos", Node, Pos);\r
-       \r
-       // Read directory's inode\r
-       Ext2_int_GetInode(Node, &inode);\r
-       size = inode.i_size;\r
-       \r
-       LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);\r
-       \r
-       // Find Entry\r
-       // Get First Block\r
-       // - Do this ourselves as it is a simple operation\r
-       Base = inode.i_block[0] * disk->BlockSize;\r
-       while(Pos -- && size > 0)\r
-       {\r
-               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);\r
-               ofs += dirent.rec_len;\r
-               size -= dirent.rec_len;\r
-               entNum ++;\r
-               \r
-               if(ofs >= disk->BlockSize) {\r
-                       block ++;\r
-                       if( ofs > disk->BlockSize ) {\r
-                               Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring",\r
-                                       entNum-1, Node->Inode);\r
-                       }\r
-                       ofs = 0;\r
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );\r
-               }\r
-       }\r
-       \r
-       // Check for the end of the list\r
-       if(size <= 0) {\r
-               LEAVE('n');\r
-               return NULL;\r
-       }\r
-       \r
-       // Read Entry\r
-       VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );\r
-       //LOG("dirent.inode = %i", dirent.inode);\r
-       //LOG("dirent.rec_len = %i", dirent.rec_len);\r
-       //LOG("dirent.name_len = %i", dirent.name_len);\r
-       VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );\r
-       namebuf[ dirent.name_len ] = '\0';      // Cap off string\r
-       \r
-       \r
-       // Ignore . and .. (these are done in the VFS)\r
-       if( (namebuf[0] == '.' && namebuf[1] == '\0')\r
-       ||  (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {\r
-               LEAVE('p', VFS_SKIP);\r
-               return VFS_SKIP;        // Skip\r
-       }\r
-       \r
-       LEAVE('s', namebuf);\r
-       // Create new node\r
-       return strdup(namebuf);\r
-}\r
-\r
-/**\r
- \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)\r
- \brief Gets information about a file\r
- \param node   vfs node - Parent Node\r
- \param filename       String - Name of file\r
- \return VFS Node of file\r
-*/\r
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)\r
-{\r
-       tExt2_Disk      *disk = Node->ImplPtr;\r
-       tExt2_Inode     inode;\r
-       char    namebuf[EXT2_NAME_LEN+1];\r
-       tExt2_DirEnt    dirent;\r
-       Uint64  Base;   // Block's Base Address\r
-        int    block = 0, ofs = 0;\r
-        int    entNum = 0;\r
-       Uint    size;\r
-       \r
-       // Read directory's inode\r
-       Ext2_int_GetInode(Node, &inode);\r
-       size = inode.i_size;\r
-       \r
-       // Get First Block\r
-       // - Do this ourselves as it is a simple operation\r
-       Base = inode.i_block[0] * disk->BlockSize;\r
-       // Find File\r
-       while(size > 0)\r
-       {\r
-               VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);\r
-               VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );\r
-               namebuf[ dirent.name_len ] = '\0';      // Cap off string\r
-               // If it matches, create a node and return it\r
-               if(strcmp(namebuf, Filename) == 0)\r
-                       return Ext2_int_CreateNode( disk, dirent.inode, namebuf );\r
-               // Increment pointers\r
-               ofs += dirent.rec_len;\r
-               size -= dirent.rec_len;\r
-               entNum ++;\r
-               \r
-               // Check for end of block\r
-               if(ofs >= disk->BlockSize) {\r
-                       block ++;\r
-                       if( ofs > disk->BlockSize ) {\r
-                               Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring",\r
-                                       entNum-1, Node->Inode);\r
-                       }\r
-                       ofs = 0;\r
-                       Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );\r
-               }\r
-       }\r
-       \r
-       return NULL;\r
-}\r
-\r
-/**\r
- * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)\r
- * \brief Create a new node\r
- */\r
-int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)\r
-{\r
-       return 0;\r
-}\r
-\r
-//==================================\r
-//=       INTERNAL FUNCTIONS       =\r
-//==================================\r
-\r
-\r
-/**\r
- * \fn int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
- * \brief Gets the inode descriptor for a node\r
- * \param Node node to get the Inode of\r
- * \param Inode        Destination\r
- */\r
-int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode)\r
-{\r
-       return Ext2_int_ReadInode(Node->ImplPtr, Node->Inode, Inode);\r
-}\r
-\r
-/**\r
- * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)\r
- * \brief Create a new VFS Node\r
- */\r
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)\r
-{\r
-       tExt2_Inode     inode;\r
-       tVFS_Node       retNode;\r
-       tVFS_Node       *tmpNode;\r
-       \r
-       if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )\r
-               return NULL;\r
-       \r
-       if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )\r
-               return tmpNode;\r
-       \r
-       \r
-       // Set identifiers\r
-       retNode.Inode = InodeID;\r
-       retNode.ImplPtr = Disk;\r
-       \r
-       // Set file length\r
-       retNode.Size = inode.i_size;\r
-       \r
-       // Set Access Permissions\r
-       retNode.UID = inode.i_uid;\r
-       retNode.GID = inode.i_gid;\r
-       retNode.NumACLs = 3;\r
-       retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);\r
-       \r
-       //  Set Function Pointers\r
-       retNode.Read = Ext2_Read;\r
-       retNode.Write = Ext2_Write;\r
-       retNode.Close = Ext2_CloseFile;\r
-       \r
-       switch(inode.i_mode & EXT2_S_IFMT)\r
-       {\r
-       // Symbolic Link\r
-       case EXT2_S_IFLNK:\r
-               retNode.Flags = VFS_FFLAG_SYMLINK;\r
-               break;\r
-       // Regular File\r
-       case EXT2_S_IFREG:\r
-               retNode.Flags = 0;\r
-               retNode.Size |= (Uint64)inode.i_dir_acl << 32;\r
-               break;\r
-       // Directory\r
-       case EXT2_S_IFDIR:\r
-               retNode.ReadDir = Ext2_ReadDir;\r
-               retNode.FindDir = Ext2_FindDir;\r
-               retNode.MkNod = Ext2_MkNod;\r
-               //retNode.Relink = Ext2_Relink;\r
-               retNode.Flags = VFS_FFLAG_DIRECTORY;\r
-               break;\r
-       // Unknown, Write protect and hide it to be safe \r
-       default:\r
-               retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;\r
-               break;\r
-       }\r
-       \r
-       // Check if the file should be hidden\r
-       //if(Name[0] == '.')    retNode.Flags |= VFS_FFLAG_HIDDEN;\r
-       \r
-       // Set Timestamps\r
-       retNode.ATime = now();\r
-       retNode.MTime = inode.i_mtime * 1000;\r
-       retNode.CTime = inode.i_ctime * 1000;\r
-       \r
-       // Save in node cache and return saved node\r
-       return Inode_CacheNode(Disk->CacheID, &retNode);\r
-}\r
-\r
-/**\r
- * \fn int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
- * \brief Read an inode into memory\r
- */\r
-int Ext2_int_ReadInode(tExt2_Disk *Disk, Uint InodeId, tExt2_Inode *Inode)\r
-{\r
-        int    group, subId;\r
-       \r
-       //LogF("Ext2_int_ReadInode: (Disk=%p, InodeId=%i, Inode=%p)", Disk, InodeId, Inode);\r
-       //ENTER("pDisk iInodeId pInode", Disk, InodeId, Inode);\r
-       \r
-       if(InodeId == 0)        return 0;\r
-       \r
-       InodeId --;     // Inodes are numbered starting at 1\r
-       \r
-       group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
-       subId = InodeId % Disk->SuperBlock.s_inodes_per_group;\r
-       \r
-       //LOG("group=%i, subId = %i", group, subId);\r
-       \r
-       // Read Inode\r
-       VFS_ReadAt(Disk->FD,\r
-               Disk->Groups[group].bg_inode_table * Disk->BlockSize + sizeof(tExt2_Inode)*subId,\r
-               sizeof(tExt2_Inode),\r
-               Inode);\r
-       return 1;\r
-}\r
-\r
-/**\r
- * \fn Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
- * \brief Get the address of a block from an inode's list\r
- * \param Disk Disk information structure\r
- * \param Blocks       Pointer to an inode's block list\r
- * \param BlockNum     Block index in list\r
- */\r
-Uint64 Ext2_int_GetBlockAddr(tExt2_Disk *Disk, Uint32 *Blocks, int BlockNum)\r
-{\r
-       Uint32  *iBlocks;\r
-       // Direct Blocks\r
-       if(BlockNum < 12)\r
-               return (Uint64)Blocks[BlockNum] * Disk->BlockSize;\r
-       \r
-       // Single Indirect Blocks\r
-       iBlocks = malloc( Disk->BlockSize );\r
-       VFS_ReadAt(Disk->FD, (Uint64)Blocks[12]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       \r
-       BlockNum -= 12;\r
-       if(BlockNum < 256) {\r
-               BlockNum = iBlocks[BlockNum];\r
-               free(iBlocks);\r
-               return (Uint64)BlockNum * Disk->BlockSize;\r
-       }\r
-       \r
-       // Double Indirect Blocks\r
-       if(BlockNum < 256*256)\r
-       {\r
-               VFS_ReadAt(Disk->FD, (Uint64)Blocks[13]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-               VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-               BlockNum = iBlocks[BlockNum%256];\r
-               free(iBlocks);\r
-               return (Uint64)BlockNum * Disk->BlockSize;\r
-       }\r
-       // Triple Indirect Blocks\r
-       VFS_ReadAt(Disk->FD, (Uint64)Blocks[14]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[BlockNum/(256*256)]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       VFS_ReadAt(Disk->FD, (Uint64)iBlocks[(BlockNum/256)%256]*Disk->BlockSize, Disk->BlockSize, iBlocks);\r
-       BlockNum = iBlocks[BlockNum%256];\r
-       free(iBlocks);\r
-       return (Uint64)BlockNum * Disk->BlockSize;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
- * \brief Allocate an inode (from the current group preferably)\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param Parent       Inode ID of the parent (used to locate the child nearby)\r
- */\r
-Uint32 Ext2_int_AllocateInode(tExt2_Disk *Disk, Uint32 Parent)\r
-{\r
-//     Uint    block = (Parent - 1) / Disk->SuperBlock.s_inodes_per_group;\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \fn Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)\r
- * \brief Allocate a block from the best possible location\r
- * \param Disk EXT2 Disk Information Structure\r
- * \param PrevBlock    Previous block ID in the file\r
- */\r
-Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 PrevBlock)\r
-{\r
-        int    bpg = Disk->SuperBlock.s_blocks_per_group;\r
-       Uint    blockgroup = PrevBlock / bpg;\r
-       Uint    bitmap[Disk->BlockSize/sizeof(Uint)];\r
-       Uint    bitsperblock = 8*Disk->BlockSize;\r
-        int    i, j = 0;\r
-       Uint    block;\r
-       \r
-       // Are there any free blocks?\r
-       if(Disk->SuperBlock.s_free_blocks_count == 0)   return 0;\r
-       \r
-       if(Disk->Groups[blockgroup].bg_free_blocks_count > 0)\r
-       {\r
-               // Search block group's bitmap\r
-               for(i = 0; i < bpg; i++)\r
-               {\r
-                       // Get the block in the bitmap block\r
-                       j = i & (bitsperblock-1);\r
-                       \r
-                       // Read in if needed\r
-                       if(j == 0) {\r
-                               VFS_ReadAt(\r
-                                       Disk->FD,\r
-                                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,\r
-                                       Disk->BlockSize,\r
-                                       bitmap\r
-                                       );\r
-                       }\r
-                       \r
-                       // Fast Check\r
-                       if( bitmap[j/32] == -1 ) {\r
-                               j = (j + 31) & ~31;\r
-                               continue;\r
-                       }\r
-                       \r
-                       // Is the bit set?\r
-                       if( bitmap[j/32] & (1 << (j%32)) )\r
-                               continue;\r
-                       \r
-                       // Ooh! We found one\r
-                       break;\r
-               }\r
-               if( i < bpg ) {\r
-                       Warning("[EXT2 ] Inconsistency detected, Group Free Block count is non-zero when no free blocks exist");\r
-                       goto    checkAll;       // Search the entire filesystem for a free block\r
-                       // Goto needed for neatness\r
-               }\r
-               \r
-               // Mark as used\r
-               bitmap[j/32] |= (1 << (j%32));\r
-               VFS_WriteAt(\r
-                       Disk->FD,\r
-                       (Uint64)Disk->Groups[blockgroup].bg_block_bitmap + i / bitsperblock,\r
-                       Disk->BlockSize,\r
-                       bitmap\r
-                       );\r
-               block = i;\r
-               Disk->Groups[blockgroup].bg_free_blocks_count --;\r
-       }\r
-       else\r
-       {\r
-       checkAll:\r
-               Warning("[EXT2 ] TODO - Implement using blocks outside the current block group");\r
-               return 0;\r
-       }\r
-       \r
-       // Reduce global count\r
-       Disk->SuperBlock.s_free_blocks_count --;\r
-       #if EXT2_UPDATE_WRITEBACK\r
-       Ext2_int_UpdateSuperblock(Disk);\r
-       #endif\r
-       \r
-       return block;\r
-}\r
-\r
-/**\r
- * \fn void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
- */\r
-void Ext2_int_UpdateSuperblock(tExt2_Disk *Disk)\r
-{\r
-       VFS_WriteAt(Disk->FD, 1024, 1024, &Disk->SuperBlock);\r
-}\r

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