Code: Select all
Dir *parsePath(const char *path, int flags, int *error)
{
kprintf_debug("start of parsePath()\n");
*error = VFS_NO_FILE; // default error
// TODO: relative paths
if (path[0] != '/')
{
return NULL;
};
SplitPath spath;
if (resolveMounts(path, &spath) != 0)
{
return NULL;
};
char token[128];
char *end = (char*) &token[127];
const char *scan = spath.filename;
if (spath.fs->openroot == NULL)
{
return NULL;
};
Dir *dir = (Dir*) kmalloc(sizeof(Dir));
memset(dir, 0, sizeof(Dir));
if (spath.fs->openroot(spath.fs, dir, sizeof(Dir)) != 0)
{
kfree(dir);
return NULL;
};
while (1)
{
char *put = token;
while ((*scan != 0) && (*scan != '/'))
{
if (put == end)
{
*put = 0;
panic("parsePath(): token too long: '%s'\n", token);
};
*put++ = *scan++;
};
*put = 0;
kprintf_debug("token '%s'\n", token);
if (strlen(token) == 0)
{
if (*scan == 0)
{
return dir;
};
if (dir->close != NULL) dir->close(dir);
kfree(dir);
return NULL;
};
while (strcmp(dir->dirent.d_name, token) != 0)
{
if (dir->next(dir) != 0)
{
if (dir->close != NULL) dir->close(dir);
kfree(dir);
return NULL;
};
};
if (*scan == '/')
{
if ((dir->stat.st_mode & VFS_MODE_DIRECTORY) == 0)
{
*error = VFS_NOT_DIR;
if (dir->close != NULL) dir->close(dir);
kfree(dir);
return NULL;
};
if ((!vfsCanCurrentThread(&dir->stat, 1)) && (flags & VFS_CHECK_ACCESS))
{
if (dir->close != NULL) dir->close(dir);
kfree(dir);
*error = VFS_PERM;
return NULL;
};
Dir *subdir = (Dir*) kmalloc(sizeof(Dir));
memset(subdir, 0, sizeof(Dir));
if (dir->opendir(dir, subdir, sizeof(Dir)) != 0)
{
kfree(subdir);
if (dir->close != NULL) dir->close(dir);
kfree(dir);
return NULL;
};
if (dir->close != NULL) dir->close(dir);
kfree(dir);
dir = subdir;
scan++; // skip over '/'
}
else
{
return dir;
};
};
};
I know that when an interrupt occurs in user mode, the CPU sets the RSP to the value RSP0 from the TSS. And as far as I know, if an interrupt occurs in kernel mode, the interrupt stack from is pushed onto the current stack - it does not take the value from RSP0, is that correct?
When I do a task switch, I change the value of RSP0 in the TSS to a distinct per-thread value, so I do not see how the stack could be breaking. On the other hand, the fact that parsePath() seems to be throwing those exceptions MOST (but not all) of the time, I think something could be wrong with it, but it does appear correct.
If I am right about the RSP0 thing, then what else could be causing the stack to break? And if I'm wrong, how can I make the kernel preemptive without breaking the stack?