// === PROTOTYPES ===
int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
+tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName, Uint Flags);
tVFS_Node *Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
int Ext2_Unlink(tVFS_Node *Node, const char *OldName);
int Ext2_Link(tVFS_Node *Parent, const char *Name, tVFS_Node *Node);
*/
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);
+
+ if( dirent.rec_len == 0 ) {
+ size = 0;
+ break;
+ }
+
ofs += dirent.rec_len;
size -= dirent.rec_len;
entNum ++;
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;
}
* \param Filename Name of wanted file
* \return VFS Node of file
*/
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename)
+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)
{
VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
- // TODO: Possible overrun if name_len == 255?
- dirent.name[ dirent.name_len ] = '\0'; // Cap off string
// If it matches, create a node and return it
- if(dirent.name_len == filenameLen && strcmp(dirent.name, Filename) == 0)
+ if(dirent.name_len == filenameLen && strncmp(dirent.name, Filename, filenameLen) == 0)
return Ext2_int_CreateNode( disk, dirent.inode );
+ if( dirent.rec_len == 0 )
+ break;
// Increment pointers
ofs += dirent.rec_len;
size -= 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 )
+ break;
}
}
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
int block = 0, ofs = 0;
Uint size;
- void *blockData;
int bestMatch = -1;
int bestSize=0, bestBlock=0, bestOfs=0, bestNeedsSplit=0;
int nEntries;
ENTER("pNode sName pChild",
Node, Name, Child);
- blockData = malloc(disk->BlockSize);
-
- // Read child inode (get's the file type)
- Ext2_int_ReadInode(disk, Child->Inode, &inode);
+ void *blockData = malloc(disk->BlockSize);
// 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;
LOG(" name='%.*s'", dirent->name_len, dirent->name);
if(strncmp(Name, dirent->name, dirent->name_len) == 0) {
//Ext2_int_UnlockInode(disk, Node->Inode);
- Mutex_Release(&Node->Lock);
- LEAVE('i', 1);
- return 1; // ERR_???
+ goto _err;
}
int spare_space = dirent->rec_len - (dirent->name_len + EXT2_DIRENT_SIZE);
// 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;
Child->Flags |= VFS_FFLAG_DIRTY;
//Ext2_int_UnlockInode(disk, Node->Inode);
+ free(blockData);
Mutex_Release(&Node->Lock);
LEAVE('i', 0);
return 0;
+_err:
+ free(blockData);
+ Mutex_Release(&Node->Lock);
+ LEAVE('i', 1);
+ return 1; // ERR_???
}