3 * Ext2 Driver Version 1
7 * \brief Second Extended Filesystem Driver
8 * \todo Implement file full write support
12 #include "ext2_common.h"
16 char *Ext2_ReadDir(tVFS_Node *Node, int Pos);
17 tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *FileName);
18 int Ext2_MkNod(tVFS_Node *Node, char *Name, Uint Flags);
19 tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId, char *Name);
23 \fn char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
24 \brief Reads a directory entry
26 char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
29 char namebuf[EXT2_NAME_LEN+1];
31 Uint64 Base; // Block's Base Address
32 int block = 0, ofs = 0;
34 tExt2_Disk *disk = Node->ImplPtr;
37 ENTER("pNode iPos", Node, Pos);
39 // Read directory's inode
40 Ext2_int_GetInode(Node, &inode);
43 LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);
47 // - Do this ourselves as it is a simple operation
48 Base = inode.i_block[0] * disk->BlockSize;
49 while(Pos -- && size > 0)
51 VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
52 ofs += dirent.rec_len;
53 size -= dirent.rec_len;
56 if(ofs >= disk->BlockSize) {
58 if( ofs > disk->BlockSize ) {
59 Warning("[EXT2] Directory Entry %i of inode %i extends over a block boundary, ignoring",
60 entNum-1, Node->Inode);
63 Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
67 // Check for the end of the list
74 VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );
75 //LOG("dirent.inode = %i", dirent.inode);
76 //LOG("dirent.rec_len = %i", dirent.rec_len);
77 //LOG("dirent.name_len = %i", dirent.name_len);
78 VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
79 namebuf[ dirent.name_len ] = '\0'; // Cap off string
82 // Ignore . and .. (these are done in the VFS)
83 if( (namebuf[0] == '.' && namebuf[1] == '\0')
84 || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {
86 return VFS_SKIP; // Skip
91 return strdup(namebuf);
95 \fn tVFS_Node *Ext2_FindDir(tVFS_Node *node, char *filename)
96 \brief Gets information about a file
97 \param node vfs node - Parent Node
98 \param filename String - Name of file
99 \return VFS Node of file
101 tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)
103 tExt2_Disk *disk = Node->ImplPtr;
105 char namebuf[EXT2_NAME_LEN+1];
107 Uint64 Base; // Block's Base Address
108 int block = 0, ofs = 0;
112 // Read directory's inode
113 Ext2_int_GetInode(Node, &inode);
117 // - Do this ourselves as it is a simple operation
118 Base = inode.i_block[0] * disk->BlockSize;
122 VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
123 VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
124 namebuf[ dirent.name_len ] = '\0'; // Cap off string
125 // If it matches, create a node and return it
126 if(strcmp(namebuf, Filename) == 0)
127 return Ext2_int_CreateNode( disk, dirent.inode, namebuf );
128 // Increment pointers
129 ofs += dirent.rec_len;
130 size -= dirent.rec_len;
133 // Check for end of block
134 if(ofs >= disk->BlockSize) {
136 if( ofs > disk->BlockSize ) {
137 Warning("[EXT2 ] Directory Entry %i of inode %i extends over a block boundary, ignoring",
138 entNum-1, Node->Inode);
141 Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
149 * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
150 * \brief Create a new node
152 int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
157 // ---- INTERNAL FUNCTIONS ----
159 * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
160 * \brief Create a new VFS Node
162 tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
168 if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
171 if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
176 retNode.Inode = InodeID;
177 retNode.ImplPtr = Disk;
180 retNode.Size = inode.i_size;
182 // Set Access Permissions
183 retNode.UID = inode.i_uid;
184 retNode.GID = inode.i_gid;
186 retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
188 // Set Function Pointers
189 retNode.Read = Ext2_Read;
190 retNode.Write = Ext2_Write;
191 retNode.Close = Ext2_CloseFile;
193 switch(inode.i_mode & EXT2_S_IFMT)
197 retNode.Flags = VFS_FFLAG_SYMLINK;
202 retNode.Size |= (Uint64)inode.i_dir_acl << 32;
206 retNode.ReadDir = Ext2_ReadDir;
207 retNode.FindDir = Ext2_FindDir;
208 retNode.MkNod = Ext2_MkNod;
209 //retNode.Relink = Ext2_Relink;
210 retNode.Flags = VFS_FFLAG_DIRECTORY;
212 // Unknown, Write protect and hide it to be safe
214 retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;
218 // Check if the file should be hidden
219 //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN;
222 retNode.ATime = now();
223 retNode.MTime = inode.i_mtime * 1000;
224 retNode.CTime = inode.i_ctime * 1000;
226 // Save in node cache and return saved node
227 return Inode_CacheNode(Disk->CacheID, &retNode);