164 lines
4.6 KiB
Nim
164 lines
4.6 KiB
Nim
# MARKUS MAIWALD (ARCHITECT) | VOXIS FORGE (AI)
|
|
# Rumpk L1: Sovereign VFS (Indexing TarFS)
|
|
|
|
{.push stackTrace: off, lineTrace: off.}
|
|
|
|
import std/tables
|
|
|
|
# Kernel Imports
|
|
proc kprint(s: cstring) {.importc, cdecl.}
|
|
proc kprintln(s: cstring) {.importc, cdecl.}
|
|
proc kprint_hex(n: uint64) {.importc, cdecl.}
|
|
|
|
type
|
|
TarHeader* = array[512, byte]
|
|
|
|
FileEntry = object
|
|
offset*: uint64
|
|
size*: uint64
|
|
is_sfs*: bool
|
|
|
|
FileHandle = object
|
|
path*: string
|
|
offset*: uint64
|
|
is_sfs*: bool
|
|
|
|
VFSInitRD* = object
|
|
start_addr*: uint64
|
|
end_addr*: uint64
|
|
index*: Table[string, FileEntry]
|
|
fds*: Table[int, FileHandle]
|
|
next_fd*: int
|
|
|
|
var vfs*: VFSInitRD
|
|
|
|
proc toHexChar(b: byte): char =
|
|
if b < 10: return char(byte('0') + b)
|
|
else: return char(byte('A') + (b - 10))
|
|
|
|
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
|
|
|
|
var p = vfs.start_addr
|
|
while p < vfs.end_addr:
|
|
let h = cast[ptr TarHeader](p)
|
|
if h[][0] == byte(0): break
|
|
|
|
var name = ""
|
|
for i in 0..99:
|
|
if h[][i] == byte(0): break
|
|
name.add(char(h[][i]))
|
|
|
|
var size: uint64 = 0
|
|
for i in 124..134:
|
|
let b = h[][i]
|
|
if b >= byte('0') and b <= byte('7'):
|
|
size = (size shl 3) or uint64(b - byte('0'))
|
|
|
|
# Manual Normalization
|
|
var clean = name
|
|
if clean.len > 2 and clean[0] == '.' and clean[1] == '/':
|
|
# Strip ./
|
|
var new_clean = ""
|
|
for i in 2 ..< clean.len: new_clean.add(clean[i])
|
|
clean = new_clean
|
|
elif clean.len > 1 and clean[0] == '/':
|
|
# Strip /
|
|
var new_clean = ""
|
|
for i in 1 ..< clean.len: new_clean.add(clean[i])
|
|
clean = new_clean
|
|
|
|
if clean.len > 0:
|
|
vfs.index[clean] = FileEntry(offset: p + 512'u64, size: size, is_sfs: false)
|
|
kprint("[VFS] Indexed: '")
|
|
kprint(cstring(clean))
|
|
kprint("' Size: ")
|
|
var ss = ""; ss.add($size); kprintln(cstring(ss))
|
|
else:
|
|
kprint("[VFS] Empty Name? Raw: ")
|
|
var r = ""
|
|
for i in 0..min(10, name.len-1):
|
|
r.add(toHexChar(byte(name[i]) shr 4))
|
|
r.add(toHexChar(byte(name[i]) and 0xF))
|
|
r.add(' ')
|
|
kprintln(cstring(r))
|
|
|
|
p += 512'u64 + ((size + 511'u64) and not 511'u64)
|
|
|
|
proc vfs_open*(path: string): int =
|
|
var clean = path
|
|
if clean.len > 0 and clean[0] == '/':
|
|
var nc = ""; for i in 1..<clean.len: nc.add(clean[i]); clean = nc
|
|
|
|
if vfs.index.hasKey(clean):
|
|
let entry = vfs.index[clean]
|
|
let fd = vfs.next_fd
|
|
vfs.fds[fd] = FileHandle(path: clean, offset: 0, is_sfs: entry.is_sfs)
|
|
vfs.next_fd += 1
|
|
return fd
|
|
return -1
|
|
|
|
proc vfs_read_file*(path: string): string =
|
|
var clean = path
|
|
if clean.len > 0 and clean[0] == '/':
|
|
var nc = ""; for i in 1..<clean.len: nc.add(clean[i]); clean = nc
|
|
|
|
kprint("[VFS] Reading: '"); kprint(cstring(clean)); kprint("' -> ")
|
|
|
|
if vfs.index.hasKey(clean):
|
|
let entry = vfs.index[clean]
|
|
kprintln("FOUND.")
|
|
if entry.is_sfs: return ""
|
|
var s = newString(int(entry.size))
|
|
if entry.size > 0:
|
|
copyMem(addr s[0], cast[pointer](entry.offset), int(entry.size))
|
|
return s
|
|
|
|
kprintln("NOT FOUND.")
|
|
# Debug Keys
|
|
kprint("Available: ")
|
|
for k in vfs.index.keys:
|
|
kprint("'"); kprint(cstring(k)); kprint("' ")
|
|
kprintln("")
|
|
return ""
|
|
|
|
proc ion_vfs_open*(path: cstring): int32 {.exportc, cdecl.} =
|
|
return int32(vfs_open($path))
|
|
|
|
proc sfs_read_file(name: cstring, dest: pointer, max_len: int): int {.importc, cdecl.}
|
|
|
|
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]
|
|
if fh.is_sfs:
|
|
let n = sfs_read_file(cstring(fh.path), buf, int(count))
|
|
if n > 0: fh.offset += uint64(n); vfs.fds[fd_int] = fh; return int64(n)
|
|
return 0
|
|
if vfs.index.hasKey(fh.path):
|
|
let entry = vfs.index[fh.path]
|
|
if fh.offset >= entry.size: return 0
|
|
let to_read = min(uint64(entry.size - fh.offset), count)
|
|
if to_read > 0:
|
|
copyMem(buf, cast[pointer](entry.offset + fh.offset), int(to_read))
|
|
fh.offset += to_read
|
|
vfs.fds[fd_int] = fh
|
|
return int64(to_read)
|
|
return 0
|
|
|
|
proc ion_vfs_list*(buf: pointer, max_len: uint64): int64 {.exportc, cdecl.} =
|
|
var s = ""
|
|
for name, _ in vfs.index: s.add(name & "\n")
|
|
let n = min(s.len, int(max_len))
|
|
if n > 0: copyMem(buf, addr s[0], n)
|
|
return int64(n)
|
|
|
|
proc vfs_register_sfs*(name: string, size: uint64) {.exportc, cdecl.} =
|
|
vfs.index[name] = FileEntry(offset: 0, size: size, is_sfs: true)
|
|
|
|
{.pop.}
|