package mining import ( "os" "path/filepath" ) // AtomicWriteFile("/home/alice/.config/lethean-desktop/miners/installed-miners.json", data, 0600) func AtomicWriteFile(filePath string, data []byte, perm os.FileMode) error { directoryPath := filepath.Dir(filePath) temporaryFile, err := os.CreateTemp(directoryPath, ".tmp-*") if err != nil { return ErrInternal("create temp file").WithCause(err) } temporaryFilePath := temporaryFile.Name() success := false defer func() { if !success { os.Remove(temporaryFilePath) } }() if _, err := temporaryFile.Write(data); err != nil { temporaryFile.Close() return ErrInternal("write temp file").WithCause(err) } if err := temporaryFile.Sync(); err != nil { temporaryFile.Close() return ErrInternal("sync temp file").WithCause(err) } if err := temporaryFile.Close(); err != nil { return ErrInternal("close temp file").WithCause(err) } if err := os.Chmod(temporaryFilePath, perm); err != nil { return ErrInternal("set file permissions").WithCause(err) } if err := os.Rename(temporaryFilePath, filePath); err != nil { return ErrInternal("rename temp file").WithCause(err) } success = true return nil }