Document every public function; fix a real gap the audit found

Cross-checked every function declared in include/packfs.h against
nm -D libpackfs.so.0 as the starting point for a full documentation
pass, per the request to document literally everything rather than
just the parts already covered.

That check found a genuine bug, not just a documentation gap:
backend_pack_new was declared in the public header and named in
CLAUDE.md's architecture map, but never implemented in src/pack.c —
any caller would fail at link time. Implemented it as a standalone,
read-only `pack` Backend (every mutating call returns VFS_ERR_PERM,
consistent with concept.md Section 2.1 listing `pack` as its own
backend kind distinct from the overlay), covered it with a new test
case, and verified it under -fsanitize=undefined per CLAUDE.md's
sanitizer rule.

Added a doc comment to every previously-undocumented function and
struct field in packfs.h and internal.h (vfs_open/read/write/close/
stat/readdir/mkdir/unlink/rename, every upper_* structural/content
function, pfs_dir_*, pfs_fnv1a64, PackIndexEntry/Pack fields). Updated
README and CLAUDE.md to mention backend_pack_new and to stop gesturing
at zip/tar as though import/export exists.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UqJpkdJ6Njnt1pw3CbghzB
This commit is contained in:
2026-09-14 05:54:52 +00:00
co-authored by Claude Sonnet 5
parent 72e3c900f2
commit 9fb5cf2d9a
6 changed files with 350 additions and 20 deletions
+74 -3
View File
@@ -47,27 +47,39 @@ typedef enum {
VFS_KIND_DIR = 1
} VfsEntryKind;
/* Result of vfs_stat. For a directory, `size` is always 0 (directories
* carry no byte content) and `mtime` is 0 for one that exists only
* implicitly via a child's path (Section 9.3) rather than an explicit
* directory-marker entry. */
typedef struct VfsStat {
pfs_usize size;
int64_t mtime; /* seconds since epoch */
VfsEntryKind kind;
} VfsStat;
/* One child of a directory, as populated by vfs_readdir. `name` is the
* final path component only (not the full path), NUL-terminated. */
typedef struct VfsDirEntry {
char name[256];
VfsEntryKind kind;
} VfsDirEntry;
/* Result of vfs_readdir: `count` entries at `entries`, owned by the
* caller until passed to vfs_dir_free. A freshly zeroed VfsDir
* (`{0}`/`memset`) is always safe to pass to vfs_dir_free even if
* vfs_readdir was never called on it or returned an error. */
typedef struct VfsDir {
VfsDirEntry *entries;
pfs_usize count;
} VfsDir;
/* Flags for vfs_open, bitwise-OR'd. VFS_O_RDONLY is 0, i.e. the absence
* of VFS_O_WRONLY/VFS_O_RDWR, matching POSIX's convention. */
#define VFS_O_RDONLY 0x00
#define VFS_O_WRONLY 0x01
#define VFS_O_RDWR 0x02
#define VFS_O_CREAT 0x04
#define VFS_O_TRUNC 0x08
#define VFS_O_CREAT 0x04 /* create the file if it does not already exist */
#define VFS_O_TRUNC 0x08 /* reset an existing file's content to empty */
/* --- VFS lifecycle -------------------------------------------------- */
@@ -87,7 +99,14 @@ Backend *backend_mem_new(void);
/* dir: capability-scoped host directory, containment per Section 6. */
Backend *backend_dir_new(const char *host_path, int *err);
/* pack: read-only image loaded and validated per Section 7. */
/*
* pack: a shipped tree in one file, read-only, loaded and validated per
* Section 7 (Section 2.1, 3.1). Every mutating operation on a Backend
* returned by this constructor (open with a write flag, mkdir, unlink,
* rename, sync) returns VFS_ERR_PERM rather than being silently absorbed.
* To make a pack writable, wrap it in an overlay via backend_overlay_new
* instead of mounting it directly.
*/
Backend *backend_pack_new(const char *pack_path, int *err);
/*
@@ -115,21 +134,73 @@ void backend_free(Backend *b);
* observed mid-change by a concurrent path resolution.
*/
/* Mounts `b` at `prefix` (longest-prefix match resolves overlapping
* mounts, Section 2.2). Returns VFS_ERR_INVAL if `prefix` fails
* virtual-namespace canonicalization (Section 6.1), VFS_ERR_EXIST if a
* mount already exists at exactly this prefix, else VFS_OK. */
int vfs_mount(Vfs *v, const char *prefix, Backend *b);
/* Detaches the backend mounted at exactly `prefix`. Returns
* VFS_ERR_NOMOUNT if nothing is mounted there. The detached Backend is
* not freed — call backend_free explicitly once no other thread can
* still be resolving a path through it. */
int vfs_unmount(Vfs *v, const char *prefix);
/* --- File operations -------------------------------------------------- */
/* Opens `path` per the resolved backend's semantics. VFS_O_CREAT creates
* a new file if none exists; VFS_O_TRUNC resets an existing file's
* content to empty. Returns NULL and sets *err on failure (e.g.
* VFS_ERR_NOENT if the path doesn't exist and VFS_O_CREAT wasn't given,
* VFS_ERR_ISDIR if the path names a directory, VFS_ERR_PERM if the
* backend or the specific path is read-only). */
VfsFile *vfs_open(Vfs *v, const char *path, int flags, int *err);
/* Reads up to `n` bytes from the file's current position into `buf`,
* advancing that position by the number of bytes actually read. Returns
* the byte count (0 at end of file), or a negative VfsStatus on error. */
pfs_isize vfs_read(VfsFile *f, void *buf, pfs_usize n);
/* Writes `n` bytes from `buf` at the file's current position, advancing
* that position by the number of bytes actually written; a write past
* the current end of the file extends it. Returns the byte count
* written, or a negative VfsStatus on error (e.g. VFS_ERR_PERM for a
* file opened read-only or served from a read-only backend). */
pfs_isize vfs_write(VfsFile *f, const void *buf, pfs_usize n);
/* Closes a file handle from vfs_open, releasing every resource it held.
* `f` must not be used again afterward. Always returns VFS_OK. */
int vfs_close(VfsFile *f);
/* Fills `out` with `path`'s size, kind, and mtime. Returns VFS_ERR_NOENT
* if nothing exists at that path in the resolved backend. */
int vfs_stat(Vfs *v, const char *path, VfsStat *out);
/* Lists the immediate children of the directory at `path` into `out`
* (caller-owned until passed to vfs_dir_free). Returns VFS_ERR_NOENT if
* `path` doesn't exist, VFS_ERR_NOTDIR if it names a file. */
int vfs_readdir(Vfs *v, const char *path, VfsDir *out);
/* Frees the entries array a prior vfs_readdir populated into `*d` and
* zeroes it; safe to call on an already-freed or zeroed VfsDir. */
void vfs_dir_free(VfsDir *d);
/* Creates an empty directory at `path` (Section 9.3: this writes an
* explicit, compaction-surviving marker, since an empty directory has no
* file beneath it to imply its existence). Returns VFS_ERR_EXIST if
* `path` already names something. */
int vfs_mkdir(Vfs *v, const char *path);
/* Removes the file or empty directory at `path`. Returns VFS_ERR_NOENT
* if nothing exists there, VFS_ERR_NOTEMPTY for a non-empty directory,
* VFS_ERR_PERM if the resolved backend is read-only. Against an overlay,
* removing a path that exists in the read-only lower pack writes a
* whiteout rather than failing (Section 4.2). */
int vfs_unlink(Vfs *v, const char *path);
/* Moves the entry at `from` to `to` within the same mount; both paths
* must resolve to the same backend (VFS_ERR_INVAL otherwise — v0 does
* not support a cross-mount rename). */
int vfs_rename(Vfs *v, const char *from, const char *to);
/*