atomicwrite.go

 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}