safesight-edge/agent/internal/files/atomic.go
sladro 5f69321b40
Some checks are pending
CI / host-build (push) Waiting to run
CI / rk3588-cross-build (push) Waiting to run
准备测试agent服务能力
2026-01-10 09:27:13 +08:00

68 lines
1.4 KiB
Go

package files
import (
"fmt"
"os"
"path/filepath"
"runtime"
)
func EnsureDir(path string, perm os.FileMode) error {
if err := os.MkdirAll(path, perm); err != nil {
return fmt.Errorf("mkdir %s: %w", path, err)
}
return nil
}
func WriteFileAtomic(path string, data []byte, perm os.FileMode) error {
dir := filepath.Dir(path)
if err := EnsureDir(dir, 0o755); err != nil {
return err
}
f, err := os.CreateTemp(dir, ".tmp-*")
if err != nil {
return fmt.Errorf("create temp: %w", err)
}
tmp := f.Name()
ok := false
defer func() {
_ = f.Close()
if !ok {
_ = os.Remove(tmp)
}
}()
if _, err := f.Write(data); err != nil {
return fmt.Errorf("write temp: %w", err)
}
if err := f.Chmod(perm); err != nil {
return fmt.Errorf("chmod temp: %w", err)
}
if err := f.Sync(); err != nil {
return fmt.Errorf("fsync temp: %w", err)
}
if err := f.Close(); err != nil {
return fmt.Errorf("close temp: %w", err)
}
if err := ReplaceFile(tmp, path); err != nil {
return err
}
ok = true
return nil
}
func ReplaceFile(tmpPath, dstPath string) error {
if err := os.Rename(tmpPath, dstPath); err == nil {
return nil
} else if runtime.GOOS == "windows" {
_ = os.Remove(dstPath)
if err2 := os.Rename(tmpPath, dstPath); err2 != nil {
return fmt.Errorf("rename %s -> %s: %w", tmpPath, dstPath, err2)
}
return nil
} else {
return fmt.Errorf("rename %s -> %s: %w", tmpPath, dstPath, err)
}
}