+/**\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
+ 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( (node = Inode_GetCache(Disk->CacheID, InodeID)) )\r
+ return node;\r
+ node = &data.retNode;\r
+\r
+ memset(node, 0, sizeof(*node));\r
+ \r
+ // Set identifiers\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
+ node->Size = in->i_size;\r
+ \r
+ // Set Access Permissions\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
+ node->Type = &gExt2_FileType;\r
+ \r
+ switch(in->i_mode & EXT2_S_IFMT)\r
+ {\r
+ // Symbolic Link\r
+ case EXT2_S_IFLNK:\r
+ node->Flags = VFS_FFLAG_SYMLINK;\r
+ break;\r
+ // Regular File\r
+ case EXT2_S_IFREG:\r
+ node->Flags = 0;\r
+ node->Size |= (Uint64)in->i_dir_acl << 32;\r
+ break;\r
+ // Directory\r
+ case EXT2_S_IFDIR:\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
+ node->Flags = VFS_FFLAG_READONLY;\r
+ break;\r
+ }\r
+ \r
+ // Set Timestamps\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_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 = (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
+ 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
+ inode->i_mode |= 777;\r
+\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