A toy operating system written in C.
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.
 
 
 
 
freywaros/src/kernel/path.c

84 lines
2.3 KiB

#include "src/kernel/path.h"
#include "src/kernel/fs.h"
#include "src/lib/memory.h"
#include "src/lib/string.h"
#include "src/lib/util.h"
path_t *path_open(const fs_node_t *root, const path_t *source, const char *path) {
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 < source->depth; i++) {
result->stack[result->depth++] = fs_open_again(source->stack[i]);
}
}
for (uint8_t i = 0; i < path_length; i++) {
if (string_empty(path_components[i]) || string_equal(path_components[i], ".")) {
continue;
} else if (string_equal(path_components[i], "..")) {
if (result->depth) {
fs_close(result->stack[--result->depth]);
}
} else {
const fs_node_t *prev = result->depth ? result->stack[result->depth - 1] : root;
fs_node_t *next = prev->is_dir ? fs_open_by(prev, path_components[i]) : NUL;
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;
}
fs_node_t *path_open_file(const fs_node_t *root, const path_t *source, const char *path) {
path_t *p = path_open(root, source, path);
if (!p) {
return NUL;
}
if (!p->depth || p->stack[p->depth - 1]->is_dir) {
path_close(p);
return NUL;
}
fs_node_t *n = fs_open_again(p->stack[p->depth - 1]);
path_close(p);
return n;
}
fs_node_t *path_open_directory(const fs_node_t *root, const path_t *source, const char *path) {
path_t *p = path_open(root, source, path);
if (!p) {
return NUL;
}
if (!p->depth) {
path_close(p);
return (fs_node_t *)root;
}
if (!p->stack[p->depth - 1]->is_dir) {
path_close(p);
return NUL;
}
fs_node_t *n = fs_open_again(p->stack[p->depth - 1]);
path_close(p);
return n;
}
void path_close(path_t *path) {
for (uint64_t i = 0; i < path->depth; i++) {
fs_close(path->stack[i]);
}
memory_free(path);
}