* dir.c
* - Directory Handling
*/
-#define DEBUG 1
+#define DEBUG 0
#define VERBOSE 0
#include "ext2_common.h"
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 = {
*/
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;
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;
}
#define MIN_BLOCKS_PER_GROUP 2\r
#define MAX_BLOCK_LOG_SIZE 10 // 1024 << 10 = 1MiB\r
\r
-// === IMPORTS ===\r
-extern tVFS_NodeType gExt2_DirType;\r
-\r
// === PROTOTYPES ===\r
int Ext2_Install(char **Arguments);\r
int Ext2_Cleanup(void);\r
if( Node->Flags & VFS_FFLAG_DIRTY )\r
{\r
// Commit changes\r
- Log_Warning("Ext2", "TODO: Commit node changes");\r
+ Ext2_int_WritebackNode(disk, Node);\r
+ Node->Flags &= ~VFS_FFLAG_DIRTY;\r
}\r
\r
int was_not_referenced = (Node->ImplInt == 0);\r
{\r
LOG("Removng inode");\r
// Remove inode\r
- Log_Warning("Ext2", "TODO: Remove inode when not referenced");\r
+ Log_Warning("Ext2", "TODO: Remove inode when not referenced (%x)", (Uint32)Node->Inode);\r
}\r
if( acls != &gVFS_ACL_EveryoneRW ) {\r
free(acls);\r
return 1;\r
}\r
\r
+/**\r
+ * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID)\r
+ * \brief Create a new VFS Node\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
+ return NULL;\r
+ \r
+ if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )\r
+ return tmpNode;\r
+\r
+ memset(&retNode, 0, sizeof(retNode)); \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
+ 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
+ \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.Type = &gExt2_FileType;\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.Type = &gExt2_DirType;\r
+ retNode.Flags = VFS_FFLAG_DIRECTORY;\r
+ retNode.Data = calloc( sizeof(Uint16), DivUp(retNode.Size, Disk->BlockSize) );\r
+ break;\r
+ // Unknown, Write protect it to be safe \r
+ default:\r
+ retNode.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
+ \r
+ // Save in node cache and return saved node\r
+ return Inode_CacheNode(Disk->CacheID, &retNode);\r
+}\r
+\r
+int Ext2_int_WritebackNode(tExt2_Disk *Disk, tVFS_Node *Node)\r
+{\r
+ tExt2_Inode inode;\r
+\r
+ if( Disk != Node->ImplPtr ) {\r
+ Log_Error("Ext2", "Ext2_int_WritebackNode - Disk != Node->ImplPtr");\r
+ return -1;\r
+ }\r
+ \r
+ if( Node->Flags & VFS_FFLAG_SYMLINK ) {\r
+ inode.i_mode = EXT2_S_IFLNK;\r
+ }\r
+ else if( Node->Flags & VFS_FFLAG_DIRECTORY ) {\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
+ }\r
+\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
+\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
+\r
+ Ext2_int_WriteInode(Disk, Node->Inode, &inode);\r
+\r
+ return 0;\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