Files
Agent-System/internal/fsutil/atomic.go
T
weichenandCursor e3b72ad64b fix(cli): require positive live-dev identity and exclusive backups
Live apply now accepts only :5433/agent_system_dev plus a data/dev
host root, maps stored work dirs fail-closed, and reports unique
O_EXCL backups after a parent-directory fsync.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 02:30:11 +00:00

103 lines
2.4 KiB
Go

package fsutil
import (
"errors"
"fmt"
"os"
"path/filepath"
"syscall"
)
// dirSync is the directory durability hook; tests replace it.
var dirSync = syncDirImpl
// WriteFileAtomic writes data via temp file + Sync + rename so readers never see a partial file.
// After a successful rename the parent directory is opened and Sync'd.
func WriteFileAtomic(path string, data []byte, perm os.FileMode) error {
return writeFileAtomic(path, data, perm, false)
}
// WriteFileAtomicExclusive is WriteFileAtomic but creates the destination with O_EXCL.
func WriteFileAtomicExclusive(path string, data []byte, perm os.FileMode) error {
return writeFileAtomic(path, data, perm, true)
}
func writeFileAtomic(path string, data []byte, perm os.FileMode, exclusive bool) error {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
if exclusive {
f, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, perm)
if err != nil {
if os.IsExist(err) {
return fmt.Errorf("fsutil: refuse overwrite of existing %s", path)
}
return err
}
if cerr := f.Close(); cerr != nil {
return cerr
}
}
tmp, err := os.CreateTemp(dir, "."+filepath.Base(path)+".*.tmp")
if err != nil {
return err
}
tmpName := tmp.Name()
cleanup := true
defer func() {
if cleanup {
_ = os.Remove(tmpName)
}
}()
if _, err := tmp.Write(data); err != nil {
_ = tmp.Close()
return fmt.Errorf("atomic write: %w", err)
}
if err := tmp.Sync(); err != nil {
_ = tmp.Close()
return fmt.Errorf("atomic sync: %w", err)
}
if err := tmp.Close(); err != nil {
return err
}
if err := os.Chmod(tmpName, perm); err != nil {
return err
}
if err := os.Rename(tmpName, path); err != nil {
return err
}
cleanup = false
if err := dirSync(dir); err != nil {
if ignorableDirSync(err) {
return nil
}
return err
}
return nil
}
// SyncDir fsyncs a directory so create/rename/unlink entries become durable.
func SyncDir(dir string) error {
return dirSync(dir)
}
func syncDirImpl(dir string) error {
d, err := os.Open(dir)
if err != nil {
return fmt.Errorf("fsutil: open dir %s: %w", dir, err)
}
defer d.Close()
if err := d.Sync(); err != nil {
if ignorableDirSync(err) {
return nil
}
return fmt.Errorf("fsutil: sync dir %s: %w", dir, err)
}
return nil
}
func ignorableDirSync(err error) bool {
return errors.Is(err, syscall.EINVAL) || errors.Is(err, syscall.ENOTSUP) || errors.Is(err, syscall.ENOSYS)
}