You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.6 KiB
98 lines
2.6 KiB
#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);
|
|
}
|
|
|