diff --git a/include/string.h b/include/string.h index 2c2ed98..2f76470 100644 --- a/include/string.h +++ b/include/string.h @@ -11,5 +11,6 @@ size_t strlen(const char*); char *strcat(char *dest, const char *src); char *strcpy(char *dest, const char *src); char *strtok(char *str, const char *delim); +char *strrchr(const char *s, int c); #endif diff --git a/src/tasking/syscalls.c b/src/tasking/syscalls.c index b87956d..45f3893 100644 --- a/src/tasking/syscalls.c +++ b/src/tasking/syscalls.c @@ -442,59 +442,55 @@ int sys_execve(TrapFrame *tf) { int sys_chdir(TrapFrame *tf) { - l9660_dir new_cwd; + const char* path = (const char*)tf->ebx; + size_t path_len = strlen(path); l9660_file placeholder_file; + l9660_dir target_dir; - new_cwd = *current->cwd; + target_dir = *current->cwd; + int status = follow_path(path, &placeholder_file, &target_dir); - int status = follow_path((char*)tf->ebx, &placeholder_file, &new_cwd); + // Case 1: The path does not end with a slash (e.g., "/path/to/dir" or "/path/to/file") + if (path_len == 0 || path[path_len - 1] != '/') { + // If follow_path succeeded, it means the path was a file, which is an error for chdir. + if (status == L9660_OK) { + return -20; // Return -ENOTDIR + } - if(status == L9660_OK) - { - *(current->cwd) = new_cwd; + // If it failed with L9660_ENOTFILE, it means we found a directory when expecting a file. + // This is the expected outcome for a directory path. + if (status == L9660_ENOTFILE) { + // The safe way to proceed is to re-traverse the path with a trailing slash. + // This avoids using the potentially corrupt 'target_dir' left by the failed call. + char new_path[path_len + 2]; + memcpy(new_path, path, path_len); + new_path[path_len] = '/'; + new_path[path_len + 1] = '\0'; + + // Reset target_dir and try again with the corrected path. + target_dir = *current->cwd; + status = follow_path(new_path, &placeholder_file, &target_dir); + } } - if(status == L9660_ENOTFILE) - { - l9660_dir dir1; - l9660_status err = l9660_opendirat(&dir1, &new_cwd, (char*)tf->ebx); - if(err != L9660_ENOTDIR) - { - *(current->cwd) = dir1; - return 0; - } + // At this point, 'status' should be L9660_OK if the path was a valid directory. + if (status == L9660_OK) { + *current->cwd = target_dir; + return 0; } switch(status) { case L9660_EIO: - return -5;//-EIO - break; case L9660_EBADFS: - return -5;//EIO as well - break; + return -5; // -EIO case L9660_ENOENT: - return -2; - break; + return -2; // -ENOENT case L9660_ENOTDIR: - return -20;//ENOTDIR - break; - case L9660_OK: - return 0; - break; + return -20; // -ENOTDIR default: - return -5;//EIO - break; + return -1; // Generic error } - - //strcat(current->cwd->fat->path, "/"); - //strcat(current->cwd->fat->path, (char*)tf->ebx); - - int result = 0;//fat_opendir(current->cwd, (const char*)tf->ebx); - if(result == 0) - return 0; - - return -1; } #include "../include/vfs.h" diff --git a/src/utils/string.c b/src/utils/string.c index 9a525fa..268ce3f 100644 --- a/src/utils/string.c +++ b/src/utils/string.c @@ -149,4 +149,15 @@ char *strtok(char *str, const char *delim) { } return token_start; +} + +char *strrchr(const char *s, int c) { + const char *p = NULL; + + for (;;) { + if (*s == (char)c) + p = s; + if (*s++ == '\0') + return (char *)p; + } } \ No newline at end of file