summaryrefslogtreecommitdiff
path: root/userland/libc/stdlib
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-11-22 00:47:55 +0100
committerAnton Kling <anton@kling.gg>2023-11-22 00:47:55 +0100
commitf3c7d7fbdea1f2bac81909116ddb747a1f8abdf5 (patch)
tree62a1d998ce11bf4db4343f69dea4e8d231191e48 /userland/libc/stdlib
parent24f81104f5ff9cb4ab7db766c53f77fe0e5b86cc (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.c61
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;
+}