From 8d4347ce602d51e17c3113edf940ee4d0d78a938 Mon Sep 17 00:00:00 2001 From: Martin Czygan Date: Thu, 20 May 2021 11:38:47 +0200 Subject: add atomic file ops --- skate/atomic/file.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 skate/atomic/file.go (limited to 'skate/atomic') diff --git a/skate/atomic/file.go b/skate/atomic/file.go new file mode 100644 index 0000000..1b9bf25 --- /dev/null +++ b/skate/atomic/file.go @@ -0,0 +1,63 @@ +package atomic + +import ( + "io" + "io/ioutil" + "os" + "path" +) + +// WriteFileReader writes data from a reader atomically into filename. +func WriteFileReader(filename string, r io.Reader, perm os.FileMode) error { + dir, name := path.Split(filename) + f, err := ioutil.TempFile(dir, name) + if err != nil { + return err + } + _, err = io.Copy(f, r) + if err == nil { + err = f.Sync() + } + if closeErr := f.Close(); err == nil { + err = closeErr + } + if permErr := os.Chmod(f.Name(), perm); err == nil { + err = permErr + } + if err == nil { + err = os.Rename(f.Name(), filename) + } + // Any err should result in full cleanup. + if err != nil { + os.Remove(f.Name()) + } + return err +} + +// WriteFileAtomic writes the data to a temp file and atomically move if +// everything else succeeds. +func WriteFile(filename string, data []byte, perm os.FileMode) error { + dir, name := path.Split(filename) + f, err := ioutil.TempFile(dir, name) + if err != nil { + return err + } + _, err = f.Write(data) + if err == nil { + err = f.Sync() + } + if closeErr := f.Close(); err == nil { + err = closeErr + } + if permErr := os.Chmod(f.Name(), perm); err == nil { + err = permErr + } + if err == nil { + err = os.Rename(f.Name(), filename) + } + // Any err should result in full cleanup. + if err != nil { + os.Remove(f.Name()) + } + return err +} -- cgit v1.2.3