*/
int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
- tExt2_Inode inode;
+ tExt2_Inode *inode = (void*)(Node+1);
tExt2_DirEnt dirent;
Uint64 Base; // Block's Base Address
int block = 0;
ENTER("pNode iPos", Node, Pos);
// Read directory's inode
- Ext2_int_ReadInode(disk, Node->Inode, &inode);
- size = inode.i_size;
+ size = inode->i_size;
- LOG("inode={.i_block[0]= 0x%x, .i_size=0x%x}", inode.i_block[0], inode.i_size);
+ LOG("inode={.i_block[0]= 0x%x, .i_size=0x%x}", inode->i_block[0], inode->i_size);
// Find Entry
// Get First Block
// - Do this ourselves as it is a simple operation
- Base = inode.i_block[0] * disk->BlockSize;
+ Base = inode->i_block[0] * disk->BlockSize;
// Scan directory
- while(Pos -- && size > 0 && size <= inode.i_size)
+ while(Pos -- && size > 0 && size <= inode->i_size)
{
VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
ofs += dirent.rec_len;
entNum-1, Node->Inode);
}
ofs = 0;
- Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+ Base = Ext2_int_GetBlockAddr( disk, inode->i_block, block );
if( Base == 0 ) {
size = 0;
break;
}
// Check for the end of the list
- if(size <= 0 || size > inode.i_size) {
+ if(size <= 0 || size > inode->i_size) {
LEAVE('i', -ENOENT);
return -ENOENT;
}
tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename, Uint Flags)
{
tExt2_Disk *disk = Node->ImplPtr;
- tExt2_Inode inode;
+ tExt2_Inode *inode = (void*)(Node+1);
tExt2_DirEnt dirent;
Uint64 Base; // Block's Base Address
int block = 0;
int filenameLen = strlen(Filename);
// Read directory's inode
- Ext2_int_ReadInode(disk, Node->Inode, &inode);
- size = inode.i_size;
+ size = inode->i_size;
// Get First Block
// - Do this ourselves as it is a simple operation
- Base = inode.i_block[0] * disk->BlockSize;
+ Base = inode->i_block[0] * disk->BlockSize;
// Find File
while(size > 0)
{
entNum-1, Node->Inode);
}
ofs = 0;
- Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
+ Base = Ext2_int_GetBlockAddr( disk, inode->i_block, block );
}
}
int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
{
tExt2_Disk *disk = Node->ImplPtr;
- tExt2_Inode inode;
+ tExt2_Inode *inode = (void*)(Node+1);
tExt2_DirEnt *dirent;
tExt2_DirEnt newEntry;
Uint64 base; // Block's Base Address
void *blockData = malloc(disk->BlockSize);
- // Read child inode (get's the file type)
- Ext2_int_ReadInode(disk, Child->Inode, &inode);
-
// Create a stub entry
newEntry.inode = Child->Inode;
newEntry.name_len = strlen(Name);
newEntry.rec_len = ((newEntry.name_len+3)&~3) + EXT2_DIRENT_SIZE;
- newEntry.type = inode.i_mode >> 12;
+ newEntry.type = inode->i_mode >> 12;
memcpy(newEntry.name, Name, newEntry.name_len);
// Read directory's inode
- Ext2_int_ReadInode(disk, Node->Inode, &inode);
- size = inode.i_size;
+ size = inode->i_size;
// Get a lock on the inode
//Ext2_int_LockInode(disk, Node->Inode);
// Get First Block
// - Do this ourselves as it is a simple operation
- base = inode.i_block[0] * disk->BlockSize;
+ base = inode->i_block[0] * disk->BlockSize;
VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
block = 0;
nEntries = 0;
// BLOCK_DIR_OFS(Node->Data, block) = nEntries;
block ++;
ofs = 0;
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
}
}
if( bestMatch >= 0 )
{
// Read-Modify-Write
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, bestBlock);
VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData );
dirent = blockData + bestOfs;
// Shorten a pre-existing entry
else {
// Allocate block, Write
Uint32 newblock = Ext2_int_AllocateBlock(disk, base / disk->BlockSize);
- Ext2_int_AppendBlock(disk, &inode, newblock);
+ Ext2_int_AppendBlock(Node, inode, newblock);
base = newblock * disk->BlockSize;
Node->Size += newEntry.rec_len;
Node->Flags |= VFS_FFLAG_DIRTY;
tVFS_Node *Ext2_InitDevice(const char *Device, const char **Options);\r
void Ext2_Unmount(tVFS_Node *Node);\r
void Ext2_CloseFile(tVFS_Node *Node);\r
+tVFS_Node *Ext2_GetNodeFromINode(tVFS_Node *RootNode, Uint64 Inode);\r
// - Internal Helpers\r
int Ext2_int_GetInode(tVFS_Node *Node, tExt2_Inode *Inode);\r
+void Ext2_int_DumpInode(tExt2_Disk *Disk, Uint32 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
void Ext2_int_DereferenceInode(tExt2_Disk *Disk, Uint32 Inode);\r
.Detect = Ext2_Detect,\r
.InitDevice = Ext2_InitDevice,\r
.Unmount = Ext2_Unmount,\r
- .GetNodeFromINode = NULL\r
+ .GetNodeFromINode = Ext2_GetNodeFromINode\r
};\r
\r
// === CODE ===\r
int fd;\r
int groupCount;\r
tExt2_SuperBlock sb;\r
- tExt2_Inode inode;\r
\r
ENTER("sDevice pOptions", Device, Options);\r
\r
LOG(".bg_inode_table = 0x%x", disk->Groups[1].bg_inode_table);\r
\r
// Get root Inode\r
- Ext2_int_ReadInode(disk, 2, &inode);\r
+ Ext2_int_ReadInode(disk, 2, &disk->RootInode);\r
\r
// Create Root Node\r
memset(&disk->RootNode, 0, sizeof(tVFS_Node));\r
disk->RootNode.Type = &gExt2_DirType;\r
\r
// Complete root node\r
- disk->RootNode.UID = inode.i_uid;\r
- disk->RootNode.GID = inode.i_gid;\r
+ disk->RootNode.UID = disk->RootInode.i_uid;\r
+ disk->RootNode.GID = disk->RootInode.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
+ LOG("inode.i_size = 0x%x", disk->RootInode.i_size);\r
+ LOG("inode.i_block[0] = 0x%x", disk->RootInode.i_block[0]);\r
#endif\r
\r
LEAVE('p', &disk->RootNode);\r
return ;\r
}\r
\r
+tVFS_Node *Ext2_GetNodeFromINode(tVFS_Node *RootNode, Uint64 Inode)\r
+{\r
+ return Ext2_int_CreateNode(RootNode->ImplPtr, Inode);\r
+}\r
+\r
//==================================\r
//= INTERNAL FUNCTIONS =\r
//==================================\r
LEAVE('i', 0);\r
return 0;\r
}\r
- \r
+\r
+ Ext2_int_DumpInode(Disk, InodeId, Inode); \r
+\r
InodeId --; // Inodes are numbered starting at 1\r
\r
group = InodeId / Disk->SuperBlock.s_inodes_per_group;\r
*/\r
tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)\r
{\r
- tExt2_Inode inode;\r
- tVFS_Node retNode;\r
- tVFS_Node *tmpNode;\r
- \r
- if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )\r
+ struct {\r
+ tVFS_Node retNode;\r
+ tExt2_Inode inode;\r
+ } data;\r
+ tVFS_Node *node = &data.retNode;\r
+ tExt2_Inode *in = &data.inode;\r
+ \r
+ if( !Ext2_int_ReadInode(Disk, InodeID, &data.inode) )\r
return NULL;\r
\r
- if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )\r
- return tmpNode;\r
+ if( (node = Inode_GetCache(Disk->CacheID, InodeID)) )\r
+ return node;\r
+ node = &data.retNode;\r
\r
- memset(&retNode, 0, sizeof(retNode)); \r
+ memset(node, 0, sizeof(*node));\r
\r
// Set identifiers\r
- retNode.Inode = InodeID;\r
- retNode.ImplPtr = Disk;\r
- retNode.ImplInt = inode.i_links_count;\r
- if( inode.i_links_count == 0 ) {\r
+ node->Inode = InodeID;\r
+ node->ImplPtr = Disk;\r
+ node->ImplInt = in->i_links_count;\r
+ if( in->i_links_count == 0 ) {\r
Log_Notice("Ext2", "Inode %p:%x is not referenced, bug?", Disk, InodeID);\r
}\r
\r
// Set file length\r
- retNode.Size = inode.i_size;\r
+ node->Size = in->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
+ node->UID = in->i_uid;\r
+ node->GID = in->i_gid;\r
+ node->NumACLs = 3;\r
+ node->ACLs = VFS_UnixToAcessACL(in->i_mode & 0777, in->i_uid, in->i_gid);\r
\r
// Set Function Pointers\r
- retNode.Type = &gExt2_FileType;\r
+ node->Type = &gExt2_FileType;\r
\r
- switch(inode.i_mode & EXT2_S_IFMT)\r
+ switch(in->i_mode & EXT2_S_IFMT)\r
{\r
// Symbolic Link\r
case EXT2_S_IFLNK:\r
- retNode.Flags = VFS_FFLAG_SYMLINK;\r
+ node->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
+ node->Flags = 0;\r
+ node->Size |= (Uint64)in->i_dir_acl << 32;\r
break;\r
// Directory\r
case EXT2_S_IFDIR:\r
- retNode.Type = &gExt2_DirType;\r
- retNode.Flags = VFS_FFLAG_DIRECTORY;\r
- retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) );\r
+ node->Type = &gExt2_DirType;\r
+ node->Flags = VFS_FFLAG_DIRECTORY;\r
+ node->Data = calloc( sizeof(Uint16), DivUp(node->Size, Disk->BlockSize) );\r
break;\r
// Unknown, Write protect it to be safe \r
default:\r
- retNode.Flags = VFS_FFLAG_READONLY;\r
+ node->Flags = VFS_FFLAG_READONLY;\r
break;\r
}\r
\r
// Set Timestamps\r
- retNode.ATime = inode.i_atime * 1000;\r
- retNode.MTime = inode.i_mtime * 1000;\r
- retNode.CTime = inode.i_ctime * 1000;\r
+ node->ATime = in->i_atime * 1000;\r
+ node->MTime = in->i_mtime * 1000;\r
+ node->CTime = in->i_ctime * 1000;\r
\r
// Save in node cache and return saved node\r
- return Inode_CacheNode(Disk->CacheID, &retNode);\r
+ return Inode_CacheNodeEx(Disk->CacheID, &data.retNode, sizeof(data));\r
}\r
\r
int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)\r
{\r
- tExt2_Inode inode = {0};\r
+ tExt2_Inode *inode = (void*)(Node+1);\r
\r
if( Disk != Node->ImplPtr ) {\r
Log_Error("Ext2", "Ext2_int_WritebackNode - Disk != Node->ImplPtr");\r
return -1;\r
}\r
- \r
+\r
if( Node->Flags & VFS_FFLAG_SYMLINK ) {\r
- inode.i_mode = EXT2_S_IFLNK;\r
+ inode->i_mode = EXT2_S_IFLNK;\r
}\r
else if( Node->Flags & VFS_FFLAG_DIRECTORY ) {\r
- inode.i_mode = EXT2_S_IFDIR;\r
+ inode->i_mode = EXT2_S_IFDIR;\r
}\r
else if( Node->Flags & VFS_FFLAG_READONLY ) {\r
Log_Notice("Ext2", "Not writing back readonly inode %p:%x", Disk, Node->Inode);\r
return 1;\r
}\r
else {\r
- inode.i_mode = EXT2_S_IFREG;\r
- inode.i_dir_acl = Node->Size >> 32;\r
+ inode->i_mode = EXT2_S_IFREG;\r
+ inode->i_dir_acl = Node->Size >> 32;\r
}\r
\r
- inode.i_size = Node->Size & 0xFFFFFFFF;\r
- inode.i_links_count = Node->ImplInt;\r
+ inode->i_size = Node->Size & 0xFFFFFFFF;\r
+ inode->i_links_count = Node->ImplInt;\r
\r
- inode.i_uid = Node->UID;\r
- inode.i_gid = Node->GID;\r
+ inode->i_uid = Node->UID;\r
+ inode->i_gid = Node->GID;\r
\r
- inode.i_atime = Node->ATime / 1000;\r
- inode.i_mtime = Node->MTime / 1000;\r
- inode.i_ctime = Node->CTime / 1000;\r
+ inode->i_atime = Node->ATime / 1000;\r
+ inode->i_mtime = Node->MTime / 1000;\r
+ inode->i_ctime = Node->CTime / 1000;\r
\r
// TODO: Compact ACLs into unix mode\r
Log_Warning("Ext2", "TODO: Support converting Acess ACLs into unix modes");\r
+ inode->i_mode |= 777;\r
\r
- Ext2_int_WriteInode(Disk, Node->Inode, &inode);\r
+ Ext2_int_WriteInode(Disk, Node->Inode, inode);\r
\r
return 0;\r
}\r
\r
+void Ext2_int_DumpInode(tExt2_Disk *Disk, Uint32 InodeID, tExt2_Inode *Inode)\r
+{\r
+ LOG("%p[Inode %i] = {", Disk, InodeID);\r
+ LOG(" .i_mode = 0%04o", Inode->i_mode);\r
+ LOG(" .i_uid:i_gid = %i:%i", Inode->i_uid, Inode->i_gid);\r
+ LOG(" .i_size = 0x%x", Inode->i_size);\r
+ LOG(" .i_block[0:3] = {0x%x,0x%x,0x%x,0x%x}",\r
+ Inode->i_block[0], Inode->i_block[1], Inode->i_block[2], Inode->i_block[3]);\r
+ LOG(" .i_block[4:7] = {0x%x,0x%x,0x%x,0x%x}",\r
+ Inode->i_block[4], Inode->i_block[5], Inode->i_block[6], Inode->i_block[7]);\r
+ LOG(" .i_block[8:11] = {0x%x,0x%x,0x%x,0x%x}",\r
+ Inode->i_block[8], Inode->i_block[6], Inode->i_block[10], Inode->i_block[11]);\r
+ LOG(" .i_block[12:14] = {0x%x,0x%x,0x%x}",\r
+ Inode->i_block[12], Inode->i_block[13], Inode->i_block[14]);\r
+ LOG("}");\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
int FD;
tInodeCache *CacheID;
tVFS_Node RootNode;
+ tExt2_Inode RootInode;
tExt2_SuperBlock SuperBlock;
Uint BlockSize;
extern size_t Ext2_Write(tVFS_Node *node, off_t offset, size_t length, const void *buffer, Uint Flags);
extern Uint32 Ext2_int_AllocateBlock(tExt2_Disk *Disk, Uint32 LastBlock);
extern void Ext2_int_DeallocateBlock(tExt2_Disk *Disk, Uint32 Block);
-extern int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block);
+extern int Ext2_int_AppendBlock(tVFS_Node *Node, tExt2_Inode *Inode, Uint32 Block);
#endif
* \brief Second Extended Filesystem Driver
* \todo Implement file full write support
*/
-#define DEBUG 1
+#define DEBUG 0
#define VERBOSE 0
#include "ext2_common.h"
size_t Ext2_Read(tVFS_Node *Node, off_t Offset, size_t Length, void *Buffer, Uint Flags)
{
tExt2_Disk *disk = Node->ImplPtr;
- tExt2_Inode inode;
+ tExt2_Inode *inode = (void*)(Node+1);
Uint64 base;
Uint block;
Uint64 remLen;
- ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
-
- // Get Inode
- Ext2_int_ReadInode(disk, Node->Inode, &inode);
+ ENTER("pNode XOffset xLength pBuffer", Node, Offset, Length, Buffer);
// Sanity Checks
- if(Offset >= inode.i_size) {
+ if(Offset >= inode->i_size) {
LEAVE('i', 0);
return 0;
}
- if(Offset + Length > inode.i_size)
- Length = inode.i_size - Offset;
+ if(Offset + Length > inode->i_size)
+ Length = inode->i_size - Offset;
block = Offset / disk->BlockSize;
- Offset = Offset / disk->BlockSize;
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+ Offset = Offset % disk->BlockSize;
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
if(base == 0) {
- Warning("[EXT2 ] NULL Block Detected in INode 0x%llx", Node->Inode);
+ Log_Warning("EXT2", "NULL Block Detected in INode 0x%llx (Block %i)", Node->Inode, block);
LEAVE('i', 0);
return 0;
}
// Read middle blocks
while(remLen > disk->BlockSize)
{
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
if(base == 0) {
Log_Warning("EXT2", "NULL Block Detected in INode 0x%llx", Node->Inode);
LEAVE('i', 0);
}
// Read last block
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
VFS_ReadAt( disk->FD, base, remLen, Buffer);
LEAVE('X', Length);
* \brief Second Extended Filesystem Driver
* \todo Implement file full write support
*/
-#define DEBUG 1
+#define DEBUG 0
#define VERBOSE 0
#include "ext2_common.h"
// === PROTOYPES ===
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 ===
/**
size_t Ext2_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer, Uint Flags)
{
tExt2_Disk *disk = Node->ImplPtr;
- tExt2_Inode inode;
+ tExt2_Inode *inode = (void*)(Node+1);
Uint64 base;
Uint64 retLen;
Uint block;
//Debug_HexDump("Ext2_Write", Buffer, Length);
// TODO: Handle (Flags & VFS_IOFLAG_NOBLOCK)
-
- 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);
+ allocSize = (inode->i_size + disk->BlockSize-1) & ~(disk->BlockSize-1);
+ LOG("allocSize = %llx, Offset=%llx", allocSize, Offset);
// Are we writing to inside the allocated space?
if( Offset > allocSize ) return 0;
// Within the allocated space
block = Offset / disk->BlockSize;
Offset %= disk->BlockSize;
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
// Write only block (if only one)
if(Offset + retLen <= disk->BlockSize) {
// Write middle blocks
while(retLen > disk->BlockSize)
{
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, block);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, block);
VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
Buffer += disk->BlockSize;
retLen -= disk->BlockSize;
}
// Write last block
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, 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
}
else
- base = Ext2_int_GetBlockAddr(disk, inode.i_block, allocSize/disk->BlockSize-1);
+ base = Ext2_int_GetBlockAddr(disk, inode->i_block, allocSize/disk->BlockSize-1);
addBlocks:
- Log_Notice("EXT2", "File extending is untested");
-
// Allocate blocks and copy data to them
retLen = Length - (allocSize-Offset);
- while( retLen > disk->BlockSize )
+ while( retLen > 0 )
{
+ size_t blk_len = (retLen < disk->BlockSize ? 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) ) {
+ if( Ext2_int_AppendBlock(Node, inode, block) ) {
Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
block, disk, Node->Inode);
Ext2_int_DeallocateBlock(disk, block);
}
// Copy data to the node
base = block * disk->BlockSize;
- VFS_WriteAt(disk->FD, base, disk->BlockSize, Buffer);
+ VFS_WriteAt(disk->FD, base, blk_len, 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) ) {
- Log_Warning("Ext2", "Appending %x to inode %p:%X failed",
- block, disk, Node->Inode);
- Ext2_int_DeallocateBlock(disk, block);
- goto ret;
+ Buffer += blk_len;
+ retLen -= blk_len;
}
- base = block * disk->BlockSize;
- VFS_WriteAt(disk->FD, base, retLen, Buffer);
-
- // TODO: When should the size update be committed?
- inode.i_size += retLen;
- Node->Size += retLen;
- Node->Flags |= VFS_FFLAG_DIRTY;
-
- retLen = 0;
-ret: // Makes sure the changes to the inode are committed
- Ext2_int_WriteInode(disk, Node->Inode, &inode);
- return Length - retLen;
+
+ret:
+ retLen = Length - retLen;
+ if( retLen )
+ {
+ // TODO: When should the size update be committed?
+ inode->i_size += retLen;
+ Node->Size += retLen;
+ Node->Flags |= VFS_FFLAG_DIRTY;
+ //Ext2_int_WriteInode(disk, Node->Inode, inode);
+ }
+ return retLen;
}
/**
// First: Check the next block after `PrevBlock`
int iblock = (PrevBlock + 1) % Disk->SuperBlock.s_blocks_per_group;
+ //LOG("iblock = %i, Disk=%p, blockgroup=%i", iblock, Disk, blockgroup);
if( iblock != 0 && Disk->Groups[blockgroup].bg_free_blocks_count > 0 )
{
- LOG("Checking %i:%i", blockgroup, iblock);
+ //LOG("Checking %i:%i", blockgroup, iblock);
bg = &Disk->Groups[blockgroup];
Uint64 vol_ofs = Disk->BlockSize*bg->bg_block_bitmap+ofs;
VFS_ReadAt(Disk->FD, vol_ofs, sector_size, buf);
- LOG("buf@%llx[%i] = %02x (& %02x)", vol_ofs, byte, buf[byte], bit);
+ //LOG("buf@%llx[%i] = %02x (& %02x)", vol_ofs, byte, buf[byte], bit);
if( (buf[byte] & bit) == 0 )
{
Disk);
return 0;
}
- LOG("BG%i has free blocks", blockgroup);
+ //LOG("BG%i has free blocks", blockgroup);
// Search the bitmap for a free block
bg = &Disk->Groups[blockgroup];
;
if( byte < sector_size )
{
- LOG("buf@%llx[%i] = %02x", vol_ofs, byte, buf[byte]);
+ //LOG("buf@%llx[%i] = %02x", vol_ofs, byte, buf[byte]);
for( bit = 0; bit < 8 && buf[byte] & (1 << bit); bit ++)
;
ASSERT(bit != 8);
#endif
Uint32 ret = blockgroup * Disk->SuperBlock.s_blocks_per_group + byte * 8 + bit;
- Log_Debug("Ext2", "Ext2_int_AllocateBlock - Allocated 0x%x", ret);
+ LOG("Allocated 0x%x", ret);
return ret;
}
} while(ofs < Disk->SuperBlock.s_blocks_per_group / 8);
/**
* \brief Append a block to an inode
*/
-int Ext2_int_AppendBlock(tExt2_Disk *Disk, tExt2_Inode *Inode, Uint32 Block)
+int Ext2_int_AppendBlock(tVFS_Node *Node, tExt2_Inode *Inode, Uint32 Block)
{
+ tExt2_Disk *Disk = Node->ImplPtr;
int nBlocks;
int dwPerBlock = Disk->BlockSize / 4;
Uint32 *blocks;
Uint32 id1, id2;
nBlocks = (Inode->i_size + Disk->BlockSize - 1) / Disk->BlockSize;
+
+ LOG("Append 0x%x to inode [%i]", Block, nBlocks);
// Direct Blocks
if( nBlocks < 12 ) {
// Single Indirect
if( nBlocks < dwPerBlock)
{
+ LOG("Indirect 1 %i", nBlocks);
// Allocate/Get Indirect block
if( nBlocks == 0 ) {
Inode->i_block[12] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
blocks[nBlocks] = Block;
VFS_WriteAt(Disk->FD, Inode->i_block[12]*Disk->BlockSize, Disk->BlockSize, blocks);
+ Node->Flags |= VFS_FFLAG_DIRTY;
free(blocks);
return 0;
}
- nBlocks += dwPerBlock;
+ nBlocks -= dwPerBlock;
// Double Indirect
if( nBlocks < dwPerBlock*dwPerBlock )
{
+ LOG("Indirect 2 %i/%i", nBlocks/dwPerBlock, nBlocks%dwPerBlock);
// Allocate/Get Indirect block
if( nBlocks == 0 ) {
Inode->i_block[13] = Ext2_int_AllocateBlock(Disk, Inode->i_block[0]);
return 1;
}
memset(blocks, 0, Disk->BlockSize);
+ Node->Flags |= VFS_FFLAG_DIRTY;
}
else
VFS_ReadAt(Disk->FD, Inode->i_block[13]*Disk->BlockSize, Disk->BlockSize, blocks);
return 1;
}
memset(blocks, 0, Disk->BlockSize);
+ Node->Flags |= VFS_FFLAG_DIRTY;
}
else
VFS_ReadAt(Disk->FD, Inode->i_block[14]*Disk->BlockSize, Disk->BlockSize, blocks);