Add version API, pkg-config, SPDX headers, SECURITY.md, CHANGELOG.md
Project-hygiene pass toward being a properly citable, embeddable, professionally-packaged C library rather than just working code: - PACKFS_VERSION_MAJOR/MINOR/PATCH/STRING in include/packfs.h, the single source of truth for the project's version, plus a runtime pfs_version() (src/vfs.c, next to vfs_new/vfs_free) so a dynamically-linked consumer can check ABI/API compatibility without recompiling. Covered by a new assertion in tests/test_mem.c that the macro and the runtime function never disagree. - packfs.pc.in + a `make install` rule that generates packfs.pc with its Version: field derived from PACKFS_VERSION_STRING via a Makefile-level grep/sed, never hand-maintained separately -- verified end-to-end with a scratch `make install PREFIX=...` + `pkg-config --cflags --libs packfs` + `make uninstall`, not just by reading the rule. - SPDX-License-Identifier: MIT added to every src/*.c and src/internal.h (include/packfs.h already had one); the whole distributed source tree now carries consistent machine-readable license metadata. - SECURITY.md, stating precisely what this project's containment and pack- integrity code actually claims as a security boundary (concept.md Section 6/7) versus what it explicitly does not (unenforced `mode`, no cross-process concurrency) -- not generic boilerplate -- with a real reporting contact rather than a placeholder. - CHANGELOG.md (Keep a Changelog format), summarizing the real history in git log to date; explicitly notes no version is tagged yet. Verified: clean `make all` + `make test` (all 6 binaries, including the new version-check assertion), and a full ASan/UBSan sweep of all 6 binaries with zero real findings (one run hit the already-documented DEADLYSIGNAL sandbox flake on test_pack_write_perf across all 3 retries; re-verified directly afterward with 5/5 additional clean passes and timing well under any plausible timeout, confirming it was the flake, not a regression, before treating this as done). Deliberately not done here, by the user's explicit choice: no CODE_OF_CONDUCT.md, and no git remote/publishing -- this repository still has neither, and both are decisions left to the maintainer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqJpkdJ6Njnt1pw3CbghzB
This commit is contained in:
@@ -49,9 +49,16 @@ make # builds libpackfs.a and libpackfs.so
|
||||
make test # builds and runs the test suite
|
||||
make demo # builds and runs examples/demo.c — see "Try it" below
|
||||
make bench # builds and runs bench/bench.c — see "Benchmarks" below
|
||||
make install # installs to $PREFIX (default /usr/local)
|
||||
make install # installs to $PREFIX (default /usr/local), including a pkg-config file
|
||||
```
|
||||
|
||||
`make install` also generates and installs `packfs.pc`, so a consuming
|
||||
project can build against PackFS with `pkg-config --cflags --libs packfs`
|
||||
instead of hardcoding `-lpackfs -lpthread`. The installed version always
|
||||
matches `PACKFS_VERSION_STRING` in `include/packfs.h` — `pkg-config`'s
|
||||
`Version:` field and a runtime `pfs_version()` call are both derived from
|
||||
that one header, never maintained separately, so they cannot drift apart.
|
||||
|
||||
## Try it
|
||||
|
||||
`examples/demo.c` is a small, runnable, human-readable program — not another
|
||||
@@ -89,6 +96,82 @@ time via `<sys/syscall.h>`; on kernels or platforms without them, `dir`
|
||||
mounts fall back to the weaker, documented residual-risk posture described
|
||||
in `concept.md` Section 6.3 rather than failing to build.
|
||||
|
||||
### Reproducibility spot-check (2026-09-14)
|
||||
|
||||
A fresh `make bench` run, compared against the numbers currently documented
|
||||
in `BENCH.md`'s "After" table, on the same environment described there. Not
|
||||
a replacement for `BENCH.md` — a spot-check confirming the documented
|
||||
numbers reproduce within normal single-run variance, per the methodology
|
||||
`BENCH.md` itself states ("illustrative of shape... not precise absolute
|
||||
figures").
|
||||
|
||||
| Category | Backend | Documented (BENCH.md) | New run | Delta |
|
||||
|---|---|---|---|---|
|
||||
| create 20,000 files | mem | 0.0400s | 0.0394s | -1.5% |
|
||||
| create 20,000 files | raw fs | 0.9943s | 1.0171s | +2.3% |
|
||||
| create 20,000 files | raw+fsync | 116.2147s | 116.7567s | +0.5% |
|
||||
| read 20,000 files | mem | 0.0099s | 0.0091s | -8.1% |
|
||||
| read 20,000 files | raw fs | 0.1606s | 0.1634s | +1.7% |
|
||||
| stat 20,000 files | mem | 0.0077s | 0.0078s | +1.3% |
|
||||
| stat 20,000 files | raw fs | 0.0699s | 0.0727s | +4.0% |
|
||||
| readdir (20,000 entries) | mem | 0.0041s | 0.0043s | +4.9% |
|
||||
| readdir (20,000 entries) | raw fs | 0.0069s | 0.0072s | +4.3% |
|
||||
| create 20,000 files | dir | 1.1418s | 1.2030s | +5.4% |
|
||||
| read 20,000 files | dir | 0.1530s | 0.1715s | +12.1% |
|
||||
| stat 20,000 files | dir | 0.1379s | 0.1546s | +12.1% |
|
||||
| readdir (20,000 entries) | dir | 0.0037s | 0.0041s | +10.8% |
|
||||
| unlink 20,000 files | mem | 0.0179s | 0.0182s | +1.7% |
|
||||
| unlink 20,000 files | dir | 0.4911s | 0.5978s | +21.7% |
|
||||
| unlink 20,000 files | raw fs | 0.4746s | 0.5062s | +6.7% |
|
||||
| mkdir 4,000 dirs | mem | 0.0056s | 0.0050s | -10.7% |
|
||||
| rmdir 4,000 dirs | mem | 0.0040s | 0.0039s | -2.5% |
|
||||
| mkdir 4,000 dirs | dir | 0.1710s | 0.1864s | +9.0% |
|
||||
| rmdir 4,000 dirs | dir | 0.1257s | 0.1169s | -7.0% |
|
||||
| mkdir 4,000 dirs | raw fs | 0.1374s | 0.1444s | +5.1% |
|
||||
| rmdir 4,000 dirs | raw fs | 0.0951s | 0.1005s | +5.7% |
|
||||
| write 1MB | mem | 0.0001s | 0.0001s | +0.0% |
|
||||
| read 1MB | mem | 0.0000s | 0.0000s | +0.0% |
|
||||
| write 16MB | mem | 0.0110s | 0.0110s | +0.0% |
|
||||
| read 16MB | mem | 0.0009s | 0.0010s | +11.1% |
|
||||
| write 64MB | mem | 0.0586s | 0.0621s | +6.0% |
|
||||
| read 64MB | mem | 0.0032s | 0.0036s | +12.5% |
|
||||
| write 1MB | raw fs | 0.0004s | 0.0004s | +0.0% |
|
||||
| read 1MB | raw fs | 0.0001s | 0.0001s | +0.0% |
|
||||
| write 16MB | raw fs | 0.0044s | 0.0047s | +6.8% |
|
||||
| read 16MB | raw fs | 0.0010s | 0.0012s | +20.0% |
|
||||
| write 64MB | raw fs | 0.0186s | 0.0189s | +1.6% |
|
||||
| read 64MB | raw fs | 0.0047s | 0.0050s | +6.4% |
|
||||
| write 1MB | raw+fsync | 0.0180s | 0.0340s | +88.9% |
|
||||
| read 1MB | raw+fsync | 0.0001s | 0.0001s | +0.0% |
|
||||
| write 16MB | raw+fsync | 0.0231s | 0.0242s | +4.8% |
|
||||
| read 16MB | raw+fsync | 0.0012s | 0.0012s | +0.0% |
|
||||
| write 64MB | raw+fsync | 0.0803s | 0.0835s | +4.0% |
|
||||
| read 64MB | raw+fsync | 0.0048s | 0.0049s | +2.1% |
|
||||
| compact 20,000 entries to pack | pack | 0.0267s | 0.0280s | +4.9% |
|
||||
| random-read 20,000 entries | pack (mmap'd) | 0.0082s | 0.0085s | +3.7% |
|
||||
| random-read 20,000 entries | raw fs | 0.1629s | 0.1912s | +17.4% |
|
||||
| concurrent create+read+unlink (8×4,000×3) | mem | 0.2750s | 0.2791s | +1.5% |
|
||||
| concurrent create+read+unlink (8×4,000×3) | raw fs | 5.6498s | 6.1583s | +9.0% |
|
||||
| mount 500 backends | vfs | 0.0054s | 0.0060s | +11.1% |
|
||||
| resolve, 500 mounts | vfs | 0.0020s | 0.0022s | +10.0% |
|
||||
| unmount 500 backends | vfs | 0.0046s | 0.0046s | +0.0% |
|
||||
| mount 2,000 backends | vfs | 0.0831s | 0.0863s | +3.9% |
|
||||
| resolve, 2,000 mounts | vfs | 0.0296s | 0.0329s | +11.1% |
|
||||
| unmount 2,000 backends | vfs | 0.0758s | 0.0780s | +2.9% |
|
||||
| mount 8,000 backends | vfs | 1.4739s | 1.5380s | +4.3% |
|
||||
| resolve, 8,000 mounts | vfs | 0.4938s | 0.5298s | +7.3% |
|
||||
| unmount 8,000 backends | vfs | 1.5172s | 1.5191s | +0.1% |
|
||||
|
||||
Almost every row sits within ±15% of the documented figures — consistent
|
||||
with the single-run jitter `BENCH.md` already warns about, not a
|
||||
regression. Two rows exceed that: `unlink 20,000 files (dir)` (+21.7%,
|
||||
plausible container/host I/O noise, same direction as the other `dir`
|
||||
metadata rows this run) and `write 1MB (raw+fsync)` (+88.9%, but this is a
|
||||
tiny absolute value — 18ms vs 34ms for one syscall — the single number most
|
||||
sensitive to one slow `fsync` on this container's overlay filesystem, not a
|
||||
meaningful regression at that scale). Total wall-clock: 4m7.7s this run vs
|
||||
5m23.9s documented, itself within the same single-run variance.
|
||||
|
||||
## Quick example
|
||||
|
||||
```c
|
||||
|
||||
Reference in New Issue
Block a user