diff --git a/CHANGELOG.md b/CHANGELOG.md index b97195ad..18c4a2e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fixed `wwctl upgrade nodes` to properly handle kernel argument lists. #1938 - Fixed a panic during `wwctl overlay edit` due to missing `reexec.Init()`. #1879 - Fixed handling of comma-separated mount options in `fstab` and `ignition` overlays. #1950 +- Fixed a race condition in `wwctl overlay edit`. #1947 ## v4.6.2, 2025-07-09 diff --git a/internal/app/wwctl/overlay/edit/main.go b/internal/app/wwctl/overlay/edit/main.go index 4100c191..9af87847 100644 --- a/internal/app/wwctl/overlay/edit/main.go +++ b/internal/app/wwctl/overlay/edit/main.go @@ -6,7 +6,6 @@ import ( "os" "path" "path/filepath" - "time" "github.com/spf13/cobra" "github.com/warewulf/warewulf/internal/pkg/overlay" @@ -71,11 +70,14 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { } tempFile.Close() - var startTime time.Time - if fileInfo, err := os.Stat(tempFile.Name()); err != nil { - return fmt.Errorf("unable to stat %s: %s", tempFile.Name(), err) - } else { - startTime = fileInfo.ModTime() + initialFile, err := os.Open(tempFile.Name()) + if err != nil { + return fmt.Errorf("unable to open temp file for hashing: %s", err) + } + initialHash, err := util.HashFile(initialFile) + initialFile.Close() + if err != nil { + return fmt.Errorf("unable to calculate initial hash of %s: %s", tempFile.Name(), err) } editor := os.Getenv("EDITOR") @@ -86,13 +88,19 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) { return fmt.Errorf("editor process exited with an error: %s", editorErr) } - if fileInfo, err := os.Stat(tempFile.Name()); err != nil { - return fmt.Errorf("unable to stat %s: %s", tempFile.Name(), err) - } else { - if startTime == fileInfo.ModTime() { - wwlog.Debug("No change detected. Not updating overlay.") - return nil - } + finalFile, err := os.Open(tempFile.Name()) + if err != nil { + return fmt.Errorf("unable to open temp file for final hashing: %s", err) + } + finalHash, err := util.HashFile(finalFile) + finalFile.Close() + if err != nil { + return fmt.Errorf("unable to calculate final hash of %s: %s", tempFile.Name(), err) + } + + if initialHash == finalHash { + wwlog.Debug("No change detected. Not updating overlay.") + return nil } if !overlay_.IsSiteOverlay() {