#define BLOCK_DIR_OFS(_data, _block) (((Uint16*)(_data))[(_block)])
// === PROTOTYPES ===
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos);
-tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *FileName);
- int Ext2_MkNod(tVFS_Node *Node, const char *Name, Uint Flags);
+ int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
+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);
-// --- Helpers ---
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId);
// === GLOBALS ===
tVFS_NodeType gExt2_DirType = {
* \param Node Directory node
* \param Pos Position of desired element
*/
-char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
+int Ext2_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
{
tExt2_Inode inode;
tExt2_DirEnt dirent;
// Check for the end of the list
if(size <= 0 || size > inode.i_size) {
- LEAVE('n');
- return NULL;
+ LEAVE('i', -ENOENT);
+ return -ENOENT;
}
// Read Entry
dirent.name[ dirent.name_len ] = '\0'; // Cap off string
if( dirent.name_len == 0 ) {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP;
+ LEAVE('i', 1);
+ return 1;
}
// Ignore . and .. (these are done in the VFS)
if( (dirent.name[0] == '.' && dirent.name[1] == '\0')
|| (dirent.name[0] == '.' && dirent.name[1] == '.' && dirent.name[2]=='\0')) {
- LEAVE('p', VFS_SKIP);
- return VFS_SKIP; // Skip
+ LEAVE('i', 1);
+ return 1; // Skip
}
- LEAVE('s', dirent.name);
- // Create new node
- return strdup(dirent.name);
+ LOG("Name '%s'", dirent.name);
+ strncpy(Dest, dirent.name, FILENAME_MAX);
+ LEAVE('i', 0);
+ return 0;
}
/**
* \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;
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 );
// Increment pointers
ofs += dirent.rec_len;
* \fn int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
* \brief Create a new node
*/
-int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
+tVFS_Node *Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags)
{
ENTER("pParent sName xFlags", Parent, Name, Flags);
Uint64 inodeNum = Ext2_int_AllocateInode(Parent->ImplPtr, Parent->Inode);
if( inodeNum == 0 ) {
LOG("Inode allocation failed");
- LEAVE('i', -1);
- return -1;
+ LEAVE_RET('n', NULL);
}
tVFS_Node *child = Ext2_int_CreateNode(Parent->ImplPtr, inodeNum);
if( !child ) {
Ext2_int_DereferenceInode(Parent->ImplPtr, inodeNum);
Log_Warning("Ext2", "Ext2_MkNod - Node creation failed");
- LEAVE('i', -1);
- return -1;
+ LEAVE_RET('n', NULL);
}
child->Flags = Flags & (VFS_FFLAG_DIRECTORY|VFS_FFLAG_SYMLINK|VFS_FFLAG_READONLY);
// TODO: Set up ACLs
int rv = Ext2_Link(Parent, Name, child);
- child->Type->Close(child);
- LEAVE('i', rv);
- return rv;
+ if( rv ) {
+ Ext2_CloseFile(child);
+ return NULL;
+ }
+ LEAVE_RET('p', child);
}
/**
*/
int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child)
{
- #if 1
tExt2_Disk *disk = Node->ImplPtr;
tExt2_Inode inode;
tExt2_DirEnt *dirent;
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);
+ void *blockData = malloc(disk->BlockSize);
// Read child inode (get's the file type)
Ext2_int_ReadInode(disk, Child->Inode, &inode);
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);
Child->Flags |= VFS_FFLAG_DIRTY;
//Ext2_int_UnlockInode(disk, Node->Inode);
+ free(blockData);
Mutex_Release(&Node->Lock);
LEAVE('i', 0);
return 0;
- #else
- Log_Warning("Ext2", "TODO: Impliment Ext2_Link");
- return 1;
- #endif
-}
-
-// ---- INTERNAL FUNCTIONS ----
-/**
- * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)
- * \brief Create a new VFS Node
- */
-tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)
-{
- tExt2_Inode inode;
- tVFS_Node retNode;
- tVFS_Node *tmpNode;
-
- if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
- return NULL;
-
- if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
- return tmpNode;
-
- memset(&retNode, 0, sizeof(retNode));
-
- // Set identifiers
- retNode.Inode = InodeID;
- retNode.ImplPtr = Disk;
- retNode.ImplInt = inode.i_links_count;
-
- // Set file length
- retNode.Size = inode.i_size;
-
- // Set Access Permissions
- retNode.UID = inode.i_uid;
- retNode.GID = inode.i_gid;
- retNode.NumACLs = 3;
- retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
-
- // Set Function Pointers
- retNode.Type = &gExt2_FileType;
-
- switch(inode.i_mode & EXT2_S_IFMT)
- {
- // Symbolic Link
- case EXT2_S_IFLNK:
- retNode.Flags = VFS_FFLAG_SYMLINK;
- break;
- // Regular File
- case EXT2_S_IFREG:
- retNode.Flags = 0;
- retNode.Size |= (Uint64)inode.i_dir_acl << 32;
- break;
- // Directory
- case EXT2_S_IFDIR:
- retNode.Type = &gExt2_DirType;
- retNode.Flags = VFS_FFLAG_DIRECTORY;
- retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) );
- break;
- // Unknown, Write protect it to be safe
- default:
- retNode.Flags = VFS_FFLAG_READONLY;
- break;
- }
-
- // Set Timestamps
- retNode.ATime = inode.i_atime * 1000;
- retNode.MTime = inode.i_mtime * 1000;
- retNode.CTime = inode.i_ctime * 1000;
-
- // Save in node cache and return saved node
- return Inode_CacheNode(Disk->CacheID, &retNode);
-}
-
-int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)
-{
- Log_Warning("Ext2","TODO: Impliment Ext2_int_WritebackNode");
- return 0;
+_err:
+ free(blockData);
+ Mutex_Release(&Node->Lock);
+ LEAVE('i', 1);
+ return 1; // ERR_???
}