|
ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
|
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. | |
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.
Definition in file filesystem.h.
| #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.
| #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.
| #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.
| #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.
| #define PROTOCORE_FS_OK 0u |
Definition at line 172 of file filesystem.h.
| #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.
| #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.
| #define PROTOCORE_FS_TRAVERSAL (1u << 2) |
the request path contained .. and was refused.
Definition at line 175 of file filesystem.h.
| #define PROTOCORE_FS_TOO_LONG (1u << 3) |
the resolved path did not fit.
Definition at line 176 of file filesystem.h.
| 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.
| name | the 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. |
Definition at line 102 of file filesystem.h.
Referenced by protocore_fs_resolve().
| 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 '/'.
.. 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_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().
| 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.
|
extern |
The one symbol this module exports.