1package config
2
3import (
4 "os"
5 "path/filepath"
6)
7
8// atomicWriteFile writes data to a file atomically by writing to a unique
9// temporary file in the same directory and renaming it into place. This
10// prevents concurrent readers from observing a partially-written file.
11func atomicWriteFile(path string, data []byte, perm os.FileMode) error {
12 path = filepath.Clean(path)
13 dir := filepath.Dir(path)
14 f, err := os.CreateTemp(dir, filepath.Base(path)+".*.tmp")
15 if err != nil {
16 return err
17 }
18 tmp := f.Name()
19 if _, err := f.Write(data); err != nil {
20 f.Close()
21 os.Remove(tmp)
22 return err
23 }
24 if err := f.Chmod(perm); err != nil {
25 f.Close()
26 os.Remove(tmp)
27 return err
28 }
29 if err := f.Close(); err != nil {
30 os.Remove(tmp)
31 return err
32 }
33 if err := os.Rename(tmp, path); err != nil {
34 os.Remove(tmp)
35 return err
36 }
37 return nil
38}