ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
filesystem.h File Reference

The filesystem accessor: it owns the mount root, it owns the resolved path, and it is the only way a request reaches storage. More...

#include "numeros_scribo/numeros_scribo.h"
#include "server/storage/mnt/mnt.h"
#include "protocore_config.h"

Go to the source code of this file.

Classes

struct  FsPathArgs
 The file one call names: which mount, which directory, which entry. More...
 
struct  FsDestArgs
 The second path a rename or a copy needs. More...
 
struct  FsIoArgs
 The open file a call acts on, and the bytes it moves. More...
 
struct  FilesystemNs
 

Macros

#define PROTOCORE_FS_MAX_ROOTS   4
 Roots that can be bound at once (see protocore_fs_begin).
 
#define PROTOCORE_FS_ROOT_NAME_MAX   24
 Longest root name (e.g. "mnt/sftp"), including the terminator.
 
#define PROTOCORE_FS_MAX_DEPTH   8
 How deep protocore_fs_remove() / protocore_fs_copy() descend before refusing a tree.
 
#define PROTOCORE_FS_BLOCK   512
 The storage block this file aligns its transfers to.
 
#define PROTOCORE_FS_OK   0u
 
#define PROTOCORE_FS_STORAGE_EXHAUSTED   (1u << 0)
 nothing mounted, or the store could not take the write.
 
#define PROTOCORE_FS_BAD_ROOT   (1u << 1)
 the root handle was never bound (see protocore_fs_begin).
 
#define PROTOCORE_FS_TRAVERSAL   (1u << 2)
 the request path contained .. and was refused.
 
#define PROTOCORE_FS_TOO_LONG   (1u << 3)
 the resolved path did not fit.
 

Functions

PROTOCORE_INLINE size_t protocore_fs_join (const char *root, const char *dir, const char *name, char *out, size_t cap)
 Join a mount root, a request dir, and a leaf name into out.
 
PROTOCORE_INLINE proto_bool protocore_fs_has_dotdot (const char *s)
 Resolve a mount root + a request dir + a leaf name to an on-disk path in out: reject any .. traversal, join onto the root, and drop a trailing '/'.
 
PROTOCORE_INLINE int protocore_fs_resolve (const char *root, const char *dir, const char *name, char *out, size_t cap)
 
uint8_t * protocore_filesystem_span (void)
 The PROTOCORE_FILESYSTEM_BORROW bytes this module's state lives in.
 

Variables

FilesystemNs Fs
 The one symbol this module exports.
 

Detailed Description

The filesystem accessor: it owns the mount root, it owns the resolved path, and it is the only way a request reaches storage.

A wire protocol (SFTP, SCP, WebDAV) knows a request path - the bytes a client sent. It does not know where the mount lives, and it must not be able to escape it. So it never builds a path and never holds one: it hands the request path to an operation here, and this file joins it onto the root, rejects .., and dispatches to the mounted backend (mnt.h, alongside this file).

That is why the operations take a request path rather than returning one. An accessor that returned a resolved string would put a path buffer, its capacity, and its overflow check into every caller - which is exactly the duplication that had nine identical char disk[] arrays and two copies of the .. guard spread across the SFTP and SCP servers. There is one buffer here, and callers do not size it, see it, or carry it.

protocore_fs_path() is the single exception, for the one caller that genuinely needs the text: SFTP REALPATH answers with a path string. It hands back a pointer into this file's storage, or nullptr when it cannot - there is no out/capacity pair to get wrong.

The .. guard is a rejection, not realpath/symlink resolution: the on-flash filesystems (the small embedded ones) have no symlinks, so a ..-free joined path cannot leave the root.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file filesystem.h.

Macro Definition Documentation

◆ PROTOCORE_FS_MAX_ROOTS

#define PROTOCORE_FS_MAX_ROOTS   4

Roots that can be bound at once (see protocore_fs_begin).

One per service that wants its own storage - "mnt/scp", "mnt/sftp", a local region held for temp files - and more can be bound by raising this. Two services naming the same root share it and cost one entry.

Definition at line 58 of file filesystem.h.

◆ PROTOCORE_FS_ROOT_NAME_MAX

#define PROTOCORE_FS_ROOT_NAME_MAX   24

Longest root name (e.g. "mnt/sftp"), including the terminator.

Definition at line 63 of file filesystem.h.

◆ PROTOCORE_FS_MAX_DEPTH

#define PROTOCORE_FS_MAX_DEPTH   8

How deep protocore_fs_remove() / protocore_fs_copy() descend before refusing a tree.

The bound is what turns a tree walk into a fixed cost: one level of path storage per level, all of it in this file's context, and no call recursion - the walks are loops over that array, so the depth a request can force is the array's extent rather than however many stack frames it takes to exhaust RAM.

Definition at line 75 of file filesystem.h.

◆ PROTOCORE_FS_BLOCK

#define PROTOCORE_FS_BLOCK   512

The storage block this file aligns its transfers to.

Block alignment is ours, not the caller's and not the store's. Flash and SD both erase and program in blocks: a transfer that is not a whole block makes the store read the block, merge, and write it back, so an unaligned copy costs a read-modify-write per block and burns an erase cycle to move bytes that were already there. 512 is the SD sector and the common flash program page, so one block is one operation on both.

This is why protocore_fs_copy() moves a block at a time rather than "some convenient buffer size", and why the number lives here instead of at each call site - a caller cannot know what the mounted store erases in, and should not have to.

Definition at line 92 of file filesystem.h.

◆ PROTOCORE_FS_OK

#define PROTOCORE_FS_OK   0u

Definition at line 172 of file filesystem.h.

◆ PROTOCORE_FS_STORAGE_EXHAUSTED

#define PROTOCORE_FS_STORAGE_EXHAUSTED   (1u << 0)

nothing mounted, or the store could not take the write.

Definition at line 173 of file filesystem.h.

◆ PROTOCORE_FS_BAD_ROOT

#define PROTOCORE_FS_BAD_ROOT   (1u << 1)

the root handle was never bound (see protocore_fs_begin).

Definition at line 174 of file filesystem.h.

◆ PROTOCORE_FS_TRAVERSAL

#define PROTOCORE_FS_TRAVERSAL   (1u << 2)

the request path contained .. and was refused.

Definition at line 175 of file filesystem.h.

◆ PROTOCORE_FS_TOO_LONG

#define PROTOCORE_FS_TOO_LONG   (1u << 3)

the resolved path did not fit.

Definition at line 176 of file filesystem.h.

Function Documentation

◆ protocore_fs_join()

PROTOCORE_INLINE size_t protocore_fs_join ( const char *  root,
const char *  dir,
const char *  name,
char *  out,
size_t  cap 
)

Join a mount root, a request dir, and a leaf name into out.

Parameters
namethe leaf, or "" when dir is the whole path. When name is given, dir must end with '/' - that is what a directory destination means, and it is known at the call site rather than tested here.
Returns
bytes written, or 0 on overflow - the engine already knows the length, so it is handed back rather than left for the caller to rediscover with a scan.

Definition at line 102 of file filesystem.h.

Referenced by protocore_fs_resolve().

◆ protocore_fs_has_dotdot()

PROTOCORE_INLINE proto_bool protocore_fs_has_dotdot ( const char *  s)

Resolve a mount root + a request dir + a leaf name to an on-disk path in out: reject any .. traversal, join onto the root, and drop a trailing '/'.

Returns
0 on success, -1 on a traversal attempt (.. present), -2 if the joined path would overflow out.

True if s contains a .. traversal.

".." is two bytes at one offset, not a pattern to search for: compare the pair and advance.

Definition at line 121 of file filesystem.h.

References PROTO_FALSE, and PROTO_TRUE.

Referenced by protocore_fs_resolve().

◆ protocore_fs_resolve()

PROTOCORE_INLINE int protocore_fs_resolve ( const char *  root,
const char *  dir,
const char *  name,
char *  out,
size_t  cap 
)

Definition at line 133 of file filesystem.h.

References protocore_fs_has_dotdot(), and protocore_fs_join().

◆ protocore_filesystem_span()

uint8_t * protocore_filesystem_span ( void  )

The PROTOCORE_FILESYSTEM_BORROW bytes this module's state lives in.

Stated beside the namespace rather than on it: an entry takes a borrow, and this is where that borrow comes from. Taken once from the end of the pool, which no mark and no release walks, so the state lasts the life of the program.

Returns
the span.

Variable Documentation

◆ Fs

FilesystemNs Fs
extern

The one symbol this module exports.