From 7f6b030b31298bc7df18fa3daa3d7502c6427000 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 6 Jul 2025 22:43:33 +0200 Subject: [PATCH] Use a .new temp file while gathering info, only move it into place on success --- src/ssh.go | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/ssh.go b/src/ssh.go index f0bfc80..d12f007 100644 --- a/src/ssh.go +++ b/src/ssh.go @@ -209,29 +209,34 @@ func (rb *RouterBackup) BackupCommands(commands []string, outputDir string) erro } filename := rb.hostname - filepath := filepath.Join(outputDir, filename) + finalPath := filepath.Join(outputDir, filename) + tempPath := finalPath + ".new" - // Truncate file at start - file, err := os.Create(filepath) + // Create temporary file + file, err := os.Create(tempPath) if err != nil { - return fmt.Errorf("failed to create file %s: %v", filepath, err) + return fmt.Errorf("failed to create temporary file %s: %v", tempPath, err) } file.Close() successCount := 0 + hasErrors := false + for i, command := range commands { fmt.Printf("Running command %d/%d: %s\n", i+1, len(commands), command) output, err := rb.RunCommand(command) if err != nil { fmt.Printf("Error executing '%s': %v\n", command, err) + hasErrors = true continue } - // Append to file - file, err := os.OpenFile(filepath, os.O_APPEND|os.O_WRONLY, 0644) + // Append to temporary file + file, err := os.OpenFile(tempPath, os.O_APPEND|os.O_WRONLY, 0644) if err != nil { fmt.Printf("Failed to open file for writing: %v\n", err) + hasErrors = true continue } @@ -243,9 +248,21 @@ func (rb *RouterBackup) BackupCommands(commands []string, outputDir string) erro } fmt.Printf("Summary: %d/%d commands successful\n", successCount, len(commands)) - if successCount > 0 { - fmt.Printf("Output saved to %s\n", filepath) + + if hasErrors || successCount == 0 { + // Remove .new suffix and log error + if err := os.Remove(tempPath); err != nil { + fmt.Printf("Failed to remove temporary file %s: %v\n", tempPath, err) + } + return fmt.Errorf("device backup incomplete due to command failures") } + + // All commands succeeded, move file into place atomically + if err := os.Rename(tempPath, finalPath); err != nil { + return fmt.Errorf("failed to move temporary file to final location: %v", err) + } + + fmt.Printf("Output saved to %s\n", finalPath) return nil }