github.com/lmb/consul@v1.4.1/lib/file/atomic.go (about) 1 package file 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 8 "github.com/hashicorp/go-uuid" 9 ) 10 11 // WriteAtomic writes the given contents to a temporary file in the same 12 // directory, does an fsync and then renames the file to its real path 13 func WriteAtomic(path string, contents []byte) error { 14 uuid, err := uuid.GenerateUUID() 15 if err != nil { 16 return err 17 } 18 tempPath := fmt.Sprintf("%s-%s.tmp", path, uuid) 19 20 if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { 21 return err 22 } 23 fh, err := os.OpenFile(tempPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) 24 if err != nil { 25 return err 26 } 27 if _, err := fh.Write(contents); err != nil { 28 fh.Close() 29 os.Remove(tempPath) 30 return err 31 } 32 if err := fh.Sync(); err != nil { 33 fh.Close() 34 os.Remove(tempPath) 35 return err 36 } 37 if err := fh.Close(); err != nil { 38 os.Remove(tempPath) 39 return err 40 } 41 if err := os.Rename(tempPath, path); err != nil { 42 os.Remove(tempPath) 43 return err 44 } 45 return nil 46 }