X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FFilesystems%2FExt2%2Fdir.c;h=3d4d2ad1409e56c1fcb769490f983f3926e158f2;hb=5cab4c07bc13888dc7956194ef9595508072a4eb;hp=ef347ad075c8d176d3736f3e13215506dda582e8;hpb=36c9094d0e26188c3dbf1b974e813797b76e7687;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Filesystems/Ext2/dir.c b/KernelLand/Modules/Filesystems/Ext2/dir.c index ef347ad0..3d4d2ad1 100644 --- a/KernelLand/Modules/Filesystems/Ext2/dir.c +++ b/KernelLand/Modules/Filesystems/Ext2/dir.c @@ -13,13 +13,11 @@ #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 = { @@ -44,9 +42,9 @@ tVFS_NodeType gExt2_FileType = { * \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_Inode *inode = (void*)(Node+1); tExt2_DirEnt dirent; Uint64 Base; // Block's Base Address int block = 0; @@ -58,19 +56,24 @@ char *Ext2_ReadDir(tVFS_Node *Node, int Pos) ENTER("pNode iPos", Node, Pos); // Read directory's inode - Ext2_int_ReadInode(disk, Node->Inode, &inode); - size = inode.i_size; + size = inode->i_size; - LOG("inode={.i_block[0]= 0x%x, .i_size=0x%x}", inode.i_block[0], inode.i_size); + LOG("inode={.i_block[0]= 0x%x, .i_size=0x%x}", inode->i_block[0], inode->i_size); // Find Entry // Get First Block // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; + Base = inode->i_block[0] * disk->BlockSize; // Scan directory - while(Pos -- && size > 0 && size <= inode.i_size) + while(Pos -- && size > 0 && size <= inode->i_size) { VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); + + if( dirent.rec_len == 0 ) { + size = 0; + break; + } + ofs += dirent.rec_len; size -= dirent.rec_len; entNum ++; @@ -82,7 +85,7 @@ char *Ext2_ReadDir(tVFS_Node *Node, int Pos) entNum-1, Node->Inode); } ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + Base = Ext2_int_GetBlockAddr( disk, inode->i_block, block ); if( Base == 0 ) { size = 0; break; @@ -91,9 +94,9 @@ char *Ext2_ReadDir(tVFS_Node *Node, int Pos) } // Check for the end of the list - if(size <= 0 || size > inode.i_size) { - LEAVE('n'); - return NULL; + if(size <= 0 || size > inode->i_size) { + LEAVE('i', -ENOENT); + return -ENOENT; } // Read Entry @@ -103,20 +106,21 @@ char *Ext2_ReadDir(tVFS_Node *Node, int Pos) 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; } /** @@ -125,10 +129,10 @@ char *Ext2_ReadDir(tVFS_Node *Node, int Pos) * \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; + tExt2_Inode *inode = (void*)(Node+1); tExt2_DirEnt dirent; Uint64 Base; // Block's Base Address int block = 0; @@ -138,21 +142,20 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename) int filenameLen = strlen(Filename); // Read directory's inode - Ext2_int_ReadInode(disk, Node->Inode, &inode); - size = inode.i_size; + size = inode->i_size; // Get First Block // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; + Base = inode->i_block[0] * disk->BlockSize; // Find File 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 ); + if( dirent.rec_len == 0 ) + break; // Increment pointers ofs += dirent.rec_len; size -= dirent.rec_len; @@ -166,7 +169,9 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename) entNum-1, Node->Inode); } ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); + Base = Ext2_int_GetBlockAddr( disk, inode->i_block, block ); + if( Base == 0 ) + break; } } @@ -177,22 +182,20 @@ tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename) * \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); @@ -206,9 +209,11 @@ int Ext2_MkNod(tVFS_Node *Parent, const char *Name, Uint Flags) // 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); } /** @@ -233,36 +238,31 @@ int Ext2_Unlink(tVFS_Node *Node, const char *OldName) */ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) { - #if 1 tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; + tExt2_Inode *inode = (void*)(Node+1); tExt2_DirEnt *dirent; tExt2_DirEnt newEntry; Uint64 base; // Block's Base Address int block = 0, ofs = 0; Uint size; - void *blockData; - int bestMatch = -1, bestSize, bestBlock, bestOfs, bestNeedsSplit; + 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); - - // Read child inode (get's the file type) - Ext2_int_ReadInode(disk, Child->Inode, &inode); + void *blockData = malloc(disk->BlockSize); // Create a stub entry newEntry.inode = Child->Inode; newEntry.name_len = strlen(Name); newEntry.rec_len = ((newEntry.name_len+3)&~3) + EXT2_DIRENT_SIZE; - newEntry.type = inode.i_mode >> 12; + newEntry.type = inode->i_mode >> 12; memcpy(newEntry.name, Name, newEntry.name_len); // Read directory's inode - Ext2_int_ReadInode(disk, Node->Inode, &inode); - size = inode.i_size; + size = inode->i_size; // Get a lock on the inode //Ext2_int_LockInode(disk, Node->Inode); @@ -273,9 +273,10 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) // Get First Block // - Do this ourselves as it is a simple operation - base = inode.i_block[0] * disk->BlockSize; + base = inode->i_block[0] * disk->BlockSize; VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData ); block = 0; + nEntries = 0; // Find File while(size > 0) { @@ -308,9 +309,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) 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); @@ -335,7 +334,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) // BLOCK_DIR_OFS(Node->Data, block) = nEntries; block ++; ofs = 0; - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); + base = Ext2_int_GetBlockAddr(disk, inode->i_block, block); VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData ); } } @@ -354,7 +353,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) if( bestMatch >= 0 ) { // Read-Modify-Write - base = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock); + base = Ext2_int_GetBlockAddr(disk, inode->i_block, bestBlock); VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData ); dirent = blockData + bestOfs; // Shorten a pre-existing entry @@ -382,7 +381,7 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) else { // Allocate block, Write Uint32 newblock = Ext2_int_AllocateBlock(disk, base / disk->BlockSize); - Ext2_int_AppendBlock(disk, &inode, newblock); + Ext2_int_AppendBlock(Node, inode, newblock); base = newblock * disk->BlockSize; Node->Size += newEntry.rec_len; Node->Flags |= VFS_FFLAG_DIRTY; @@ -395,86 +394,14 @@ int Ext2_Link(tVFS_Node *Node, const char *Name, tVFS_Node *Child) 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_??? }