#include "src/kernel/path.h" #include "src/kernel/fs.h" #include "src/kernel/stream.h" #include "src/lib/memory.h" #include "src/lib/string.h" #include "src/lib/syscall.h" #include "src/lib/util.h" path_t *path_open(const path_t *base, const char *path, uint64_t flags) { if (!base || !path) { return NUL; } uint64_t length = string_length(path); char *path_own = memory_allocate(length + 1); memory_copy(path, length + 1, path_own); path_t *result = memory_allocate(sizeof(path_t)); char *path_components[PATH_DEPTH]; uint8_t path_length = (uint8_t)string_split(path_own, '/', PATH_DEPTH, path_components); if (!string_empty(path_components[0])) { for (uint8_t i = 0; i < base->depth; i++) { result->stack[result->depth++] = fs_open_again(base->stack[i]); } } for (uint8_t i = 0; i < path_length; i++) { if (!result->depth) { result->stack[result->depth++] = fs_open_root(); } if (string_empty(path_components[i]) || string_equal(path_components[i], ".")) { if (i == path_length - 1 && result->depth) { // TODO Apply flags to current top of stack. } continue; } else if (string_equal(path_components[i], "..")) { if (result->depth > 1) { fs_close(result->stack[--result->depth]); } } else { fs_node_t *next = fs_open_by(result->stack[result->depth - 1], path_components[i], i < path_length - 1 ? (flags & ~(uint64_t)OPEN_EXCLUSIVE) | OPEN_DIRECTORY : flags); if (!next || result->depth >= PATH_DEPTH) { path_close(result); memory_free(path_own); return NUL; } else { result->stack[result->depth++] = next; } } } memory_free(path_own); return result; } path_t *path_open_again(const path_t *path) { if (!path) { return NUL; } path_t *p = memory_allocate(sizeof(path_t)); p->depth = path->depth; for (uint8_t i = 0; i < path->depth; i++) { p->stack[i] = fs_open_again(path->stack[i]); } return p; } fs_node_t *path_open_node(const path_t *base, const char *path, uint64_t flags) { path_t *p = path_open(base, path, flags); if (!p) { return NUL; } fs_node_t *n = fs_open_again(p->stack[p->depth - 1]); path_close(p); return n; } stream_t *path_open_stream(const path_t *base, const char *path, uint64_t flags) { path_t *p = path_open(base, path, flags); if (!p) { return NUL; } stream_t *s = fs_open_stream(p->stack[p->depth - 1]); path_close(p); return s; } void path_close(path_t *path) { for (uint64_t i = 0; i < path->depth; i++) { fs_close(path->stack[i]); } memory_free(path); }