*/
#define DEBUG 0
#include <acess.h>
-#include <mm_virt.h>
#include "vfs.h"
#include "vfs_int.h"
#include "vfs_ext.h"
// === CONSTANTS ===
#define OPEN_MOUNT_ROOT 1
-#define MAX_KERNEL_FILES 128
#define MAX_PATH_SLASHES 256
+#define MAX_NESTED_LINKS 4
+#define MAX_PATH_LEN 255
// === IMPORTS ===
extern tVFS_Node gVFS_MemRoot;
extern tVFS_Mount *gVFS_RootMount;
-
-// === GLOBALS ===
-tVFS_Handle *gaUserHandles = (void*)MM_PPD_VFS;
-tVFS_Handle *gaKernelHandles = (void*)MM_KERNEL_VFS;
+extern int VFS_AllocHandle(int bIsUser, tVFS_Node *Node, int Mode);
// === CODE ===
/**
char *tmpStr;
int iPos = 0;
int iPos2 = 0;
- char *chroot = CFGPTR(CFG_VFS_CHROOT);
+ const char *chroot = CFGPTR(CFG_VFS_CHROOT);
int chrootLen;
- char *cwd = CFGPTR(CFG_VFS_CWD);
+ const char *cwd = CFGPTR(CFG_VFS_CWD);
int cwdLen;
ENTER("sPath", Path);
if(Path[0] == '$') {
ret = malloc(strlen(Path)+1);
if(!ret) {
- Warning("VFS_GetAbsPath - malloc() returned NULL");
+ Log_Warning("VFS", "VFS_GetAbsPath: malloc() returned NULL");
return NULL;
}
strcpy(ret, Path);
if(Path[0] == '/') {
ret = malloc(pathLen + 1);
if(!ret) {
- Warning("VFS_GetAbsPath - malloc() returned NULL");
+ Log_Warning("VFS", "VFS_GetAbsPath: malloc() returned NULL");
return NULL;
}
strcpy(ret, Path);
strcpy(ret, cwd);
ret[cwdLen] = '/';
strcpy(&ret[cwdLen+1], Path);
- //Log("ret = '%s'\n", ret);
+ //Log("ret = '%s'", ret);
}
// Parse Path
*/
tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath)
{
- tVFS_Mount *mnt;
- tVFS_Mount *longestMount = gVFS_RootMount; // Root is first
+ tVFS_Mount *mnt, *longestMount;
int cmp, retLength = 0;
int ofs, nextSlash;
+ int iNestedLinks = 0;
tVFS_Node *curNode, *tmpNode;
char *tmp;
+ char path_buffer[MAX_PATH_LEN+1];
ENTER("sPath pTruePath", Path, TruePath);
LEAVE('p', curNode);
return curNode;
}
-
+
+restart_parse:
// For root we always fast return
if(Path[0] == '/' && Path[1] == '\0') {
if(TruePath) {
return gVFS_RootMount->RootNode;
}
- // Check if there is an`ything mounted
+ // Check if there is anything mounted
if(!gVFS_Mounts) {
Warning("WTF! There's nothing mounted?");
return NULL;
}
// Find Mountpoint
+ longestMount = gVFS_RootMount;
for(mnt = gVFS_Mounts;
mnt;
mnt = mnt->Next)
// Initialise String
if(TruePath)
{
- *TruePath = malloc( mnt->MountPointLen+1 );
+ // Assumes that the resultant path (here) will not be > strlen(Path) + 1
+ *TruePath = malloc( strlen(Path) + 1 );
strcpy(*TruePath, mnt->MountPoint);
retLength = mnt->MountPointLen;
}
Warning("VFS_ParsePath - Read of node %p is NULL (%s)",
curNode, Path);
if(curNode->Close) curNode->Close(curNode);
- // No need to free *TruePath, see above
+ // No need to free *TruePath, it should already be NULL
LEAVE('n');
return NULL;
}
- tmp = malloc( curNode->Size + 1 );
- if(!tmp) {
- Log_Warning("VFS", "VFS_ParsePath - Malloc failure");
- // No need to free *TruePath, see above
+ if(iNestedLinks > MAX_NESTED_LINKS) {
+ if(curNode->Close) curNode->Close(curNode);
LEAVE('n');
return NULL;
}
- curNode->Read( curNode, 0, curNode->Size, tmp );
- tmp[ curNode->Size ] = '\0';
// Parse Symlink Path
- curNode = VFS_ParsePath(tmp, TruePath);
- if(TruePath)
- LOG("VFS", "*TruePath='%s'", *TruePath);
-
- // Error Check
- if(!curNode) {
- Log_Debug("VFS", "Symlink fail '%s'", tmp);
- free(tmp); // Free temp string
- if(TruePath) free(TruePath);
- LEAVE('n');
- return NULL;
+ // - Just update the path variable and restart the function
+ // > Count nested symlinks and limit to some value (counteracts loops)
+ {
+ 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;
+ }
+ curNode->Read( curNode, 0, curNode->Size, path_buffer );
+ path_buffer[ curNode->Size ] = '\0';
+ strcat(path_buffer, &Path[ofs+nextSlash]);
+
+ Path = path_buffer;
+ iNestedLinks ++;
}
- // Free temp link
- free(tmp);
-
- // Set Path Variable
- if(TruePath) {
- retLength = strlen(*TruePath);
- }
-
- continue;
+
+ // EVIL: Goto :)
+ goto restart_parse;
}
// Handle Non-Directories
tmp = realloc(*TruePath, retLength + strlen(&Path[ofs]) + 1 + 1);
// Check if allocation succeeded
if(!tmp) {
- Warning("VFS_ParsePath - Unable to reallocate true path buffer");
+ Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer");
free(*TruePath);
if(tmpNode->Close) tmpNode->Close(curNode);
LEAVE('n');
}
/**
- * \fn int VFS_Open(char *Path, Uint Mode)
+ * \fn int VFS_Open(const char *Path, Uint Mode)
* \brief Open a file
*/
-int VFS_Open(char *Path, Uint Mode)
+int VFS_Open(const char *Path, Uint Mode)
{
tVFS_Node *node;
char *absPath;
return -1;
}
- // Check for a user open
- if(Mode & VFS_OPENFLAG_USER)
- {
- // Allocate Buffer
- if( MM_GetPhysAddr( (Uint)gaUserHandles ) == 0 )
- {
- Uint addr, size;
- size = CFGINT(CFG_VFS_MAXFILES) * sizeof(tVFS_Handle);
- for(addr = 0; addr < size; addr += 0x1000)
- MM_Allocate( (Uint)gaUserHandles + addr );
- memset( gaUserHandles, 0, size );
- }
- // Get a handle
- for(i=0;i<CFGINT(CFG_VFS_MAXFILES);i++)
- {
- if(gaUserHandles[i].Node) continue;
- gaUserHandles[i].Node = node;
- gaUserHandles[i].Position = 0;
- gaUserHandles[i].Mode = Mode;
- LEAVE('i', i);
- return i;
- }
- }
- else
- {
- // Allocate space if not already
- if( MM_GetPhysAddr( (Uint)gaKernelHandles ) == 0 )
- {
- Uint addr, size;
- size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
- for(addr = 0; addr < size; addr += 0x1000)
- MM_Allocate( (Uint)gaKernelHandles + addr );
- memset( gaKernelHandles, 0, size );
- }
- // Get a handle
- for(i=0;i<MAX_KERNEL_FILES;i++)
- {
- if(gaKernelHandles[i].Node) continue;
- gaKernelHandles[i].Node = node;
- gaKernelHandles[i].Position = 0;
- gaKernelHandles[i].Mode = Mode;
- LEAVE('x', i|VFS_KERNEL_FLAG);
- return i|VFS_KERNEL_FLAG;
- }
+ i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), node, Mode );
+ if( i >= 0 ) {
+ LEAVE('x', i);
+ return i;
}
Log("VFS_Open: Out of handles");
/**
* \brief Open a file from an open directory
*/
-int VFS_OpenChild(Uint *Errno, int FD, char *Name, Uint Mode)
+int VFS_OpenChild(Uint *Errno, int FD, const char *Name, Uint Mode)
{
tVFS_Handle *h;
tVFS_Node *node;
return -1;
}
- // Check for a user open
- if(Mode & VFS_OPENFLAG_USER)
- {
- // Allocate Buffer
- if( MM_GetPhysAddr( (Uint)gaUserHandles ) == 0 )
- {
- Uint addr, size;
- size = CFGINT(CFG_VFS_MAXFILES) * sizeof(tVFS_Handle);
- for(addr = 0; addr < size; addr += 0x1000)
- MM_Allocate( (Uint)gaUserHandles + addr );
- memset( gaUserHandles, 0, size );
- }
- // Get a handle
- for(i=0;i<CFGINT(CFG_VFS_MAXFILES);i++)
- {
- if(gaUserHandles[i].Node) continue;
- gaUserHandles[i].Node = node;
- gaUserHandles[i].Position = 0;
- gaUserHandles[i].Mode = Mode;
- LEAVE('i', i);
- return i;
- }
- }
- else
- {
- // Allocate space if not already
- if( MM_GetPhysAddr( (Uint)gaKernelHandles ) == 0 )
- {
- Uint addr, size;
- size = MAX_KERNEL_FILES * sizeof(tVFS_Handle);
- for(addr = 0; addr < size; addr += 0x1000)
- MM_Allocate( (Uint)gaKernelHandles + addr );
- memset( gaKernelHandles, 0, size );
- }
- // Get a handle
- for(i=0;i<MAX_KERNEL_FILES;i++)
- {
- if(gaKernelHandles[i].Node) continue;
- gaKernelHandles[i].Node = node;
- gaKernelHandles[i].Position = 0;
- gaKernelHandles[i].Mode = Mode;
- LEAVE('x', i|VFS_KERNEL_FLAG);
- return i|VFS_KERNEL_FLAG;
- }
+ i = VFS_AllocHandle( !!(Mode & VFS_OPENFLAG_USER), node, Mode );
+ if( i >= 0 ) {
+ LEAVE('x', i);
+ return i;
}
Log_Error("VFS", "VFS_OpenChild - Out of handles");
// Get handle
h = VFS_GetHandle(FD);
if(h == NULL) {
- Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x\n", FD);
+ Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x", FD);
return;
}
/**
* \brief Change current working directory
*/
-int VFS_ChDir(char *Dest)
+int VFS_ChDir(const char *Dest)
{
char *buf;
int fd;
* \fn int VFS_ChRoot(char *New)
* \brief Change current root directory
*/
-int VFS_ChRoot(char *New)
+int VFS_ChRoot(const char *New)
{
char *buf;
int fd;
return 1;
}
-/**
- * \fn tVFS_Handle *VFS_GetHandle(int FD)
- * \brief Gets a pointer to the handle information structure
- */
-tVFS_Handle *VFS_GetHandle(int FD)
-{
- tVFS_Handle *h;
-
- //Log_Debug("VFS", "VFS_GetHandle: (FD=0x%x)", FD);
-
- if(FD < 0) return NULL;
-
- if(FD & VFS_KERNEL_FLAG) {
- FD &= (VFS_KERNEL_FLAG - 1);
- if(FD >= MAX_KERNEL_FILES) return NULL;
- h = &gaKernelHandles[ FD ];
- } else {
- if(FD >= CFGINT(CFG_VFS_MAXFILES)) return NULL;
- h = &gaUserHandles[ FD ];
- }
-
- if(h->Node == NULL) return NULL;
- //Log_Debug("VFS", "VFS_GetHandle: RETURN %p", h);
- return h;
-}
-
// === EXPORTS ===
EXPORT(VFS_Open);
EXPORT(VFS_Close);