rumpk/core/fs/tar.nim

107 lines
3.0 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: ROMFS (Static Tar Loader)
##
## Freestanding implementation (No OS module dependencies).
## Uses a simple flat array for the file index.
{.push stackTrace: off, lineTrace: off.}
type
TarHeader* = array[512, byte]
FileEntry = object
name: array[64, char]
offset: uint64
size: uint64
active: bool
const MAX_INDEX = 64
var index_table: array[MAX_INDEX, FileEntry]
var index_count: int = 0
proc vfs_init*(s: pointer, e: pointer) =
let start_addr = cast[uint64](s)
let end_addr = cast[uint64](e)
index_count = 0
var p = start_addr
while p < end_addr:
let h = cast[ptr TarHeader](p)
if h[][0] == byte(0): break
# Extract name
var name_len = 0
while name_len < 100 and h[][name_len] != 0: inc name_len
var start_idx = 0
if name_len >= 2 and h[][0] == byte('.') and h[][1] == byte('/'): start_idx = 2
elif name_len >= 1 and h[][0] == byte('/'): start_idx = 1
let clean_len = name_len - start_idx
if clean_len > 0 and index_count < MAX_INDEX:
var entry = addr index_table[index_count]
entry.active = true
let to_copy = if clean_len < 63: clean_len else: 63
for i in 0..<to_copy:
entry.name[i] = char(h[][start_idx + i])
entry.name[to_copy] = '\0'
# Extract size (octal string at offset 124)
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'))
entry.size = size
entry.offset = p + 512
index_count += 1
# Move to next header
let padded_size = (size + 511) and not 511'u64
p += 512 + padded_size
else:
p += 512
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_open*(path: cstring, flags: int32 = 0): int32 =
var p = path
if path != nil and path[0] == '/':
p = cast[cstring](cast[uint64](path) + 1)
for i in 0..<index_count:
if vfs_streq(p, cast[cstring](addr index_table[i].name[0])):
return int32(i)
return -1
proc vfs_read_at*(path: cstring, buf: pointer, count: uint64, offset: uint64): int64 =
let fd = vfs_open(path)
if fd < 0: return -1
let entry = addr index_table[fd]
if offset >= entry.size: return 0
let avail = entry.size - offset
let actual = if count < avail: count else: avail
if actual > 0:
copyMem(buf, cast[pointer](entry.offset + offset), int(actual))
return int64(actual)
proc vfs_write_at*(path: cstring, buf: pointer, count: uint64, offset: uint64): int64 =
# ROMFS is read-only
return -1
proc vfs_get_names*(): int = index_count # Dummy for listing