summaryrefslogtreecommitdiff
path: root/kernel/src/generic/vfs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/generic/vfs.cpp')
-rw-r--r--kernel/src/generic/vfs.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/kernel/src/generic/vfs.cpp b/kernel/src/generic/vfs.cpp
index d34ae0c..75c3ed8 100644
--- a/kernel/src/generic/vfs.cpp
+++ b/kernel/src/generic/vfs.cpp
@@ -1,6 +1,140 @@
#include <cstdint>
#include <generic/vfs.hpp>
#include <drivers/disk.hpp>
+#include <klibc/string.hpp>
+#include <utils/errno.hpp>
+#include <klibc/stdio.hpp>
+#include <generic/lock/mutex.hpp>
+
+// /bin/path -> /usr/bin/path
+void __vfs_symlink_resolve_no_at_symlink_follow(char* path, char* out) {
+ char *next = nullptr;
+ char buffer[4096];
+
+ int e = vfs::readlink(path,buffer,4096);
+
+ if(e == ENOSYS)
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+
+ if(e == EINVAL)
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ else if(e == 0) {
+
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ } else if(e == ENOENT) {
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ // maybe it wants directory symlink ?
+ char path0[4096];
+ klibc::memcpy(path0,path,klibc::strlen(path) + 1);
+
+ char result[4096];
+
+ int c = 0;
+
+ char* token = klibc::strtok(&next, path0, "/");
+
+ /* Start building path from null and trying to find symlink */
+ while(token) {
+
+ result[c] = '/';
+ c++;
+
+ std::uint64_t mm = 0;
+ mm = klibc::strlen(token);
+ klibc::memcpy((char*)((std::uint64_t)result + c),token,mm);
+ c += mm;
+ result[c] = '\0';
+
+ e = vfs::readlink(result,buffer,4096);
+ if(e == 0) {
+ char buffer2[4096];
+ vfs::resolve_path(buffer,result,buffer2,0);
+ c = klibc::strlen(buffer2);
+ buffer2[c++] = '/';
+ klibc::memcpy(buffer2 + c, path + klibc::strlen(result) + 1, klibc::strlen(path) - klibc::strlen(result));
+ __vfs_symlink_resolve_no_at_symlink_follow(buffer2,out);
+ return;
+ } else if(e == ENOENT) {
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ }
+
+ token = klibc::strtok(&next,0,"/");
+ }
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ }
+}
+
+void __vfs_symlink_resolve(char* path, char* out, int level) {
+
+ char *next = nullptr;
+
+ char buffer[4096];
+
+ if(level == 25) {
+ // hell no :skull:
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ return;
+ }
+
+ int e = vfs::readlink(path,buffer,4096);
+
+ if(e == ENOSYS)
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+
+ if(e == EINVAL)
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ else if(e == 0) {
+
+ char result[4096];
+ vfs::resolve_path(buffer,path,result,0);
+ __vfs_symlink_resolve(result,out, level + 1);
+ } else if(e == ENOENT) {
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ // maybe it wants directory symlink ?
+ char path0[4096];
+ klibc::memcpy(path0,path,klibc::strlen(path) + 1);
+
+ char result[4096];
+
+ int c = 0;
+
+ char* token = klibc::strtok(&next, path0, "/");
+
+ /* Start building path from null and trying to find symlink */
+ while(token) {
+
+ result[c] = '/';
+ c++;
+
+ std::uint64_t mm = 0;
+ mm = klibc::strlen(token);
+ klibc:: memcpy((char*)((std::uint64_t)result + c),token,mm);
+ c += mm;
+ result[c] = '\0';
+
+ e = vfs::readlink(result,buffer,4096);
+ if(e == 0) {
+ char buffer2[4096];
+ vfs::resolve_path(buffer,result,buffer2,0);
+ c = klibc::strlen(buffer2);
+ buffer2[c++] = '/';
+ klibc::memcpy(buffer2 + c, path + klibc::strlen(result) + 1, klibc::strlen(path) - klibc::strlen(result));
+ __vfs_symlink_resolve(buffer2,out, level + 1);
+ return;
+ } else if(e == ENOENT) {
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ return;
+ } else {
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ return;
+ }
+
+ token = klibc::strtok(&next,0,"/");
+ }
+ klibc::memcpy(out,path,klibc::strlen(path) + 1);
+ }
+}
+
void vfs::init() {