From ee9c3126fc8c693418a9f1216245a0576c0582d4 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 16 Aug 2011 22:56:17 +0800 Subject: [PATCH] Kernel - Implementing infrastructure for GetNodeFromINode --- Kernel/include/vfs.h | 26 ++++++--- Kernel/include/vfs_ext.h | 12 +++-- Kernel/include/vfs_int.h | 9 ++-- Kernel/syscalls.c | 2 +- Kernel/vfs/mount.c | 17 ++++++ Kernel/vfs/open.c | 113 ++++++++++++++++++++++++--------------- 6 files changed, 123 insertions(+), 56 deletions(-) diff --git a/Kernel/include/vfs.h b/Kernel/include/vfs.h index 73161a1c..40c611bc 100644 --- a/Kernel/include/vfs.h +++ b/Kernel/include/vfs.h @@ -94,7 +94,7 @@ typedef struct sVFS_Node * corresponds to. * \{ */ - Uint64 Inode; //!< Inode ID (Essentially another ImplInt) + Uint64 Inode; //!< Inode ID - Must identify the node uniquely if tVFS_Driver.GetNodeFromINode is non-NULL Uint ImplInt; //!< Implementation Usable Integer void *ImplPtr; //!< Implementation Usable Pointer /** @@ -313,16 +313,30 @@ typedef struct sVFS_Node */ typedef struct sVFS_Driver { - //! \brief Unique Identifier for this filesystem type + /** + * \brief Unique Identifier for this filesystem type + */ const char *Name; - //! \brief Flags applying to this driver + /** + * \brief Flags applying to this driver + */ Uint Flags; - //! \brief Callback to mount a device + /** + * \brief Callback to mount a device + */ tVFS_Node *(*InitDevice)(const char *Device, const char **Options); - //! \brief Callback to unmount a device + /** + * \brief Callback to unmount a device + */ void (*Unmount)(tVFS_Node *Node); - //! \brief Used internally (next driver in the chain) + /** + * \brief Retrieve a VFS node from an inode + */ + tVFS_Node *(*GetNodeFromINode)(tVFS_Node *RootNode, Uint64 InodeValue); + /** + * \brief Used internally (next driver in the chain) + */ struct sVFS_Driver *Next; } tVFS_Driver; diff --git a/Kernel/include/vfs_ext.h b/Kernel/include/vfs_ext.h index 26feb378..060a01c8 100644 --- a/Kernel/include/vfs_ext.h +++ b/Kernel/include/vfs_ext.h @@ -284,14 +284,21 @@ extern int VFS_ReadDir(int FD, char *Dest); /** * \brief Opens a file via an open directory * \note The file to open must be a direct child of the parent - * \param Errno Error number * \param FD Parent Directory * \param Name Child name * \param Mode Open mode * \return File handle (same as returned from VFS_Open) */ -extern int VFS_OpenChild(Uint *Errno, int FD, const char *Name, Uint Mode); +extern int VFS_OpenChild(int FD, const char *Name, Uint Mode); +/** + * \brief Opens a file given a mount ID and an inode number + * \param Mount Mount ID returned by FInfo + * \param Inode Inode number from FInfo + * \param Mode Open mode (see VFS_Open) + * \return File handle (same as VFS_Open) + */ +extern int VFS_OpenInode(Uint32 Mount, Uint64 Inode, int Mode); /** * \brief Wait for an aciton on a file descriptor * \param MaxHandle Maximum set handle in \a *Handles @@ -306,7 +313,6 @@ extern int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, /** * \brief Map a file into memory - * \param ErrNo Error status pointer * \param DestHint Suggested place for read data * \param Length Size of area to map * \param Protection Protection type (see `man mmap`) diff --git a/Kernel/include/vfs_int.h b/Kernel/include/vfs_int.h index 0d6b3b5d..8ecef3b0 100644 --- a/Kernel/include/vfs_int.h +++ b/Kernel/include/vfs_int.h @@ -10,7 +10,8 @@ typedef struct sVFS_Mount { struct sVFS_Mount *Next; char *MountPoint; - int MountPointLen; + size_t MountPointLen; + Uint32 Identifier; char *Device; char *Options; tVFS_Driver *Filesystem; @@ -44,11 +45,13 @@ typedef struct sVFS_MMapPage { extern tVFS_Mount *gVFS_Mounts; // === PROTOTYPES === -// --- OPEN.C --- +// --- open.c --- extern char *VFS_GetAbsPath(const char *Path); extern tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath); extern tVFS_Handle *VFS_GetHandle(int FD); -// --- ACLS.C --- +// --- acls.c --- extern int VFS_CheckACL(tVFS_Node *Node, Uint Permissions); +// --- mount.c --- +extern tVFS_Mount *VFS_GetMountByIdent(Uint32 MountID); #endif diff --git a/Kernel/syscalls.c b/Kernel/syscalls.c index 4eb3c719..936bf277 100644 --- a/Kernel/syscalls.c +++ b/Kernel/syscalls.c @@ -245,7 +245,7 @@ void SyscallHandler(tSyscallRegs *Regs) // Open a file that is a entry in an open directory case SYS_OPENCHILD: CHECK_STR_NONULL( (char*)Regs->Arg2 ); - ret = VFS_OpenChild( &err, Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3); + ret = VFS_OpenChild( Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3); break; // Change Directory diff --git a/Kernel/vfs/mount.c b/Kernel/vfs/mount.c index 13c1fb39..a42cd09b 100644 --- a/Kernel/vfs/mount.c +++ b/Kernel/vfs/mount.c @@ -20,6 +20,7 @@ void VFS_UpdateMountFile(void); tMutex glVFS_MountList; tVFS_Mount *gVFS_Mounts; tVFS_Mount *gVFS_RootMount = NULL; +Uint32 giVFS_NextMountIdent = 0; // === CODE === /** @@ -79,6 +80,8 @@ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem free(mnt); return -2; } + + mnt->Identifier = giVFS_NextMountIdent++; // Set root if(!gVFS_RootMount) gVFS_RootMount = mnt; @@ -105,6 +108,20 @@ int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem return 0; } +/** + * \brief Gets a mount point given the identifier + */ +tVFS_Mount *VFS_GetMountByIdent(Uint32 MountID) +{ + tVFS_Mount *mnt; + for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next) + { + if(mnt->Identifier == MountID) + return mnt; + } + return NULL; +} + /** * \brief Updates the mount file buffer * diff --git a/Kernel/vfs/open.c b/Kernel/vfs/open.c index ed79ba11..02f1a7bc 100644 --- a/Kernel/vfs/open.c +++ b/Kernel/vfs/open.c @@ -19,6 +19,9 @@ extern tVFS_Node gVFS_MemRoot; extern tVFS_Mount *gVFS_RootMount; extern int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode); +// === PROTOTYPES === + int VFS_int_CreateHandle( tVFS_Node *Node, int Mode ); + // === CODE === /** * \fn char *VFS_GetAbsPath(const char *Path) @@ -434,6 +437,37 @@ restart_parse: return tmpNode; } +/** + * \brief Create and return a handle number for the given node and mode + */ +int VFS_int_CreateHandle( tVFS_Node *Node, int Mode ) +{ + int i; + i = 0; + i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0; + i |= (Mode & VFS_OPENFLAG_READ) ? VFS_PERM_READ : 0; + i |= (Mode & VFS_OPENFLAG_WRITE) ? VFS_PERM_WRITE : 0; + + LOG("i = 0b%b", i); + + // Permissions Check + if( !VFS_CheckACL(Node, i) ) { + if(Node->Close) Node->Close( Node ); + Log_Log("VFS", "VFS_int_CreateHandle: Permissions Failed"); + errno = EACCES; + LEAVE_RET('i', -1); + } + + i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), Node, Mode ); + if( i < 0 ) { + Log_Notice("VFS", "VFS_int_CreateHandle: Out of handles"); + errno = ENFILE; + LEAVE_RET('i', -1); + } + + LEAVE_RET('x', i); +} + /** * \fn int VFS_Open(const char *Path, Uint Mode) * \brief Open a file @@ -442,7 +476,6 @@ int VFS_Open(const char *Path, Uint Mode) { tVFS_Node *node; char *absPath; - int i; ENTER("sPath xMode", Path, Mode); @@ -460,6 +493,7 @@ int VFS_Open(const char *Path, Uint Mode) if(!node) { LOG("Cannot find node"); + errno = ENOENT; LEAVE_RET('i', -1); } @@ -483,86 +517,79 @@ int VFS_Open(const char *Path, Uint Mode) node = VFS_ParsePath(tmppath, NULL); if(!node) { LOG("Cannot find symlink target node (%s)", tmppath); + errno = ENOENT; LEAVE_RET('i', -1); } } - i = 0; - i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0; - i |= (Mode & VFS_OPENFLAG_READ) ? VFS_PERM_READ : 0; - i |= (Mode & VFS_OPENFLAG_WRITE) ? VFS_PERM_WRITE : 0; - - LOG("i = 0b%b", i); - - // Permissions Check - if( !VFS_CheckACL(node, i) ) { - if(node->Close) node->Close( node ); - Log_Log("VFS", "VFS_Open: Permissions Failed"); - LEAVE_RET('i', -1); - } - - i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), node, Mode ); - if( i < 0 ) { - Log_Notice("VFS", "VFS_Open: Out of handles"); - LEAVE_RET('i', -1); - } - - LEAVE_RET('x', i); + LEAVE_RET('x', VFS_int_CreateHandle(node, Mode)); } /** * \brief Open a file from an open directory */ -int VFS_OpenChild(Uint *Errno, int FD, const char *Name, Uint Mode) +int VFS_OpenChild(int FD, const char *Name, Uint Mode) { tVFS_Handle *h; tVFS_Node *node; - int i; + ENTER("xFD sName xMode", FD, Name, Mode); + // Get handle h = VFS_GetHandle(FD); if(h == NULL) { Log_Warning("VFS", "VFS_OpenChild - Invalid file handle 0x%x", FD); - if(Errno) *Errno = EINVAL; + errno = EINVAL; LEAVE_RET('i', -1); } // Check for directory if( !(h->Node->Flags & VFS_FFLAG_DIRECTORY) ) { Log_Warning("VFS", "VFS_OpenChild - Passed handle is not a directory", FD); - if(Errno) *Errno = ENOTDIR; + errno = ENOTDIR; LEAVE_RET('i', -1); } // Find Child node = h->Node->FindDir(h->Node, Name); if(!node) { - if(Errno) *Errno = ENOENT; + errno = ENOENT; LEAVE_RET('i', -1); } + + LEAVE_RET('x', VFS_int_CreateHandle(node, Mode)); +} + +int VFS_OpenInode(Uint32 Mount, Uint64 Inode, int Mode) +{ + tVFS_Mount *mnt; + tVFS_Node *node; + + ENTER("iMount iInode xMode", Mount, Inode, Mode); - i = 0; - i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0; - i |= (Mode & VFS_OPENFLAG_READ) ? VFS_PERM_READ : 0; - i |= (Mode & VFS_OPENFLAG_WRITE) ? VFS_PERM_WRITE : 0; - - // Permissions Check - if( !VFS_CheckACL(node, i) ) { - if(node->Close) node->Close( node ); - Log_Notice("VFS", "VFS_OpenChild - Permissions Failed"); - if(Errno) *Errno = EACCES; + // Get mount point + mnt = VFS_GetMountByIdent(Mount); + if( !mnt ) { + LOG("Mount point ident invalid"); + errno = ENOENT; LEAVE_RET('i', -1); } - i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), node, Mode ); - if( i >= 0 ) { - LEAVE_RET('x', i); + // Does the filesystem support this? + if( !mnt->Filesystem->GetNodeFromINode ) { + errno = ENOENT; + LEAVE_RET('i', -1); + } + + // Get node + node = mnt->Filesystem->GetNodeFromINode(mnt->RootNode, Inode); + if( !node ) { + errno = ENOENT; + LEAVE_RET('i', -1); } - Log_Error("VFS", "VFS_OpenChild - Out of handles"); - if(Errno) *Errno = ENFILE; - LEAVE_RET('i', -1); + LEAVE_RET('x', VFS_int_CreateHandle(node, Mode)); } /** -- 2.20.1