X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fvfs%2Fopen.c;h=f0b5734a4ec13696d5e590b64314c0842e090fd8;hb=7b64f5e7f00e445a5637e9e3289a1332a14d28e5;hp=e83ace8f7ae5531c03d31c464a2724105420aa56;hpb=d0b4559f2936f6d9f06be0f7c3c51527a480ec0d;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/vfs/open.c b/KernelLand/Kernel/vfs/open.c index e83ace8f..f0b5734a 100644 --- a/KernelLand/Kernel/vfs/open.c +++ b/KernelLand/Kernel/vfs/open.c @@ -18,13 +18,12 @@ // === IMPORTS === 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 === void _ReferenceMount(tVFS_Mount *Mount, const char *DebugTag); void _DereferenceMount(tVFS_Mount *Mount, const char *DebugTag); - int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode ); + int VFS_int_CreateHandle(tVFS_Node *Node, tVFS_Mount *Mount, int Mode); // === CODE === void _ReferenceMount(tVFS_Mount *Mount, const char *DebugTag) @@ -297,8 +296,9 @@ restart_parse: pathEle[nextSlash] = 0; // Check permissions on root of filesystem - if( !VFS_CheckACL(curNode, VFS_PERM_EXECUTE) ) { + if( !VFS_CheckACL(curNode, VFS_PERM_EXEC) ) { LOG("Permissions failure on '%s'", Path); + errno = EPERM; goto _error; } @@ -317,7 +317,7 @@ restart_parse: } LOG("FindDir{=%p}(%p, '%s')", curNode->Type->FindDir, curNode, pathEle); // Get Child Node - tmpNode = curNode->Type->FindDir(curNode, pathEle); + tmpNode = curNode->Type->FindDir(curNode, pathEle, 0); LOG("tmpNode = %p", tmpNode); _CloseNode( curNode ); curNode = tmpNode; @@ -325,6 +325,7 @@ restart_parse: // Error Check if(!curNode) { LOG("Node '%s' not found in dir '%s'", pathEle, Path); + errno = ENOENT; goto _error; } @@ -337,11 +338,13 @@ restart_parse: if(!curNode->Type || !curNode->Type->Read) { Log_Warning("VFS", "VFS_ParsePath - Read of symlink node %p'%s' is NULL", curNode, Path); + errno = EINTERNAL; goto _error; } if(iNestedLinks > MAX_NESTED_LINKS) { Log_Notice("VFS", "VFS_ParsePath - Nested link limit exceeded"); + errno = ENOENT; goto _error; } @@ -352,9 +355,10 @@ restart_parse: int remlen = strlen(Path) - (ofs + nextSlash); if( curNode->Size + remlen > MAX_PATH_LEN ) { Log_Warning("VFS", "VFS_ParsePath - Symlinked path too long"); + errno = ENOENT; goto _error; } - curNode->Type->Read( curNode, 0, curNode->Size, path_buffer ); + curNode->Type->Read( curNode, 0, curNode->Size, path_buffer, 0 ); path_buffer[ curNode->Size ] = '\0'; LOG("path_buffer = '%s'", path_buffer); strcat(path_buffer, Path + ofs+nextSlash); @@ -375,6 +379,7 @@ restart_parse: if( !(curNode->Flags & VFS_FFLAG_DIRECTORY) ) { Log_Warning("VFS", "VFS_ParsePath - Path segment is not a directory"); + errno = ENOTDIR; goto _error; } @@ -386,6 +391,7 @@ restart_parse: // Check if allocation succeeded if(!tmp) { Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer"); + errno = ENOMEM; goto _error; } *TruePath = tmp; @@ -402,16 +408,18 @@ restart_parse: // Check final finddir call if( !curNode->Type || !curNode->Type->FindDir ) { Log_Warning("VFS", "VFS_ParsePath - FindDir doesn't exist for element of '%s'", Path); + errno = ENOENT; goto _error; } // Get last node LOG("FindDir(%p, '%s')", curNode, &Path[ofs]); - tmpNode = curNode->Type->FindDir(curNode, &Path[ofs]); + tmpNode = curNode->Type->FindDir(curNode, &Path[ofs], 0); LOG("tmpNode = %p", tmpNode); // Check if file was found if(!tmpNode) { LOG("Node '%s' not found in dir '%.*s'", &Path[ofs], ofs, Path); + errno = ENOENT; goto _error; } _CloseNode( curNode ); @@ -423,6 +431,7 @@ restart_parse: // Check if allocation succeeded if(!tmp) { Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer"); + errno = ENOMEM; goto _error; } *TruePath = tmp; @@ -451,7 +460,6 @@ _error: } // Open failed, so decrement the open handle count _DereferenceMount(mnt, "ParsePath - error"); - LEAVE('n'); return NULL; } @@ -466,7 +474,7 @@ int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode ) ENTER("pNode pMount xMode", Node, Mount, Mode); i = 0; - i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0; + i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXEC : 0; i |= (Mode & VFS_OPENFLAG_READ) ? VFS_PERM_READ : 0; i |= (Mode & VFS_OPENFLAG_WRITE) ? VFS_PERM_WRITE : 0; @@ -549,7 +557,7 @@ int VFS_OpenEx(const char *Path, Uint Flags, Uint Mode) } // Check ACLs on the parent - if( !VFS_CheckACL(pnode, VFS_PERM_EXECUTE|VFS_PERM_WRITE) ) { + if( !VFS_CheckACL(pnode, VFS_PERM_EXEC|VFS_PERM_WRITE) ) { errno = EACCES; goto _pnode_err; } @@ -611,7 +619,7 @@ int VFS_OpenEx(const char *Path, Uint Flags, Uint Mode) goto _error; } // Read symlink's path - node->Type->Read( node, 0, node->Size, tmppath ); + node->Type->Read( node, 0, node->Size, tmppath, 0 ); tmppath[ node->Size ] = '\0'; _CloseNode( node ); _DereferenceMount(mnt, "Open - symlink"); @@ -669,7 +677,7 @@ int VFS_OpenChild(int FD, const char *Name, Uint Mode) } // Find Child - node = h->Node->Type->FindDir(h->Node, Name); + node = h->Node->Type->FindDir(h->Node, Name, 0); if(!node) { errno = ENOENT; LEAVE_RET('i', -1); @@ -698,7 +706,8 @@ int VFS_OpenInode(Uint32 Mount, Uint64 Inode, int Mode) // Does the filesystem support this? if( !mnt->Filesystem->GetNodeFromINode ) { - LOG("Filesystem does not support inode accesses"); + Log_Notice("VFS", "Filesystem '%s' does not support inode accesses", + mnt->Filesystem->Name); errno = ENOENT; LEAVE_RET('i', -1); } @@ -714,6 +723,30 @@ int VFS_OpenInode(Uint32 Mount, Uint64 Inode, int Mode) LEAVE_RET('x', VFS_int_CreateHandle(node, mnt, Mode)); } +int VFS_Reopen(int FD, const char *Path, int Flags) +{ + tVFS_Handle *h = VFS_GetHandle(FD); + if(!h) { + errno = EBADF; + return -1; + } + + int newf = VFS_Open(Path, Flags); + if( newf == -1 ) { + return -1; + } + + _CloseNode(h->Node); + _DereferenceMount(h->Mount, "Reopen"); + memcpy(h, VFS_GetHandle(newf), sizeof(*h)); + _ReferenceNode(h->Node); + _ReferenceMount(h->Mount, "Reopen"); + + VFS_Close(newf); + + return FD; +} + /** * \fn void VFS_Close(int FD) * \brief Closes an open file handle @@ -752,6 +785,44 @@ void VFS_Close(int FD) h->Node = NULL; } +int VFS_DuplicateFD(int SrcFD, int DstFD) +{ + int isUser = !(SrcFD & VFS_KERNEL_FLAG); + tVFS_Handle *src = VFS_GetHandle(SrcFD); + if( !src ) return -1; + if( DstFD == -1 ) { + DstFD = VFS_AllocHandle(isUser, src->Node, src->Mode); + } + else { + // Can't overwrite + if( VFS_GetHandle(DstFD) ) + return -1; + VFS_SetHandle(DstFD, src->Node, src->Mode); + } + _ReferenceMount(src->Mount, "DuplicateFD"); + _ReferenceNode(src->Node); + memcpy(VFS_GetHandle(DstFD), src, sizeof(tVFS_Handle)); + return DstFD; +} + +/* + * Update flags on a FD + */ +int VFS_SetFDFlags(int FD, int Mask, int Value) +{ + tVFS_Handle *h = VFS_GetHandle(FD); + if(!h) { + errno = EBADF; + return -1; + } + int ret = h->Mode; + + Value &= Mask; + h->Mode &= ~Mask; + h->Mode |= Value; + return ret; +} + /** * \brief Change current working directory */