diff options
author | Anton Kling <anton@kling.gg> | 2023-11-22 00:47:55 +0100 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2023-11-22 00:47:55 +0100 |
commit | f3c7d7fbdea1f2bac81909116ddb747a1f8abdf5 (patch) | |
tree | 62a1d998ce11bf4db4343f69dea4e8d231191e48 /userland/libc/stdlib | |
parent | 24f81104f5ff9cb4ab7db766c53f77fe0e5b86cc (diff) |
Meta: Cleanup of header files such that they are partially shared
The /include directory contains definitons that both the kernel and libc
need to be in sync.
Diffstat (limited to 'userland/libc/stdlib')
-rw-r--r-- | userland/libc/stdlib/realpath.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/userland/libc/stdlib/realpath.c b/userland/libc/stdlib/realpath.c new file mode 100644 index 0000000..438ed8d --- /dev/null +++ b/userland/libc/stdlib/realpath.c @@ -0,0 +1,61 @@ +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +// FIXME: This is nowhere near complete +char *realpath(const char *filename, char *resolvedname) { + assert(resolvedname); + // FIXME: This really should have bounds checking + char cwd[256]; + getcwd(cwd, 256); + strcat(cwd, filename); + const char *path = cwd; + char *result = resolvedname; + // 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 (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--) + ; + } + } + } + start_directory = ('/' == *path); + if ('\0' == *path) + break; + *result = *path; + result++; + } + if (should_insert_slash) { + *result = '/'; + result++; + } + *result = '\0'; + return 1; +} |