X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=sidebyside;f=Modules%2FFilesystems%2FExt2%2Fdir.c;fp=Modules%2FFilesystems%2FExt2%2Fdir.c;h=0000000000000000000000000000000000000000;hb=48743e39650eb1ef988380e9d95f27fd40d3a9ce;hp=5eb476f4b1f3b88ecc867f85ca1a2c6107b39831;hpb=a2495c6ea4f4cab16b5d339ae511428e92e89e73;p=tpg%2Facess2.git diff --git a/Modules/Filesystems/Ext2/dir.c b/Modules/Filesystems/Ext2/dir.c deleted file mode 100644 index 5eb476f4..00000000 --- a/Modules/Filesystems/Ext2/dir.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Acess OS - * Ext2 Driver Version 1 - */ -/** - * \file dir.c - * \brief Second Extended Filesystem Driver - * \todo Implement file full write support - */ -#define DEBUG 1 -#define VERBOSE 0 -#include "ext2_common.h" - -// === MACROS === -#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_Relink(tVFS_Node *Node, const char *OldName, const char *NewName); - int Ext2_Link(tVFS_Node *Parent, tVFS_Node *Node, const char *Name); -// --- Helpers --- -tVFS_Node *Ext2_int_CreateNode(tExt2_Disk *Disk, Uint InodeId); - -// === GLOBALS === -tVFS_NodeType gExt2_DirType = { - .TypeName = "ext2-dir", - .ReadDir = Ext2_ReadDir, - .FindDir = Ext2_FindDir, - .MkNod = Ext2_MkNod, - .Relink = Ext2_Relink, - .Link = Ext2_Link, - .Close = Ext2_CloseFile - }; -tVFS_NodeType gExt2_FileType = { - .TypeName = "ext2-file", - .Read = Ext2_Read, - .Write = Ext2_Write, - .Close = Ext2_CloseFile - }; - -// === CODE === -/** - * \brief Reads a directory entry - * \param Node Directory node - * \param Pos Position of desired element - */ -char *Ext2_ReadDir(tVFS_Node *Node, int Pos) -{ - tExt2_Inode inode; - tExt2_DirEnt dirent; - Uint64 Base; // Block's Base Address - int block = 0; - Uint ofs = 0; - int entNum = 0; - tExt2_Disk *disk = Node->ImplPtr; - Uint size; - - ENTER("pNode iPos", Node, Pos); - - // Read directory's inode - Ext2_int_ReadInode(disk, Node->Inode, &inode); - size = inode.i_size; - - LOG("inode.i_block[0] = 0x%x", inode.i_block[0]); - - // Find Entry - // Get First Block - // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; - // Scan directory - while(Pos -- && size > 0) - { - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); - ofs += dirent.rec_len; - size -= dirent.rec_len; - entNum ++; - - if(ofs >= disk->BlockSize) { - block ++; - if( ofs > disk->BlockSize ) { - Log_Warning("EXT2", "Directory Entry %i of inode %i extends over a block boundary, ignoring", - entNum-1, Node->Inode); - } - ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); - } - } - - // Check for the end of the list - if(size <= 0) { - LEAVE('n'); - return NULL; - } - - // Read Entry - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent ); - //LOG("dirent.inode = %i", dirent.inode); - //LOG("dirent.rec_len = %i", dirent.rec_len); - //LOG("dirent.name_len = %i", dirent.name_len); - dirent.name[ dirent.name_len ] = '\0'; // Cap off string - - - // 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('s', dirent.name); - // Create new node - return strdup(dirent.name); -} - -/** - * \brief Gets information about a file - * \param Node Parent Node - * \param Filename Name of wanted file - * \return VFS Node of file - */ -tVFS_Node *Ext2_FindDir(tVFS_Node *Node, const char *Filename) -{ - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - tExt2_DirEnt dirent; - Uint64 Base; // Block's Base Address - int block = 0; - Uint ofs = 0; - int entNum = 0; - Uint size; - int filenameLen = strlen(Filename); - - // Read directory's inode - Ext2_int_ReadInode(disk, Node->Inode, &inode); - size = inode.i_size; - - // Get First Block - // - Do this ourselves as it is a simple operation - Base = inode.i_block[0] * disk->BlockSize; - // Find File - while(size > 0) - { - VFS_ReadAt( disk->FD, Base+ofs, sizeof(tExt2_DirEnt), &dirent); - 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) - return Ext2_int_CreateNode( disk, dirent.inode ); - // Increment pointers - ofs += dirent.rec_len; - size -= dirent.rec_len; - entNum ++; - - // Check for end of block - if(ofs >= disk->BlockSize) { - block ++; - if( ofs > disk->BlockSize ) { - Log_Warning("EXT2", "Directory Entry %i of inode %i extends over a block boundary, ignoring", - entNum-1, Node->Inode); - } - ofs = 0; - Base = Ext2_int_GetBlockAddr( disk, inode.i_block, block ); - } - } - - return NULL; -} - -/** - * \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) -{ - #if 0 - tVFS_Node *child; - Uint64 inodeNum; - tExt2_Inode inode; - inodeNum = Ext2_int_AllocateInode(Parent->ImplPtr, Parent->Inode); - - memset(&inode, 0, sizeof(tExt2_Inode)); - - // File type - inode.i_mode = 0664; - if( Flags & VFS_FFLAG_READONLY ) - inode.i_mode &= ~0222; - if( Flags & VFS_FFLAG_SYMLINK ) - inode.i_mode |= EXT2_S_IFLNK; - else if( Flags & VFS_FFLAG_DIRECTORY ) - inode.i_mode |= EXT2_S_IFDIR | 0111; - - inode.i_uid = Threads_GetUID(); - inode.i_gid = Threads_GetGID(); - inode.i_ctime = - inode.i_mtime = - inode.i_atime = now() / 1000; - - child = Ext2_int_CreateNode(Parent->ImplPtr, inodeNum); - return Ext2_Link(Parent, child, Name); - #else - return 1; - #endif -} - -/** - * \brief Rename a file - * \param Node This (directory) node - * \param OldName Old name of file - * \param NewName New name for file - * \return Boolean Failure - See ::tVFS_Node.Relink for info - */ -int Ext2_Relink(tVFS_Node *Node, const char *OldName, const char *NewName) -{ - return 1; -} - -/** - * \brief Links an existing node to a new name - * \param Parent Parent (directory) node - * \param Node Node to link - * \param Name New name for the node - * \return Boolean Failure - See ::tVFS_Node.Link for info - */ -int Ext2_Link(tVFS_Node *Node, tVFS_Node *Child, const char *Name) -{ - #if 0 - tExt2_Disk *disk = Node->ImplPtr; - tExt2_Inode inode; - 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; - int nEntries; - - blockData = malloc(disk->BlockSize); - - // Read child inode (get's the file type) - Ext2_int_ReadInode(disk, Child->Inode, &inode); - - // Create a stub entry - newEntry.inode = Child->Inode; - newEntry.name_len = strlen(Name); - newEntry.rec_len = (newEntry.name_len+3+8)&~3; - 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; - - // Get a lock on the inode - Ext2_int_LockInode(disk, Node->Inode); - - // Get First Block - // - Do this ourselves as it is a simple operation - base = inode.i_block[0] * disk->BlockSize; - VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData ); - block = 0; - // Find File - while(size > 0) - { - dirent = blockData + ofs; - // Sanity Check the entry - if(ofs + dirent->rec_len > disk->BlockSize) { - Log_Warning("EXT2", - "Directory entry %i of inode 0x%x extends over a block boundary", - nEntries, (Uint)Node->Inode); - } - else { - - // Free entry - if(dirent->type == 0) { - if( dirent->rec_len >= newEntry.rec_len - && (bestMatch == -1 || bestSize > dirent->rec_len) ) - { - bestMatch = nEntries; - bestSize = dirent->rec_len; - bestBlock = block; - bestOfs = ofs; - } - } - // Non free - check name to avoid duplicates - else { - if(strncmp(Name, dirent->name, dirent->name_len) == 0) { - Ext2_int_UnlockInode(disk, Node->Inode); - return 1; // ERR_??? - } - } - } - - // Increment the pointer - nEntries ++; - ofs += dirent->rec_len; - if( ofs >= disk->BlockSize ) { - // Read the next block if needed - BLOCK_DIR_OFS(Node->Data, block) = nEntries; - block ++; - ofs = 0; - base = Ext2_int_GetBlockAddr(disk, inode.i_block, block); - VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData ); - } - } - - // Check if a free slot was found - if( bestMatch >= 0 ) { - // Read-Modify-Write - bestBlock = Ext2_int_GetBlockAddr(disk, inode.i_block, bestBlock); - if( block > 0 ) - bestMatch = BLOCK_DIR_OFS(Node->Data, bestBlock); - VFS_ReadAt( disk->FD, base, disk->BlockSize, blockData ); - dirent = blockData + bestOfs; - memcpy(dirent, newEntry, newEntry.rec_len); - VFS_WriteAt( disk->FD, base, disk->BlockSize, blockData ); - } - else { - // Allocate block, Write - block = Ext2_int_AllocateBlock(Disk, block); - Log_Warning("EXT2", ""); - } - - Ext2_int_UnlockInode(disk, Node->Inode); - return 0; - #else - 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; - - - // Set identifiers - retNode.Inode = InodeID; - retNode.ImplPtr = Disk; - - // Set file length - retNode.Size = inode.i_size; - retNode.Data = NULL; - - // 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); -}