diff options
author | Anton Kling <anton@kling.gg> | 2023-11-16 22:55:30 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-11-16 22:55:30 +0100 |
commit | 6723c96863425bda541e321127f6944bf008446a (patch) | |
tree | cb2836166dfe819e9942fdb87a6ce41cb684061c /kernel/fs/vfs.c | |
parent | a288258785bac3c2000227532f4a17210813c506 (diff) |
VFS: Do canonicalization of the current working directory
Diffstat (limited to 'kernel/fs/vfs.c')
-rw-r--r-- | kernel/fs/vfs.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c index 2347369..d0c1b95 100644 --- a/kernel/fs/vfs.c +++ b/kernel/fs/vfs.c @@ -125,25 +125,61 @@ vfs_inode_t *vfs_internal_open(const char *file) { return ret; } -char *vfs_clean_path(const char *path, char *resolved_path) { - char *clean = resolved_path; - int prev_slash = 0; - char *ptr = clean; +// Does canonicalization of absolute paths +int vfs_clean_path(const char *path, char *result) { + // It has to be a absolute path + if ('/' != *path) + return 0; + const char *result_start = result; + int start_directory = 0; + int should_insert_slash = 0; for (; *path; path++) { - if (prev_slash && '/' == *path) { - continue; + if (start_directory) { + start_directory = 0; + if ('/' == *path) { + path++; + } else if (0 == memcmp(path, "./", 2) || 0 == memcmp(path, ".\0", 2)) { + path++; + } else if (0 == memcmp(path, "../", 3) || 0 == memcmp(path, "..\0", 3)) { + path += 2; + if (result_start + 2 > result) { + // The path is probably something like "/.." or + // "/../foo". A "/.." should become a "/" + // Therefore it skips going back to the parent + if (*path == '/') { + if (result_start == result) + return 0; + result--; + } + } else { + if ('/' != *path) { + should_insert_slash = 1; + } + result--; + result--; + for (; result_start <= result && '/' != *result; result--) + ; + } + } } - prev_slash = ('/' == *path); - *ptr = *path; - ptr++; + start_directory = ('/' == *path); + if ('\0' == *path) + break; + *result = *path; + result++; + } + if (should_insert_slash) { + *result = '/'; + result++; } - *ptr = '\0'; - return clean; + *result = '\0'; + return 1; } char *vfs_resolve_path(const char *file, char *resolved_path) { if ('/' == *file) { - return vfs_clean_path(file, resolved_path); + assert(vfs_clean_path(file, resolved_path)); + return resolved_path; } const char *cwd = get_current_task()->current_working_directory; size_t l = strlen(cwd); @@ -152,8 +188,8 @@ char *vfs_resolve_path(const char *file, char *resolved_path) { char r[256]; strcpy(r, cwd); strcat(r, file); - char *final = vfs_clean_path(r, resolved_path); - return final; + assert(vfs_clean_path(r, resolved_path)); + return resolved_path; } int vfs_fstat(int fd, struct stat *buf) { |