rumpk/core/fs/vfs.nim

166 lines
4.9 KiB
Nim

# SPDX-License-Identifier: LSL-1.0
# Copyright (c) 2026 Markus Maiwald
# Stewardship: Self Sovereign Society Foundation
#
# This file is part of the Nexus Sovereign Core.
# See legal/LICENSE_SOVEREIGN.md for license terms.
## Rumpk Layer 1: Sovereign VFS (The Loom)
##
## Freestanding implementation (No OS module dependencies).
## Uses fixed-size arrays for descriptors to ensure deterministic latency.
import tar, sfs
type
VFSMode = enum
MODE_TAR, MODE_SFS, MODE_RAM, MODE_TTY
MountPoint = object
prefix: array[32, char]
mode: VFSMode
FileHandle = object
path: array[64, char]
offset: uint64
mode: VFSMode
active: bool
const MAX_MOUNTS = 8
const MAX_FDS = 32
var mnt_table: array[MAX_MOUNTS, MountPoint]
var mnt_count: int = 0
var fd_table: array[MAX_FDS, FileHandle]
# Helper: manual string compare
proc vfs_starts_with(s, prefix: cstring): bool =
let ps = cast[ptr UncheckedArray[char]](s)
let pp = cast[ptr UncheckedArray[char]](prefix)
var i = 0
while pp[i] != '\0':
if ps[i] != pp[i]: return false
i += 1
return true
proc vfs_streq(s1, s2: cstring): bool =
let p1 = cast[ptr UncheckedArray[char]](s1)
let p2 = cast[ptr UncheckedArray[char]](s2)
var i = 0
while true:
if p1[i] != p2[i]: return false
if p1[i] == '\0': return true
i += 1
proc vfs_add_mount(prefix: cstring, mode: VFSMode) =
if mnt_count >= MAX_MOUNTS: return
let p = cast[ptr UncheckedArray[char]](prefix)
var i = 0
while p[i] != '\0' and i < 31:
mnt_table[mnt_count].prefix[i] = p[i]
i += 1
mnt_table[mnt_count].prefix[i] = '\0'
mnt_table[mnt_count].mode = mode
mnt_count += 1
proc vfs_mount_init*() =
# Restore the SPEC-130 baseline
vfs_add_mount("/nexus", MODE_SFS)
vfs_add_mount("/sysro", MODE_TAR)
vfs_add_mount("/state", MODE_RAM)
vfs_add_mount("/dev/tty", MODE_TTY)
vfs_add_mount("/Bus/Console/tty0", MODE_TTY)
proc resolve_path(path: cstring): (VFSMode, int) =
for i in 0..<mnt_count:
let prefix = cast[cstring](addr mnt_table[i].prefix[0])
if vfs_starts_with(path, prefix):
var len = 0
while mnt_table[i].prefix[len] != '\0': len += 1
return (mnt_table[i].mode, len)
return (MODE_TAR, 0)
proc ion_vfs_open*(path: cstring, flags: int32): int32 {.exportc, cdecl.} =
let (mode, prefix_len) = resolve_path(path)
# Delegate internal open
let sub_path = cast[cstring](cast[uint64](path) + uint64(prefix_len))
var internal_fd: int32 = -1
case mode:
of MODE_TAR, MODE_RAM: internal_fd = tar.vfs_open(sub_path, flags)
of MODE_SFS: internal_fd = 0 # Shim
of MODE_TTY: internal_fd = 1 # Shim
if internal_fd >= 0:
for i in 0..<MAX_FDS:
if not fd_table[i].active:
fd_table[i].active = true
fd_table[i].mode = mode
fd_table[i].offset = 0
let p = cast[ptr UncheckedArray[char]](sub_path)
var j = 0
while p[j] != '\0' and j < 63:
fd_table[i].path[j] = p[j]
j += 1
fd_table[i].path[j] = '\0'
return int32(i + 3) # FDs start at 3
return -1
proc ion_vfs_read*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
let idx = int(fd - 3)
if idx < 0 or idx >= MAX_FDS or not fd_table[idx].active: return -1
let fh = addr fd_table[idx]
case fh.mode:
of MODE_TTY: return -2
of MODE_TAR, MODE_RAM:
let path = cast[cstring](addr fh.path[0])
let n = tar.vfs_read_at(path, buf, count, fh.offset)
if n > 0: fh.offset += uint64(n)
return n
of MODE_SFS:
let path = cast[cstring](addr fh.path[0])
var temp: array[256, byte] # Small shim
let n = sfs.sfs_read_file(path, addr temp[0], 256)
if n <= 0: return -1
let avail = uint64(n) - fh.offset
let actual = if count < avail: count else: avail
if actual > 0:
copyMem(buf, addr temp[int(fh.offset)], int(actual))
fh.offset += actual
return int64(actual)
return 0
proc ion_vfs_write*(fd: int32, buf: pointer, count: uint64): int64 {.exportc, cdecl.} =
let idx = int(fd - 3)
if idx < 0 or idx >= MAX_FDS or not fd_table[idx].active: return -1
let fh = addr fd_table[idx]
case fh.mode:
of MODE_TTY: return -2
of MODE_TAR, MODE_RAM:
let path = cast[cstring](addr fh.path[0])
let n = tar.vfs_write_at(path, buf, count, fh.offset)
if n > 0: fh.offset += uint64(n)
return n
of MODE_SFS:
let path = cast[cstring](addr fh.path[0])
sfs.sfs_write_file(path, buf, int(count))
return int64(count)
proc ion_vfs_close*(fd: int32): int32 {.exportc, cdecl.} =
let idx = int(fd - 3)
if idx >= 0 and idx < MAX_FDS:
fd_table[idx].active = false
return 0
return -1
proc ion_vfs_list*(buf: pointer, max_len: uint64): int64 {.exportc, cdecl.} =
# Hardcoded baseline for now to avoid string/os dependency
let msg = "/nexus\n/sysro\n/state\n"
let n = if uint64(msg.len) < max_len: uint64(msg.len) else: max_len
if n > 0: copyMem(buf, unsafeAddr msg[0], int(n))
return int64(n)