197 lines
5.0 KiB
Nim
197 lines
5.0 KiB
Nim
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
|
# Rumpk L1: Sovereign VFS (Indexing TarFS)
|
|
|
|
{.push stackTrace: off, lineTrace: off.}
|
|
|
|
import std/tables
|
|
|
|
# Kernel Imports (Avoid circular dependency)
|
|
proc kprint(s: cstring) {.importc, cdecl.}
|
|
proc kprintln(s: cstring) {.importc, cdecl.}
|
|
proc kprint_hex(n: uint64) {.importc, cdecl.} # Assuming this exists or I need to implement it equivalent
|
|
|
|
# --- TAR HEADER DEF (USTAR) ---
|
|
type
|
|
TarHeader* {.packed.} = object
|
|
name*: array[100, char]
|
|
mode*: array[8, char]
|
|
uid*: array[8, char]
|
|
gid*: array[8, char]
|
|
size*: array[12, char]
|
|
mtime*: array[12, char]
|
|
chksum*: array[8, char]
|
|
typeflag*: char
|
|
linkname*: array[100, char]
|
|
magic*: array[6, char]
|
|
version*: array[2, char]
|
|
uname*: array[32, char]
|
|
gname*: array[32, char]
|
|
devmajor*: array[8, char]
|
|
devminor*: array[8, char]
|
|
prefix*: array[155, char]
|
|
# Padding to 512 handled by jump logic
|
|
|
|
FileEntry = object
|
|
offset*: uint64
|
|
size*: uint64
|
|
|
|
FileHandle = object
|
|
path*: string
|
|
offset*: uint64
|
|
|
|
VFSInitRD* = object
|
|
start_addr*: uint64
|
|
end_addr*: uint64
|
|
index*: Table[string, FileEntry]
|
|
fds*: Table[int, FileHandle]
|
|
next_fd*: int
|
|
|
|
var vfs*: VFSInitRD
|
|
|
|
# --- HELPERS ---
|
|
|
|
proc parse_octal(a: openArray[char]): uint64 =
|
|
var res: uint64 = 0
|
|
var started = false
|
|
for c in a:
|
|
if c >= '0' and c <= '7':
|
|
res = (res shl 3) or (uint64(c) - uint64('0'))
|
|
started = true
|
|
elif started:
|
|
break
|
|
return res
|
|
|
|
proc align_512(n: uint64): uint64 =
|
|
if (n and 511) != 0:
|
|
return (n + 512) and not 511'u64
|
|
return n
|
|
|
|
proc cstring_to_nim(ptr_char: ptr char, max_len: int): string =
|
|
var res = newStringOfCap(max_len)
|
|
var p = ptr_char
|
|
var i = 0
|
|
while i < max_len and p[] != '\0':
|
|
res.add(p[])
|
|
p = cast[ptr char](cast[uint64](p) + 1)
|
|
i += 1
|
|
return res
|
|
|
|
# --- API ---
|
|
|
|
proc vfs_init*(s: pointer, e: pointer) =
|
|
vfs.start_addr = cast[uint64](s)
|
|
vfs.end_addr = cast[uint64](e)
|
|
vfs.index = initTable[string, FileEntry]()
|
|
vfs.fds = initTable[int, FileHandle]()
|
|
vfs.next_fd = 3 # 0,1,2 reserved
|
|
|
|
kprint("[VFS] Mounting TarFS InitRD... Start=")
|
|
kprint_hex(vfs.start_addr)
|
|
kprint(" End=")
|
|
kprint_hex(vfs.end_addr)
|
|
kprint(" Size=")
|
|
kprint_hex(vfs.end_addr - vfs.start_addr)
|
|
kprintln("")
|
|
|
|
var ptr_curr = vfs.start_addr
|
|
|
|
while ptr_curr < vfs.end_addr:
|
|
let header = cast[ptr TarHeader](ptr_curr)
|
|
|
|
# Check bounds safety before reading header
|
|
if ptr_curr + 512 > vfs.end_addr: break
|
|
|
|
# Check End of Archive (Empty Block)
|
|
if header.name[0] == '\0': break
|
|
|
|
let fname = cstring_to_nim(addr header.name[0], 100)
|
|
let size = parse_octal(header.size)
|
|
discard parse_octal(header.mode)
|
|
|
|
|
|
var clean_name = fname
|
|
if clean_name.len >= 2 and clean_name[0] == '.' and clean_name[1] == '/':
|
|
clean_name = clean_name[2..^1]
|
|
|
|
# Index Files (Type '0' or '\0')
|
|
if header.typeflag == '0' or header.typeflag == '\0':
|
|
if clean_name.len > 0:
|
|
let data_offset = ptr_curr + 512
|
|
vfs.index[clean_name] = FileEntry(offset: data_offset, size: size)
|
|
|
|
# Jump to next header
|
|
ptr_curr += 512 + align_512(size)
|
|
|
|
proc vfs_open*(path: string): int =
|
|
if vfs.index.hasKey(path):
|
|
let fd = vfs.next_fd
|
|
vfs.fds[fd] = FileHandle(path: path, offset: 0)
|
|
vfs.next_fd += 1
|
|
return fd
|
|
return -1
|
|
|
|
proc vfs_get_entry*(path: string): (pointer, uint64) =
|
|
if vfs.index.hasKey(path):
|
|
let entry = vfs.index[path]
|
|
return (cast[pointer](entry.offset), entry.size)
|
|
return (nil, 0)
|
|
|
|
# --- C EXPORTS (THE BRIDGE) ---
|
|
|
|
proc ion_vfs_open*(path: cstring): int32 {.exportc, cdecl.} =
|
|
return int32(vfs_open($path))
|
|
|
|
proc ion_vfs_read*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
|
|
let fd_int = int(fd)
|
|
if not vfs.fds.hasKey(fd_int): return -1
|
|
|
|
var fh = vfs.fds[fd_int] # Get a mutable copy of the FileHandle
|
|
let (base_ptr, total_size) = vfs_get_entry(fh.path)
|
|
|
|
if base_ptr == nil: return 0
|
|
if fh.offset >= total_size: return 0 # EOF
|
|
|
|
# Calculate remaining bytes
|
|
let remaining = total_size - fh.offset
|
|
let to_read = min(uint64(remaining), count)
|
|
|
|
if to_read > 0:
|
|
let data_ptr = cast[pointer](cast[uint64](base_ptr) + fh.offset)
|
|
copyMem(buf, data_ptr, to_read)
|
|
|
|
# Update cursor
|
|
fh.offset += to_read
|
|
vfs.fds[fd_int] = fh # Write back to table
|
|
|
|
return int64(to_read)
|
|
|
|
return 0
|
|
|
|
proc vfs_list_files*(): string =
|
|
var res = ""
|
|
for name, entry in vfs.index:
|
|
res.add(name)
|
|
res.add("\n")
|
|
return res
|
|
|
|
proc ion_vfs_list*(buf: pointer, max_len: uint64): int64 {.exportc, cdecl.} =
|
|
let list = vfs_list_files()
|
|
let len = min(list.len, int(max_len))
|
|
if len > 0:
|
|
copyMem(buf, unsafeAddr list[0], len)
|
|
return int64(len)
|
|
|
|
proc vfs_read_file*(path: string): string =
|
|
if vfs.index.hasKey(path):
|
|
let entry = vfs.index[path]
|
|
let ptr_data = cast[ptr UncheckedArray[char]](entry.offset)
|
|
var s = newString(entry.size)
|
|
if entry.size > 0:
|
|
copyMem(addr s[0], ptr_data, entry.size)
|
|
return s
|
|
|
|
return ""
|
|
|
|
|
|
{.pop.}
|