#include "vfs.h"
#include "vfs_int.h"
#include "vfs_ext.h"
+#include <threads.h>
// === CONSTANTS ===
#define OPEN_MOUNT_ROOT 1
#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 );
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);
}
// - 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] == '/') {
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);
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;
}
*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;
}
// 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
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
{
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;
}
// EVIL: Goto :)
+ LOG("Symlink -> '%s', restart", Path);
goto 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
// 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
// - 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)
{
// 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
LEAVE('p', tmpNode);
return tmpNode;
+
+_error:
+ _CloseNode( curNode );
+
+ if(TruePath && *TruePath) {
+ free(*TruePath);
+ *TruePath = NULL;
+ }
+ LEAVE('n');
+ return NULL;
}
/**
int VFS_int_CreateHandle( tVFS_Node *Node, tVFS_Mount *Mount, int Mode )
{
int i;
+
+ ENTER("pNode pMount xMode", Node, Mount, Mode);
+
i = 0;
i |= (Mode & VFS_OPENFLAG_EXEC) ? VFS_PERM_EXECUTE : 0;
i |= (Mode & VFS_OPENFLAG_READ) ? VFS_PERM_READ : 0;
// 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);
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) {
LEAVE_RET('i', -1);
}
}
-
+
LEAVE_RET('x', VFS_int_CreateHandle(node, mnt, 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);
tVFS_Mount *mnt;
tVFS_Node *node;
- ENTER("iMount iInode xMode", Mount, Inode, Mode);
+ ENTER("iMount XInode xMode", Mount, Inode, Mode);
// Get mount point
mnt = VFS_GetMountByIdent(Mount);
// Does the filesystem support this?
if( !mnt->Filesystem->GetNodeFromINode ) {
+ LOG("Filesystem does not support inode accesses");
errno = ENOENT;
LEAVE_RET('i', -1);
}
// Get node
node = mnt->Filesystem->GetNodeFromINode(mnt->RootNode, Inode);
if( !node ) {
+ LOG("Unable to find inode");
errno = ENOENT;
LEAVE_RET('i', -1);
}
}
#endif
- if(h->Node->Close)
- h->Node->Close( h->Node );
+ _CloseNode(h->Node);
h->Node = NULL;
}
// 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;
}
// 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);
// 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);