X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fvfs%2Fopen.c;h=1536d1a0f2c21a6c5a02c3db7e1387c8a7b2222f;hb=a2495c6ea4f4cab16b5d339ae511428e92e89e73;hp=c4c9bbfa8d8fc569190bf3440b3c2b7d5600920b;hpb=1961808f2b5eea942c11391d91a50e28eb780dde;p=tpg%2Facess2.git diff --git a/Kernel/vfs/open.c b/Kernel/vfs/open.c index c4c9bbfa..1536d1a0 100644 --- a/Kernel/vfs/open.c +++ b/Kernel/vfs/open.c @@ -7,6 +7,7 @@ #include "vfs.h" #include "vfs_int.h" #include "vfs_ext.h" +#include // === CONSTANTS === #define OPEN_MOUNT_ROOT 1 @@ -15,9 +16,9 @@ #define MAX_PATH_LEN 255 // === IMPORTS === -extern tVFS_Node gVFS_MemRoot; extern tVFS_Mount *gVFS_RootMount; extern int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode); +extern tVFS_Node *VFS_MemFile_Create(const char *Path); // === PROTOTYPES === int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode ); @@ -35,9 +36,9 @@ char *VFS_GetAbsPath(const char *Path) char *tmpStr; int iPos = 0; int iPos2 = 0; - const char *chroot = CFGPTR(CFG_VFS_CHROOT); + const char *chroot = *Threads_GetChroot(); int chrootLen; - const char *cwd = CFGPTR(CFG_VFS_CWD); + const char *cwd = *Threads_GetCWD(); int cwdLen; ENTER("sPath", Path); @@ -55,12 +56,9 @@ char *VFS_GetAbsPath(const char *Path) } // - Fetch ChRoot - if( chroot == NULL ) { + if( chroot == NULL ) chroot = ""; - chrootLen = 0; - } else { - chrootLen = strlen(chroot); - } + chrootLen = strlen(chroot); // Check if the path is already absolute if(Path[0] == '/') { @@ -155,7 +153,8 @@ char *VFS_GetAbsPath(const char *Path) ret[iPos2] = 0; // Prepend the chroot - memcpy( ret, chroot, chrootLen ); + if(chrootLen) + memcpy( ret, chroot, chrootLen ); LEAVE('s', ret); // Log_Debug("VFS", "VFS_GetAbsPath: RETURN '%s'", ret); @@ -178,13 +177,13 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath, tVFS_Mount **MountPo ENTER("sPath pTruePath", Path, TruePath); - // Memory File - if(Path[0] == '$') { + // HACK: Memory File + if(Threads_GetUID() == 0 && Path[0] == '$') { if(TruePath) { *TruePath = malloc(strlen(Path)+1); strcpy(*TruePath, Path); } - curNode = gVFS_MemRoot.FindDir(&gVFS_MemRoot, Path); + curNode = VFS_MemFile_Create(Path); if(MountPoint) { *MountPoint = NULL; } @@ -199,6 +198,7 @@ restart_parse: *TruePath = malloc( gVFS_RootMount->MountPointLen+1 ); strcpy(*TruePath, gVFS_RootMount->MountPoint); } + if(MountPoint) *MountPoint = gVFS_RootMount; LEAVE('p', gVFS_RootMount->RootNode); return gVFS_RootMount->RootNode; } @@ -269,48 +269,27 @@ restart_parse: // Check permissions on root of filesystem if( !VFS_CheckACL(curNode, VFS_PERM_EXECUTE) ) { - if(curNode->Close) curNode->Close( curNode ); - if(TruePath) { - free(*TruePath); - *TruePath = NULL; - } //Log("Permissions fail on '%s'", Path); - LEAVE('n'); - return NULL; + goto _error; } // Check if the node has a FindDir method - if( !curNode->FindDir ) + if( !curNode->Type->FindDir ) { - if(curNode->Close) curNode->Close(curNode); - if(TruePath) { - free(*TruePath); - *TruePath = NULL; - } //Log("FindDir fail on '%s'", Path); - LEAVE('n'); - return NULL; + goto _error; } - LOG("FindDir{=%p}(%p, '%s')", curNode->FindDir, curNode, pathEle); + LOG("FindDir{=%p}(%p, '%s')", curNode->Type->FindDir, curNode, pathEle); // Get Child Node - tmpNode = curNode->FindDir(curNode, pathEle); + tmpNode = curNode->Type->FindDir(curNode, pathEle); LOG("tmpNode = %p", tmpNode); - if(curNode->Close) { - //LOG2("curNode->Close = %p", curNode->Close); - curNode->Close(curNode); - } + _CloseNode( curNode ); curNode = tmpNode; // Error Check if(!curNode) { LOG("Node '%s' not found in dir '%s'", pathEle, Path); - if(TruePath) { - free(*TruePath); - *TruePath = NULL; - } - //Log("Child fail on '%s' ('%s)", Path, pathEle); - LEAVE('n'); - return NULL; + goto _error; } // Handle Symbolic Links @@ -319,19 +298,15 @@ restart_parse: free(*TruePath); *TruePath = NULL; } - if(!curNode->Read) { + if(!curNode->Type || !curNode->Type->Read) { Log_Warning("VFS", "VFS_ParsePath - Read of symlink node %p'%s' is NULL", curNode, Path); - if(curNode->Close) curNode->Close(curNode); - // No need to free *TruePath, it should already be NULL - LEAVE('n'); - return NULL; + goto _error; } if(iNestedLinks > MAX_NESTED_LINKS) { - if(curNode->Close) curNode->Close(curNode); - LEAVE('n'); - return NULL; + Log_Notice("VFS", "VFS_ParsePath - Nested link limit exceeded"); + goto _error; } // Parse Symlink Path @@ -340,13 +315,12 @@ restart_parse: { int remlen = strlen(Path) - (ofs + nextSlash); if( curNode->Size + remlen > MAX_PATH_LEN ) { - if(curNode->Close) curNode->Close(curNode); Log_Warning("VFS", "VFS_ParsePath - Symlinked path too long"); - LEAVE('n'); - return NULL; + goto _error; } - curNode->Read( curNode, 0, curNode->Size, path_buffer ); + curNode->Type->Read( curNode, 0, curNode->Size, path_buffer ); path_buffer[ curNode->Size ] = '\0'; + LOG("path_buffer = '%s'", path_buffer); strcat(path_buffer, Path + ofs+nextSlash); Path = path_buffer; @@ -355,6 +329,7 @@ restart_parse: } // EVIL: Goto :) + LOG("Symlink -> '%s', restart", Path); goto restart_parse; } @@ -362,9 +337,7 @@ restart_parse: if( !(curNode->Flags & VFS_FFLAG_DIRECTORY) ) { Log_Warning("VFS", "VFS_ParsePath - Path segment is not a directory"); - if(TruePath) free(*TruePath); - LEAVE('n'); - return NULL; + goto _error; } // Check if path needs extending @@ -375,11 +348,7 @@ restart_parse: // Check if allocation succeeded if(!tmp) { Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer"); - free(*TruePath); - *TruePath = NULL; - if(curNode->Close) curNode->Close(curNode); - LEAVE('n'); - return NULL; + goto _error; } *TruePath = tmp; // Append to path @@ -391,32 +360,23 @@ restart_parse: // - Extend Path retLength += nextSlash + 1; } - - if( !curNode->FindDir ) { - if(curNode->Close) curNode->Close(curNode); - if(TruePath) { - free(*TruePath); - *TruePath = NULL; - } + + // Check final finddir call + if( !curNode->Type || !curNode->Type->FindDir ) { Log_Warning("VFS", "VFS_ParsePath - FindDir doesn't exist for element of '%s'", Path); - LEAVE('n'); - return NULL; + goto _error; } // Get last node LOG("FindDir(%p, '%s')", curNode, &Path[ofs]); - tmpNode = curNode->FindDir(curNode, &Path[ofs]); + tmpNode = curNode->Type->FindDir(curNode, &Path[ofs]); LOG("tmpNode = %p", tmpNode); - if(curNode->Close) curNode->Close(curNode); // Check if file was found if(!tmpNode) { LOG("Node '%s' not found in dir '%s'", &Path[ofs], Path); - //Log("Child fail '%s' ('%s')", Path, &Path[ofs]); - if(TruePath) free(*TruePath); - if(curNode->Close) curNode->Close(curNode); - LEAVE('n'); - return NULL; + goto _error; } + _CloseNode( curNode ); if(TruePath) { @@ -425,10 +385,7 @@ restart_parse: // Check if allocation succeeded if(!tmp) { Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer"); - free(*TruePath); - if(tmpNode->Close) tmpNode->Close(curNode); - LEAVE('n'); - return NULL; + goto _error; } *TruePath = tmp; // Append to path @@ -444,6 +401,16 @@ restart_parse: LEAVE('p', tmpNode); return tmpNode; + +_error: + _CloseNode( curNode ); + + if(TruePath && *TruePath) { + free(*TruePath); + *TruePath = NULL; + } + LEAVE('n'); + return NULL; } /** @@ -453,7 +420,7 @@ int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode ) { int i; - ENTER("pNode pMount iMode", Node, Mount, Mode); + ENTER("pNode pMount xMode", Node, Mount, Mode); i = 0; i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0; @@ -464,7 +431,7 @@ int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode ) // Permissions Check if( !VFS_CheckACL(Node, i) ) { - if(Node->Close) Node->Close( Node ); + _CloseNode( Node ); Log_Log("VFS", "VFS_int_CreateHandle: Permissions Failed"); errno = EACCES; LEAVE_RET('i', -1); @@ -486,13 +453,18 @@ int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode ) * \fn int VFS_Open(const char *Path, Uint Mode) * \brief Open a file */ -int VFS_Open(const char *Path, Uint Mode) +int VFS_Open(const char *Path, Uint Flags) +{ + return VFS_OpenEx(Path, Flags, 0); +} + +int VFS_OpenEx(const char *Path, Uint Flags, Uint Mode) { tVFS_Node *node; tVFS_Mount *mnt; char *absPath; - ENTER("sPath xMode", Path, Mode); + ENTER("sPath xFlags oMode", Path, Flags); // Get absolute path absPath = VFS_GetAbsPath(Path); @@ -501,33 +473,46 @@ int VFS_Open(const char *Path, Uint Mode) LEAVE_RET('i', -1); } LOG("absPath = \"%s\"", absPath); + // Parse path and get mount point node = VFS_ParsePath(absPath, NULL, &mnt); + + // Create file if requested and it doesn't exist + if( !node && (Flags & VFS_OPENFLAG_CREATE) ) + { + // TODO: Translate `Mode` into ACL and node flags + // Get parent, create node + VFS_MkNod(absPath, 0); + node = VFS_ParsePath(absPath, NULL, &mnt); + } + // Free generated path free(absPath); - if(!node) { + // Check for error + if(!node) + { LOG("Cannot find node"); errno = ENOENT; LEAVE_RET('i', -1); } // Check for symlinks - if( !(Mode & VFS_OPENFLAG_NOLINK) && (node->Flags & VFS_FFLAG_SYMLINK) ) + if( !(Flags & VFS_OPENFLAG_NOLINK) && (node->Flags & VFS_FFLAG_SYMLINK) ) { char tmppath[node->Size+1]; if( node->Size > MAX_PATH_LEN ) { Log_Warning("VFS", "VFS_Open - Symlink is too long (%i)", node->Size); LEAVE_RET('i', -1); } - if( !node->Read ) { + if( !node->Type || !node->Type->Read ) { Log_Warning("VFS", "VFS_Open - No read method on symlink"); LEAVE_RET('i', -1); } // Read symlink's path - node->Read( node, 0, node->Size, tmppath ); + node->Type->Read( node, 0, node->Size, tmppath ); tmppath[ node->Size ] = '\0'; - if(node->Close) node->Close( node ); + _CloseNode( node ); // Open the target node = VFS_ParsePath(tmppath, NULL, &mnt); if(!node) { @@ -536,8 +521,8 @@ int VFS_Open(const char *Path, Uint Mode) LEAVE_RET('i', -1); } } - - LEAVE_RET('x', VFS_int_CreateHandle(node, mnt, Mode)); + + LEAVE_RET('x', VFS_int_CreateHandle(node, mnt, Flags)); } @@ -561,13 +546,20 @@ int VFS_OpenChild(int FD, const char *Name, Uint Mode) // Check for directory if( !(h->Node->Flags & VFS_FFLAG_DIRECTORY) ) { - Log_Warning("VFS", "VFS_OpenChild - Passed handle is not a directory", FD); + Log_Warning("VFS", "VFS_OpenChild - Passed handle is not a directory"); + errno = ENOTDIR; + LEAVE_RET('i', -1); + } + + // Sanity check + if( !h->Node->Type || !h->Node->Type->FindDir ) { + Log_Error("VFS", "VFS_OpenChild - Node does not have a type/is missing FindDir"); errno = ENOTDIR; LEAVE_RET('i', -1); } // Find Child - node = h->Node->FindDir(h->Node, Name); + node = h->Node->Type->FindDir(h->Node, Name); if(!node) { errno = ENOENT; LEAVE_RET('i', -1); @@ -632,8 +624,7 @@ void VFS_Close(int FD) } #endif - if(h->Node->Close) - h->Node->Close( h->Node ); + _CloseNode(h->Node); h->Node = NULL; } @@ -650,14 +641,14 @@ int VFS_ChDir(const char *Dest) // Create Absolute buf = VFS_GetAbsPath(Dest); if(buf == NULL) { - Log("VFS_ChDir: Path expansion failed"); + Log_Notice("VFS", "VFS_ChDir: Path expansion failed"); return -1; } // Check if path exists fd = VFS_Open(buf, VFS_OPENFLAG_EXEC); if(fd == -1) { - Log("VFS_ChDir: Path is invalid"); + Log_Notice("VFS", "VFS_ChDir: Path is invalid"); return -1; } @@ -672,11 +663,13 @@ int VFS_ChDir(const char *Dest) // Close file VFS_Close(fd); - // Free old working directory - if( CFGPTR(CFG_VFS_CWD) ) - free( CFGPTR(CFG_VFS_CWD) ); - // Set new - CFGPTR(CFG_VFS_CWD) = buf; + { + char **cwdptr = Threads_GetCWD(); + // Free old working directory + if( *cwdptr ) free( *cwdptr ); + // Set new + *cwdptr = buf; + } Log("Updated CWD to '%s'", buf); @@ -720,12 +713,13 @@ int VFS_ChRoot(const char *New) // Close file VFS_Close(fd); - - // Free old working directory - if( CFGPTR(CFG_VFS_CHROOT) ) - free( CFGPTR(CFG_VFS_CHROOT) ); - // Set new - CFGPTR(CFG_VFS_CHROOT) = buf; + + // Update + { + char **chroot_ptr = Threads_GetChroot(); + if( *chroot_ptr ) free( *chroot_ptr ); + *chroot_ptr = buf; + } LOG("Updated Root to '%s'", buf);