diff options
Diffstat (limited to 'kernel/src/generic/vfs.hpp')
| -rw-r--r-- | kernel/src/generic/vfs.hpp | 173 |
1 files changed, 164 insertions, 9 deletions
diff --git a/kernel/src/generic/vfs.hpp b/kernel/src/generic/vfs.hpp index 8736d42..d6fac32 100644 --- a/kernel/src/generic/vfs.hpp +++ b/kernel/src/generic/vfs.hpp @@ -37,7 +37,11 @@ struct stat { struct filesystem { locks::mutex lock; - std::uint32_t (*open)(void* file_desc, char* path); + union { + std::uint64_t partition; + } fs_specific; + + std::uint32_t (*open)(filesystem* fs, void* file_desc, char* path); char path[2048]; }; @@ -45,30 +49,181 @@ struct filesystem { struct file_descriptor { file_descriptor_type type; + + std::size_t offset; std::uint32_t flags; - union fs_specific { + union { std::uint64_t ino; std::uint64_t tmpfs_pointer; - }; + } fs_specific; - struct vnode { + struct { disk* target_disk; filesystem* fs; signed long (*read)(file_descriptor* file, void* buffer, signed long count); signed long (*write)(file_descriptor* file, void* buffer, signed long count); - signed long (*stat)(file_descriptor* file, stat* out); + std::int32_t (*stat)(file_descriptor* file, stat* out); void (*close)(file_descriptor* file); - }; + } vnode; }; namespace vfs { void init(); - void open(file_descriptor* fd, char* path, bool follow_symlinks ); - void create(char* path, std::uint32_t mode); // mode contains type too + std::int32_t open(file_descriptor* fd, char* path, bool follow_symlinks); + std::int32_t create(char* path, std::uint32_t mode); // mode contains type too + std::int32_t readlink(char* path, char* out, std::uint32_t out_len); } -// fs should setup this during open +// took from old kernel +namespace vfs { + static inline std::uint64_t resolve_count(char* str,std::uint64_t sptr,char delim) { + char* current = str; + std::uint16_t att = 0; + std::uint64_t ptr = sptr; + while(current[ptr] != delim) { + if(att > 1024) + return 0; + att++; + + if(ptr != 0) { + ptr--; + } + } + return ptr; + } + + + static inline int normalize_path(const char* src, char* dest, std::uint64_t dest_size) { + if (!src ||!dest || dest_size < 2) return -1; + std::uint64_t j = 0; + int prev_slash = 0; + for (std::uint64_t i = 0; src[i] && j < dest_size - 1; i++) { + if (src[i] == '/') { + if (!prev_slash) { + dest[j++] = '/'; + prev_slash = 1; + } + } else { + dest[j++] = src[i]; + prev_slash = 0; + } + } + + if (j > 1 && dest[j-1] == '/') j--; + if (j >= dest_size) { + dest[0] = '\0'; + return -1; + } + dest[j] = '\0'; + return 0; + } + + /* I'll use path resolver from my old kernel */ + static inline void resolve_path(const char* inter0,const char* base, char *result, char spec) { + char* next = 0; + char buffer2_in_stack[2048]; + char inter[2048]; + char* buffer = 0; + char* final_buffer = (char*)buffer2_in_stack; + std::uint64_t ptr = klibc::strlen((char*)base); + char is_first = 1; + char is_full = 0; + + klibc::memcpy(inter,inter0,klibc::strlen(inter0) + 1); + + if(klibc::strlen((char*)inter) == 1 && inter[0] == '.') { + klibc::memcpy(result,base,klibc::strlen((char*)base) + 1); + if(result[0] == '\0') { + result[0] = '/'; + result[1] = '\0'; + } + return; + } + + if(!klibc::strcmp(inter,"/")) { + klibc::memcpy(result,inter,klibc::strlen((char*)inter) + 1); + if(result[0] == '\0') { + result[0] = '/'; + result[1] = '\0'; + } + return; + } + + if(inter[0] == '/') { + ptr = 0; + is_full = 1; + } else { + klibc::memcpy(final_buffer,base,klibc::strlen((char*)base) + 1); + } + + if(spec) + is_first = 0; + + if(!klibc::strcmp(base,"/")) + is_first = 0; + + buffer = klibc::strtok(&next,(char*)inter,"/"); + while(buffer) { + + if(is_first && !is_full) { + std::uint64_t mm = resolve_count(final_buffer,ptr,'/'); + + if(ptr < mm) { + final_buffer[0] = '/'; + final_buffer[1] = '\0'; + ptr = 1; + continue; + } + + ptr = mm; + final_buffer[ptr] = '\0'; + is_first = 0; + } + + if(!klibc::strcmp(buffer,"..")) { + std::uint64_t mm = resolve_count(final_buffer,ptr,'/'); + + if(!klibc::strcmp(final_buffer,"/\0")) { + buffer = klibc::strtok(&next,0,"/"); + continue; + } + + + if(ptr < mm) { + final_buffer[0] = '/'; + final_buffer[1] = '\0'; + ptr = 1; + continue; + } + + ptr = mm; + final_buffer[ptr] = '\0'; + + + + } else if(klibc::strcmp(buffer,"./") && klibc::strcmp(buffer,".")) { + + final_buffer[ptr] = '/'; + ptr++; + + std::uint64_t mm = 0; + mm = klibc::strlen(buffer); + klibc::memcpy((char*)((std::uint64_t)final_buffer + ptr),buffer,mm); + ptr += mm; + final_buffer[ptr] = '\0'; + } + + buffer = klibc::strtok(&next,0,"/"); + } + normalize_path(final_buffer,result,2048); + + if(result[0] == '\0') { + result[0] = '/'; + result[1] = '\0'; + } + } +}
\ No newline at end of file |
