Fix a race condition in wwctl overlay edit

Switches to using sha256 rather than mtime to detect changes to an
overlay file.

- Fixes: #1947

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
Jonathon Anderson
2025-08-01 01:56:24 -06:00
parent 69875c07c6
commit b3a6f3d905
2 changed files with 22 additions and 13 deletions

View File

@@ -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 `wwctl upgrade nodes` to properly handle kernel argument lists. #1938
- Fixed a panic during `wwctl overlay edit` due to missing `reexec.Init()`. #1879 - 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 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 ## v4.6.2, 2025-07-09

View File

@@ -6,7 +6,6 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/warewulf/warewulf/internal/pkg/overlay" "github.com/warewulf/warewulf/internal/pkg/overlay"
@@ -71,11 +70,14 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
} }
tempFile.Close() tempFile.Close()
var startTime time.Time initialFile, err := os.Open(tempFile.Name())
if fileInfo, err := os.Stat(tempFile.Name()); err != nil { if err != nil {
return fmt.Errorf("unable to stat %s: %s", tempFile.Name(), err) return fmt.Errorf("unable to open temp file for hashing: %s", err)
} else { }
startTime = fileInfo.ModTime() 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") 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) return fmt.Errorf("editor process exited with an error: %s", editorErr)
} }
if fileInfo, err := os.Stat(tempFile.Name()); err != nil { finalFile, err := os.Open(tempFile.Name())
return fmt.Errorf("unable to stat %s: %s", tempFile.Name(), err) if err != nil {
} else { return fmt.Errorf("unable to open temp file for final hashing: %s", err)
if startTime == fileInfo.ModTime() { }
wwlog.Debug("No change detected. Not updating overlay.") finalHash, err := util.HashFile(finalFile)
return nil 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() { if !overlay_.IsSiteOverlay() {