package mining import ( "fmt" "os" "path/filepath" ) // AtomicWriteFile writes data to a file atomically by writing to a temp file // first, syncing to disk, then renaming to the target path. This prevents // corruption if the process is interrupted during write. func AtomicWriteFile(path string, data []byte, perm os.FileMode) error { dir := filepath.Dir(path) // Create temp file in the same directory for atomic rename tmpFile, err := os.CreateTemp(dir, ".tmp-*") if err != nil { return fmt.Errorf("failed to create temp file: %w", err) } tmpPath := tmpFile.Name() // Clean up temp file on error success := false defer func() { if !success { os.Remove(tmpPath) } }() if _, err := tmpFile.Write(data); err != nil { tmpFile.Close() return fmt.Errorf("failed to write temp file: %w", err) } // Sync to ensure data is flushed to disk before rename if err := tmpFile.Sync(); err != nil { tmpFile.Close() return fmt.Errorf("failed to sync temp file: %w", err) } if err := tmpFile.Close(); err != nil { return fmt.Errorf("failed to close temp file: %w", err) } // Set permissions before rename if err := os.Chmod(tmpPath, perm); err != nil { return fmt.Errorf("failed to set file permissions: %w", err) } // Atomic rename (on POSIX systems) if err := os.Rename(tmpPath, path); err != nil { return fmt.Errorf("failed to rename temp file: %w", err) } success = true return nil }