atomicfile

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Sep 11, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package atomicfile replaces a file's contents so that readers only ever observe the old file or the complete new one. It is the one writer behind every file Sentra rewrites in place — sentra.yaml and the AWS shared credentials file — so that the crash-safety and symlink rules those two files earned separately cannot drift apart again.

It is a leaf package on purpose: internal/config and internal/setup both need it and neither may import the other.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Write

func Write(path string, body []byte, perm os.FileMode) error

Write stages body in a temp file beside path, fsyncs it, and renames it over path, leaving the result at perm. A crash at any point leaves either the previous file or the new one, never a truncated or empty file. What a truncated file would cost is each caller's to say (see config.Write and setup.WriteAWSCredentialsProfile); this package only promises the old-or-new outcome.

The directory is deliberately not fsynced after the rename. A directory fsync would only shorten the window in which a power loss reverts the rename and leaves the PREVIOUS file in place — which is one of the two outcomes promised above, not a corruption. The file's own fsync is the one that matters: it is what keeps the new name from ever landing on zero-length content. Both callers re-read the file on the next launch, so a reverted rename shows up as "the setting did not stick", and the extra fsync of the directory would cost every settings toggle a disk flush to close that window.

Every failure leg removes the temp file — a stray `.<name>-*.tmp` beside the target would otherwise outlive the crash it was meant to protect against. The temp file lives in the target's directory because rename is atomic only within one filesystem. The directory must already exist: creating it is the caller's decision (config creates its own private one), and a typo'd path must not gain a directory.

A symlinked path is written through, not replaced. Operators keep the files this writes in a dotfiles repo behind a symlink (stow, chezmoi, `ln -s`), and renaming the temp file over the link would swap the link for a regular file, severing the dotfiles on every rewrite, which the plain os.WriteFile this replaced never did. So when path is a symlink it is resolved with EvalSymlinks and the resolved file is what gets staged beside and renamed over. A dangling link is an error rather than a fresh file: creating a regular file at the link's path is the same severing, and inventing the target's directory writes where nobody asked. A path that does not exist at all stays as given, so a fresh file lands exactly where the caller named it.

Types

This section is empty.

Jump to

Keyboard shortcuts

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