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 * \brief Reads a directory entry
24 * \param Node Directory node
25 * \param Pos Position of desired element
27 char *Ext2_ReadDir(tVFS_Node *Node, int Pos)
30 char namebuf[EXT2_NAME_LEN+1];
32 Uint64 Base; // Block's Base Address
33 int block = 0, ofs = 0;
35 tExt2_Disk *disk = Node->ImplPtr;
38 ENTER("pNode iPos", Node, Pos);
40 // Read directory's inode
41 //Ext2_int_GetInode(Node, &inode);
42 Ext2_int_ReadInode(disk, Node->Inode, &inode);
45 LOG("inode.i_block[0] = 0x%x", inode.i_block[0]);
49 // - Do this ourselves as it is a simple operation
50 Base = inode.i_block[0] * disk->BlockSize;
52 while(Pos -- && size > 0)
54 VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
55 ofs += dirent.rec_len;
56 size -= dirent.rec_len;
59 if(ofs >= disk->BlockSize) {
61 if( ofs > disk->BlockSize ) {
62 Log_Warning("EXT2", "Directory Entry %i of inode %i extends over a block boundary, ignoring",
63 entNum-1, Node->Inode);
66 Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
70 // Check for the end of the list
77 VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent );
78 //LOG("dirent.inode = %i", dirent.inode);
79 //LOG("dirent.rec_len = %i", dirent.rec_len);
80 //LOG("dirent.name_len = %i", dirent.name_len);
81 VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
82 namebuf[ dirent.name_len ] = '\0'; // Cap off string
85 // Ignore . and .. (these are done in the VFS)
86 if( (namebuf[0] == '.' && namebuf[1] == '\0')
87 || (namebuf[0] == '.' && namebuf[1] == '.' && namebuf[2]=='\0')) {
89 return VFS_SKIP; // Skip
94 return strdup(namebuf);
98 * \brief Gets information about a file
99 * \param Node Parent Node
100 * \param Filename Name of wanted file
101 * \return VFS Node of file
103 tVFS_Node *Ext2_FindDir(tVFS_Node *Node, char *Filename)
105 tExt2_Disk *disk = Node->ImplPtr;
107 char namebuf[EXT2_NAME_LEN+1];
109 Uint64 Base; // Block's Base Address
110 int block = 0, ofs = 0;
114 // Read directory's inode
115 Ext2_int_ReadInode(disk, Node->Inode, &inode);
119 // - Do this ourselves as it is a simple operation
120 Base = inode.i_block[0] * disk->BlockSize;
124 VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent);
125 VFS_ReadAt( disk->FD, Base+ofs+sizeof(tExt2_DirEnt), dirent.name_len, namebuf );
126 namebuf[ dirent.name_len ] = '\0'; // Cap off string
127 // If it matches, create a node and return it
128 if(strcmp(namebuf, Filename) == 0)
129 return Ext2_int_CreateNode( disk, dirent.inode, namebuf );
130 // Increment pointers
131 ofs += dirent.rec_len;
132 size -= dirent.rec_len;
135 // Check for end of block
136 if(ofs >= disk->BlockSize) {
138 if( ofs > disk->BlockSize ) {
139 Log_Warning("EXT2", "Directory Entry %i of inode %i extends over a block boundary, ignoring",
140 entNum-1, Node->Inode);
143 Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block );
151 * \fn int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
152 * \brief Create a new node
154 int Ext2_MkNod(tVFS_Node *Parent, char *Name, Uint Flags)
158 child = Ext2_int_AllocateNode(Parent, Flags);
159 return Ext2_Link(Parent, child, Name);
163 * \brief Links an existing node to a new name
164 * \param Parent Parent (directory) node
165 * \param Node Node to link
166 * \param Name New name for the node
167 * \return Boolean Failure - See ::tVFS_Node.Link for info
169 int Ext2_Link(tVFS_Node *Parent, tVFS_Node *Node, char *Name)
174 // ---- INTERNAL FUNCTIONS ----
176 * \fn vfs_node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
177 * \brief Create a new VFS Node
179 tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeID, char *Name)
185 if( !Ext2_int_ReadInode(Disk, InodeID, &inode) )
188 if( (tmpNode = Inode_GetCache(Disk->CacheID, InodeID)) )
193 retNode.Inode = InodeID;
194 retNode.ImplPtr = Disk;
197 retNode.Size = inode.i_size;
199 // Set Access Permissions
200 retNode.UID = inode.i_uid;
201 retNode.GID = inode.i_gid;
203 retNode.ACLs = VFS_UnixToAcessACL(inode.i_mode & 0777, inode.i_uid, inode.i_gid);
205 // Set Function Pointers
206 retNode.Read = Ext2_Read;
207 retNode.Write = Ext2_Write;
208 retNode.Close = Ext2_CloseFile;
210 switch(inode.i_mode & EXT2_S_IFMT)
214 retNode.Flags = VFS_FFLAG_SYMLINK;
219 retNode.Size |= (Uint64)inode.i_dir_acl << 32;
223 retNode.ReadDir = Ext2_ReadDir;
224 retNode.FindDir = Ext2_FindDir;
225 retNode.MkNod = Ext2_MkNod;
226 //retNode.Relink = Ext2_Relink;
227 retNode.Flags = VFS_FFLAG_DIRECTORY;
229 // Unknown, Write protect and hide it to be safe
231 retNode.Flags = VFS_FFLAG_READONLY;//|VFS_FFLAG_HIDDEN;
235 // Check if the file should be hidden
236 //if(Name[0] == '.') retNode.Flags |= VFS_FFLAG_HIDDEN;
239 retNode.ATime = inode.i_atime * 1000;
240 retNode.MTime = inode.i_mtime * 1000;
241 retNode.CTime = inode.i_ctime * 1000;
243 // Save in node cache and return saved node
244 return Inode_CacheNode(Disk->CacheID, &retNode);