Documentation
¶
Overview ¶
Package fsatomic provides atomic file replacement and cross-process locking for state that multiple processes read, write, and clean up concurrently: delivery caches, user hook configs, server descriptors.
A plain os.WriteFile truncates in place, so a crash, a full disk, or a concurrent reader can observe a half-written file. All writes here go through a same-directory temp file + fsync + rename, so any reader observes either the previous or the new content, never a mix. Read-check- act sequences that content comparison cannot protect (publish vs ownership-checked cleanup, read-merge-write config updates) serialize via Lock's sidecar advisory lock instead.
Index ¶
- func ReplaceGuarded(path string, expected []byte, data []byte, perm os.FileMode) error
- func ResolvePath(path string) (string, error)
- func WriteFile(path string, data []byte, perm os.FileMode) error
- func WriteFilePrepared(path string, data []byte, perm os.FileMode, prepare func(string) error) error
- func WriteFilePreparedExact(path string, data []byte, perm os.FileMode, prepare func(string) error) error
- type Unlocker
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ReplaceGuarded ¶
ReplaceGuarded 在最终 rename 前再次比较当前内容。它与合作 writer 的 sidecar lock 配合;对不获取 lock 的宿主/编辑器,至少检测并拒绝已发生的 修改,而不是静默覆盖。expected=nil 表示读取时文件不存在。
func ResolvePath ¶
ResolvePath resolves a symlinked destination (and, for a not-yet-existing destination, its symlinked parent). Callers that lock before a read/merge/ write transaction must lock this resolved path, otherwise two aliases to the same target would use different sidecar locks.
func WriteFile ¶
WriteFile atomically replaces path with data. The temp file lives in the destination directory so the final rename never crosses filesystems. When the destination already exists its permission bits are preserved; otherwise perm applies.
A symlinked destination is resolved first and the TARGET is replaced: a plain rename would swap the symlink itself for a regular file, silently detaching dotfiles-managed configs from their repository (the pre-atomic os.WriteFile used to write through the link, so following it preserves that contract).
Types ¶
type Unlocker ¶
type Unlocker func()
Unlocker releases a cross-process lock acquired by Lock.
func Lock ¶
Lock acquires an exclusive, blocking, cross-process advisory lock on a sidecar file derived from path (path + ".lock"). It serializes writers AND cleaners of multi-process state files — the descriptor publish / ownership-check-remove sequence, and the hook-config read-merge-write cycle — whose read-check-act windows cannot be closed by content comparison alone.
The sidecar file is created if missing and intentionally never deleted: removing a lock file while another process holds or is about to open it reintroduces the very race the lock exists to prevent. The empty sidecar is a few bytes of permanent state next to the file it guards.