Documentation
¶
Overview ¶
Package publish is the descriptor-rooted bounded reader and transactional output publisher for CEM artifacts.
Every path is repository-root-relative and validated before any directory is created; ancestors are walked with no-follow checks so an output can never escape its root through a symlinked directory, an absolute path, or a dot-dot segment. Two-output publication is transactional: if the second output cannot land, the first's exact prior file is restored by atomic rename (or the fresh file removed when none existed) and no temporary or backup residue remains.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Publish ¶
Publish atomically writes one output with owner-only permissions, refusing a symlink as the final path.
func PublishPair ¶
PublishPair publishes two outputs transactionally: both land, or neither does. Both outputs are fully staged before either final path is touched, the first's prior file is set aside by atomic rename so a failed pair restores the exact prior inode, and a restoration failure is reported — never swallowed. The two targets must be distinct files. A crash after the prior file is set aside but before the first output lands leaves only the backup; callers holding the output's Lock repair that with RecoverPairBackup before treating the first output as missing.
func PublishSecure ¶
PublishSecure publishes through held directory descriptors. It rejects symlinks in every traversed component, locks the parent directory, syncs the file before promotion, and syncs the directory after the atomic rename.
func ReadBoundedFile ¶
ReadBoundedFile reads one absolute-path regular file with the same bounds. The opened descriptor's identity must match the pre-open metadata, so a path swapped for a symlink between the checks reads nothing else, and all bytes flow through a bound-plus-one limiter so growth after the size check can never allocate beyond the bound.
Types ¶
type Root ¶
type Root struct {
// contains filtered or unexported fields
}
Root is one validated publication root.
func (*Root) Lock ¶
Lock serializes one root-relative output's read-modify-write under an exclusive advisory lock on the sibling file "<output>.lock". A non-empty file at that path is refused, never adopted. The returned release removes the lock file before unlocking, but only while the path still names the held inode; a waiter that then acquires the unlinked inode sees it no longer names the path and retries. Expiry of the wait refuses with map-locked rather than risking a lost update.
func (*Root) ReadBounded ¶
ReadBounded reads one root-relative regular file without following a symlink at any component, rejecting content above bound bytes. An ancestor that is not a real directory is the caller's read refusal, not a publication one.
func (*Root) RecoverPairBackup ¶
RecoverPairBackup repairs the one crash window of PublishPair that loses the first output: its prior file was set aside as "<output>.bak-<hex>" and the process died before the new file landed. With the output missing, exactly one such backup is restored by atomic rename; several are refused because the intended prior file is ambiguous. A present output is left untouched. Callers must hold the output's Lock so an in-flight pair is never mistaken for an interrupted one.
func (*Root) RemoveValidatedPairBackup ¶
RemoveValidatedPairBackup removes the one recognized backup left when a pair publication crashed after its new first output landed. The caller must already have validated the present final output while holding its Lock. Multiple backups remain an ambiguous, fail-closed condition.