fsatomic

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2026 License: MIT Imports: 7 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReplaceGuarded

func ReplaceGuarded(path string, expected []byte, data []byte, perm os.FileMode) error

ReplaceGuarded 在最终 rename 前再次比较当前内容。它与合作 writer 的 sidecar lock 配合;对不获取 lock 的宿主/编辑器,至少检测并拒绝已发生的 修改,而不是静默覆盖。expected=nil 表示读取时文件不存在。

func ResolvePath

func ResolvePath(path string) (string, error)

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

func WriteFile(path string, data []byte, perm os.FileMode) error

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).

func WriteFilePrepared

func WriteFilePrepared(path string, data []byte, perm os.FileMode, prepare func(string) error) error

WriteFilePrepared 与 WriteFile 相同,但在 temp 可见性提交前调用 prepare。 descriptor 用它先设置 Windows owner-only DACL,再 rename;这样不会出现 “宽继承 ACL 文件已发布、随后才收紧”的泄漏窗口。

func WriteFilePreparedExact

func WriteFilePreparedExact(path string, data []byte, perm os.FileMode, prepare func(string) error) error

WriteFilePreparedExact 不继承目标文件旧权限,专供含 secret 的状态文件。

Types

type Unlocker

type Unlocker func()

Unlocker releases a cross-process lock acquired by Lock.

func Lock

func Lock(path string) (Unlocker, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL