- Remove unnecessary debug print statements in VFS and WebDAV middleware for cleaner code. - Fix a bug in `OurDBVFS.exists` to correctly handle root and current directory paths. - Enhance `OurDBVFS.get_entry` to handle '.' path correctly. - Improve WebDAV authentication middleware to gracefully handle unauthenticated requests.
353 lines
8.1 KiB
V
353 lines
8.1 KiB
V
module vfsourdb
|
|
|
|
import freeflowuniverse.herolib.vfs.vfscore
|
|
import freeflowuniverse.herolib.vfs.ourdb_fs
|
|
import os
|
|
import time
|
|
|
|
// OurDBVFS represents a VFS that uses OurDB as the underlying storage
|
|
pub struct OurDBVFS {
|
|
mut:
|
|
core &ourdb_fs.OurDBFS
|
|
}
|
|
|
|
// new creates a new OurDBVFS instance
|
|
pub fn new(data_dir string, metadata_dir string) !&OurDBVFS {
|
|
mut core := ourdb_fs.new(
|
|
data_dir: data_dir
|
|
metadata_dir: metadata_dir
|
|
incremental_mode: false
|
|
)!
|
|
|
|
return &OurDBVFS{
|
|
core: core
|
|
}
|
|
}
|
|
|
|
// Implementation of VFSImplementation interface
|
|
pub fn (mut self OurDBVFS) root_get() !vfscore.FSEntry {
|
|
mut root := self.core.get_root()!
|
|
return convert_to_vfscore_entry(root)
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) file_create(path string) !vfscore.FSEntry {
|
|
// Get parent directory
|
|
parent_path := os.dir(path)
|
|
file_name := os.base(path)
|
|
|
|
mut parent_dir := self.get_directory(parent_path)!
|
|
mut file := parent_dir.touch(file_name)!
|
|
return convert_to_vfscore_entry(file)
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) file_read(path string) ![]u8 {
|
|
mut entry := self.get_entry(path)!
|
|
if mut entry is ourdb_fs.File {
|
|
content := entry.read()!
|
|
return content.bytes()
|
|
}
|
|
return error('Not a file: ${path}')
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) file_write(path string, data []u8) ! {
|
|
mut entry := self.get_entry(path)!
|
|
if mut entry is ourdb_fs.File {
|
|
entry.write(data.bytestr())!
|
|
} else {
|
|
return error('Not a file: ${path}')
|
|
}
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) delete(path string) ! {
|
|
println('Not implemented')
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) link_delete(path string) ! {
|
|
parent_path := os.dir(path)
|
|
file_name := os.base(path)
|
|
|
|
mut parent_dir := self.get_directory(parent_path)!
|
|
parent_dir.rm(file_name)!
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) file_delete(path string) ! {
|
|
parent_path := os.dir(path)
|
|
file_name := os.base(path)
|
|
|
|
mut parent_dir := self.get_directory(parent_path)!
|
|
parent_dir.rm(file_name)!
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) dir_create(path string) !vfscore.FSEntry {
|
|
parent_path := os.dir(path)
|
|
dir_name := os.base(path)
|
|
|
|
mut parent_dir := self.get_directory(parent_path)!
|
|
mut new_dir := parent_dir.mkdir(dir_name)!
|
|
new_dir.save()! // Ensure the directory is saved
|
|
|
|
return convert_to_vfscore_entry(new_dir)
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) dir_list(path string) ![]vfscore.FSEntry {
|
|
mut dir := self.get_directory(path)!
|
|
mut entries := dir.children(false)!
|
|
mut result := []vfscore.FSEntry{}
|
|
|
|
for entry in entries {
|
|
result << convert_to_vfscore_entry(entry)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) dir_delete(path string) ! {
|
|
parent_path := os.dir(path)
|
|
dir_name := os.base(path)
|
|
|
|
mut parent_dir := self.get_directory(parent_path)!
|
|
parent_dir.rm(dir_name)!
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) exists(path_ string) bool {
|
|
path := if !path_.starts_with('/') {
|
|
'/${path_}'
|
|
} else {
|
|
path_
|
|
}
|
|
if path == '/' {
|
|
return true
|
|
}
|
|
self.get_entry(path) or { return false }
|
|
return true
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) get(path string) !vfscore.FSEntry {
|
|
mut entry := self.get_entry(path)!
|
|
return convert_to_vfscore_entry(entry)
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) rename(old_path string, new_path string) ! {
|
|
return error('Not implemented')
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) copy(src_path string, dst_path string) ! {
|
|
return error('Not implemented')
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) move(src_path string, dst_path string) ! {
|
|
return error('Not implemented')
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) link_create(target_path string, link_path string) !vfscore.FSEntry {
|
|
parent_path := os.dir(link_path)
|
|
link_name := os.base(link_path)
|
|
|
|
mut parent_dir := self.get_directory(parent_path)!
|
|
|
|
mut symlink := ourdb_fs.Symlink{
|
|
metadata: ourdb_fs.Metadata{
|
|
id: self.core.get_next_id()
|
|
name: link_name
|
|
file_type: .symlink
|
|
created_at: time.now().unix()
|
|
modified_at: time.now().unix()
|
|
accessed_at: time.now().unix()
|
|
mode: 0o777
|
|
owner: 'user'
|
|
group: 'user'
|
|
}
|
|
target: target_path
|
|
parent_id: parent_dir.metadata.id
|
|
myvfs: self.core
|
|
}
|
|
|
|
parent_dir.add_symlink(mut symlink)!
|
|
return convert_to_vfscore_entry(symlink)
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) link_read(path string) !string {
|
|
mut entry := self.get_entry(path)!
|
|
if mut entry is ourdb_fs.Symlink {
|
|
return entry.get_target()!
|
|
}
|
|
return error('Not a symlink: ${path}')
|
|
}
|
|
|
|
pub fn (mut self OurDBVFS) destroy() ! {
|
|
// Nothing to do as the core VFS handles cleanup
|
|
}
|
|
|
|
fn (mut self OurDBVFS) get_entry(path string) !ourdb_fs.FSEntry {
|
|
if path == '/' || path == '' || path == '.' {
|
|
return ourdb_fs.FSEntry(self.core.get_root()!)
|
|
}
|
|
|
|
mut current := *self.core.get_root()!
|
|
parts := path.trim_left('/').split('/')
|
|
|
|
for i := 0; i < parts.len; i++ {
|
|
mut found := false
|
|
children := current.children(false)!
|
|
|
|
for child in children {
|
|
if child.metadata.name == parts[i] {
|
|
match child {
|
|
ourdb_fs.Directory {
|
|
current = child
|
|
found = true
|
|
break
|
|
}
|
|
else {
|
|
if i == parts.len - 1 {
|
|
return child
|
|
} else {
|
|
return error('Not a directory: ${parts[i]}')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
return error('Path not found: ${path}')
|
|
}
|
|
}
|
|
|
|
return ourdb_fs.FSEntry(current)
|
|
}
|
|
|
|
fn (mut self OurDBVFS) get_directory(path string) !&ourdb_fs.Directory {
|
|
mut entry := self.get_entry(path)!
|
|
if mut entry is ourdb_fs.Directory {
|
|
return &entry
|
|
}
|
|
return error('Not a directory: ${path}')
|
|
}
|
|
|
|
fn convert_to_vfscore_entry(entry ourdb_fs.FSEntry) vfscore.FSEntry {
|
|
match entry {
|
|
ourdb_fs.Directory {
|
|
return &DirectoryEntry{
|
|
metadata: convert_metadata(entry.metadata)
|
|
path: entry.metadata.name
|
|
}
|
|
}
|
|
ourdb_fs.File {
|
|
return &FileEntry{
|
|
metadata: convert_metadata(entry.metadata)
|
|
path: entry.metadata.name
|
|
}
|
|
}
|
|
ourdb_fs.Symlink {
|
|
return &SymlinkEntry{
|
|
metadata: convert_metadata(entry.metadata)
|
|
path: entry.metadata.name
|
|
target: entry.target
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn convert_metadata(meta ourdb_fs.Metadata) vfscore.Metadata {
|
|
return vfscore.Metadata{
|
|
id: meta.id
|
|
name: meta.name
|
|
file_type: match meta.file_type {
|
|
.file { vfscore.FileType.file }
|
|
.directory { vfscore.FileType.directory }
|
|
.symlink { vfscore.FileType.symlink }
|
|
}
|
|
size: meta.size
|
|
created_at: meta.created_at
|
|
modified_at: meta.modified_at
|
|
accessed_at: meta.accessed_at
|
|
}
|
|
}
|
|
|
|
// Entry type implementations
|
|
struct DirectoryEntry {
|
|
metadata vfscore.Metadata
|
|
path string
|
|
}
|
|
|
|
fn (e &DirectoryEntry) get_metadata() vfscore.Metadata {
|
|
return e.metadata
|
|
}
|
|
|
|
fn (e &DirectoryEntry) get_path() string {
|
|
return e.path
|
|
}
|
|
|
|
// is_dir returns true if the entry is a directory
|
|
pub fn (self &DirectoryEntry) is_dir() bool {
|
|
return self.metadata.file_type == .directory
|
|
}
|
|
|
|
// is_file returns true if the entry is a file
|
|
pub fn (self &DirectoryEntry) is_file() bool {
|
|
return self.metadata.file_type == .file
|
|
}
|
|
|
|
// is_symlink returns true if the entry is a symlink
|
|
pub fn (self &DirectoryEntry) is_symlink() bool {
|
|
return self.metadata.file_type == .symlink
|
|
}
|
|
|
|
struct FileEntry {
|
|
metadata vfscore.Metadata
|
|
path string
|
|
}
|
|
|
|
fn (e &FileEntry) get_metadata() vfscore.Metadata {
|
|
return e.metadata
|
|
}
|
|
|
|
fn (e &FileEntry) get_path() string {
|
|
return e.path
|
|
}
|
|
|
|
// is_dir returns true if the entry is a directory
|
|
pub fn (self &FileEntry) is_dir() bool {
|
|
return self.metadata.file_type == .directory
|
|
}
|
|
|
|
// is_file returns true if the entry is a file
|
|
pub fn (self &FileEntry) is_file() bool {
|
|
return self.metadata.file_type == .file
|
|
}
|
|
|
|
// is_symlink returns true if the entry is a symlink
|
|
pub fn (self &FileEntry) is_symlink() bool {
|
|
return self.metadata.file_type == .symlink
|
|
}
|
|
|
|
struct SymlinkEntry {
|
|
metadata vfscore.Metadata
|
|
path string
|
|
target string
|
|
}
|
|
|
|
fn (e &SymlinkEntry) get_metadata() vfscore.Metadata {
|
|
return e.metadata
|
|
}
|
|
|
|
fn (e &SymlinkEntry) get_path() string {
|
|
return e.path
|
|
}
|
|
|
|
// is_dir returns true if the entry is a directory
|
|
pub fn (self &SymlinkEntry) is_dir() bool {
|
|
return self.metadata.file_type == .directory
|
|
}
|
|
|
|
// is_file returns true if the entry is a file
|
|
pub fn (self &SymlinkEntry) is_file() bool {
|
|
return self.metadata.file_type == .file
|
|
}
|
|
|
|
// is_symlink returns true if the entry is a symlink
|
|
pub fn (self &SymlinkEntry) is_symlink() bool {
|
|
return self.metadata.file_type == .symlink
|
|
}
|