130 lines
4.5 KiB
Nim
130 lines
4.5 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: LittleFS Bridge
|
|
##
|
|
## Nim FFI wrapper for the Zig-side LittleFS HAL (littlefs_hal.zig).
|
|
## Provides the API that VFS delegates to for /nexus mount point.
|
|
##
|
|
## All calls cross the Nim→Zig→C boundary:
|
|
## Nim (this file) → Zig (littlefs_hal.zig) → C (lfs.c) → VirtIO-Block
|
|
|
|
# --- FFI imports from littlefs_hal.zig (exported as C ABI) ---
|
|
proc nexus_lfs_format(): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_mount(): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_unmount(): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_open(path: cstring, flags: int32): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_read(handle: int32, buf: pointer, size: uint32): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_write(handle: int32, buf: pointer, size: uint32): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_close(handle: int32): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_seek(handle: int32, off: int32, whence: int32): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_size(handle: int32): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_remove(path: cstring): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_mkdir(path: cstring): int32 {.importc, cdecl.}
|
|
proc nexus_lfs_is_mounted(): int32 {.importc, cdecl.}
|
|
|
|
# --- LFS open flags (match lfs.h) ---
|
|
const
|
|
LFS_O_RDONLY* = 1'i32
|
|
LFS_O_WRONLY* = 2'i32
|
|
LFS_O_RDWR* = 3'i32
|
|
LFS_O_CREAT* = 0x0100'i32
|
|
LFS_O_EXCL* = 0x0200'i32
|
|
LFS_O_TRUNC* = 0x0400'i32
|
|
LFS_O_APPEND* = 0x0800'i32
|
|
|
|
# --- LFS seek flags ---
|
|
const
|
|
LFS_SEEK_SET* = 0'i32
|
|
LFS_SEEK_CUR* = 1'i32
|
|
LFS_SEEK_END* = 2'i32
|
|
|
|
# --- Public API for VFS ---
|
|
|
|
proc lfs_mount_fs*(): bool =
|
|
## Mount the LittleFS filesystem. Auto-formats on first boot.
|
|
return nexus_lfs_mount() == 0
|
|
|
|
proc lfs_unmount_fs*(): bool =
|
|
return nexus_lfs_unmount() == 0
|
|
|
|
proc lfs_format_fs*(): bool =
|
|
return nexus_lfs_format() == 0
|
|
|
|
proc lfs_is_mounted*(): bool =
|
|
return nexus_lfs_is_mounted() != 0
|
|
|
|
proc lfs_open_file*(path: cstring, flags: int32): int32 =
|
|
## Open a file. Returns handle >= 0 on success, < 0 on error.
|
|
return nexus_lfs_open(path, flags)
|
|
|
|
proc lfs_read_file*(handle: int32, buf: pointer, size: uint32): int32 =
|
|
## Read from file. Returns bytes read or negative error.
|
|
return nexus_lfs_read(handle, buf, size)
|
|
|
|
proc lfs_write_file*(handle: int32, buf: pointer, size: uint32): int32 =
|
|
## Write to file. Returns bytes written or negative error.
|
|
return nexus_lfs_write(handle, buf, size)
|
|
|
|
proc lfs_close_file*(handle: int32): int32 =
|
|
return nexus_lfs_close(handle)
|
|
|
|
proc lfs_seek_file*(handle: int32, off: int32, whence: int32): int32 =
|
|
return nexus_lfs_seek(handle, off, whence)
|
|
|
|
proc lfs_file_size*(handle: int32): int32 =
|
|
return nexus_lfs_size(handle)
|
|
|
|
proc lfs_remove_path*(path: cstring): int32 =
|
|
return nexus_lfs_remove(path)
|
|
|
|
proc lfs_mkdir_path*(path: cstring): int32 =
|
|
return nexus_lfs_mkdir(path)
|
|
|
|
# --- Convenience: VFS-compatible read/write (path-based, like SFS) ---
|
|
|
|
proc lfs_vfs_read*(path: cstring, buf: pointer, max_len: int): int =
|
|
## Read entire file into buffer. Returns bytes read or -1.
|
|
let h = nexus_lfs_open(path, LFS_O_RDONLY)
|
|
if h < 0: return -1
|
|
let n = nexus_lfs_read(h, buf, uint32(max_len))
|
|
discard nexus_lfs_close(h)
|
|
if n < 0: return -1
|
|
return int(n)
|
|
|
|
proc lfs_vfs_write*(path: cstring, buf: pointer, len: int) =
|
|
## Write buffer to file (create/truncate).
|
|
let h = nexus_lfs_open(path, LFS_O_WRONLY or LFS_O_CREAT or LFS_O_TRUNC)
|
|
if h < 0: return
|
|
discard nexus_lfs_write(h, buf, uint32(len))
|
|
discard nexus_lfs_close(h)
|
|
|
|
proc lfs_vfs_read_at*(path: cstring, buf: pointer, count: uint64,
|
|
offset: uint64): int64 =
|
|
## Read `count` bytes starting at `offset`. Returns bytes read.
|
|
let h = nexus_lfs_open(path, LFS_O_RDONLY)
|
|
if h < 0: return -1
|
|
if offset > 0:
|
|
discard nexus_lfs_seek(h, int32(offset), LFS_SEEK_SET)
|
|
let n = nexus_lfs_read(h, buf, uint32(count))
|
|
discard nexus_lfs_close(h)
|
|
if n < 0: return -1
|
|
return int64(n)
|
|
|
|
proc lfs_vfs_write_at*(path: cstring, buf: pointer, count: uint64,
|
|
offset: uint64): int64 =
|
|
## Write `count` bytes at `offset`. Returns bytes written.
|
|
let flags = LFS_O_WRONLY or LFS_O_CREAT
|
|
let h = nexus_lfs_open(path, flags)
|
|
if h < 0: return -1
|
|
if offset > 0:
|
|
discard nexus_lfs_seek(h, int32(offset), LFS_SEEK_SET)
|
|
let n = nexus_lfs_write(h, buf, uint32(count))
|
|
discard nexus_lfs_close(h)
|
|
if n < 0: return -1
|
|
return int64(n)
|