diff --git a/go.mod b/go.mod index 74ba810..e9b5099 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.5.0 + github.com/natefinch/atomic v1.0.1 github.com/oklog/run v1.1.0 github.com/orcaman/concurrent-map/v2 v2.0.1 github.com/prometheus/client_golang v1.20.4 diff --git a/go.sum b/go.sum index 4caa486..8932446 100644 --- a/go.sum +++ b/go.sum @@ -96,6 +96,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= +github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c= diff --git a/internal/fans/file.go b/internal/fans/file.go index f85c25f..489b23f 100644 --- a/internal/fans/file.go +++ b/internal/fans/file.go @@ -106,7 +106,7 @@ func (fan *FileFan) SetPwm(pwm int) (err error) { filePath = filepath.Join(currentUser.HomeDir, filePath[1:]) } - err = util.WriteIntToFile(pwm, filePath) + err = util.WriteIntToFileAtomic(pwm, filePath) if err != nil { ui.Error("Unable to write to file: %v", fan.Config.File.Path) return err diff --git a/internal/util/file.go b/internal/util/file.go index f198483..a5ed68b 100644 --- a/internal/util/file.go +++ b/internal/util/file.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/markusressel/fan2go/internal/ui" + "github.com/natefinch/atomic" "os" "path/filepath" "regexp" @@ -64,15 +65,30 @@ func ReadIntFromFile(path string) (value int, err error) { // WriteIntToFile write a single integer to a file.go path func WriteIntToFile(value int, path string) error { - evaluatedPath, err := filepath.EvalSymlinks(path) + evaluatedPath, err := resolvePath(path) if len(evaluatedPath) > 0 && err == nil { path = evaluatedPath } valueAsString := fmt.Sprintf("%d", value) + err = os.WriteFile(path, []byte(valueAsString), 0644) return err } +func resolvePath(path string) (string, error) { + return filepath.EvalSymlinks(path) +} + +func WriteIntToFileAtomic(value int, path string) error { + evaluatedPath, err := resolvePath(path) + if len(evaluatedPath) > 0 && err == nil { + path = evaluatedPath + } + valueAsString := fmt.Sprintf("%d", value) + valueReader := strings.NewReader(valueAsString) + return atomic.WriteFile(path, valueReader) +} + // FindFilesMatching finds all files in a given directory, matching the given regex func FindFilesMatching(path string, expr *regexp.Regexp) []string { var result []string