diff --git a/atomicfile/atomicfile.go b/atomicfile/atomicfile.go index f2af37182..ec3025340 100644 --- a/atomicfile/atomicfile.go +++ b/atomicfile/atomicfile.go @@ -9,20 +9,36 @@ package atomicfile // import "tailscale.com/atomicfile" import ( - "fmt" "io/ioutil" "os" + "path/filepath" ) // WriteFile writes data to filename+some suffix, then renames it // into filename. -func WriteFile(filename string, data []byte, perm os.FileMode) error { - tmpname := filename + ".new.tmp" - if err := ioutil.WriteFile(tmpname, data, perm); err != nil { - return fmt.Errorf("%#v: %v", tmpname, err) +func WriteFile(filename string, data []byte, perm os.FileMode) (err error) { + f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".tmp") + if err != nil { + return err } - if err := os.Rename(tmpname, filename); err != nil { - return fmt.Errorf("%#v->%#v: %v", tmpname, filename, err) + tmpName := f.Name() + defer func() { + if err != nil { + f.Close() + os.Remove(tmpName) + } + }() + if _, err := f.Write(data); err != nil { + return err } - return nil + if err := f.Chmod(perm); err != nil { + return err + } + if err := f.Sync(); err != nil { + return err + } + if err := f.Close(); err != nil { + return err + } + return os.Rename(tmpName, filename) }