github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/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 return WriteAtomicWithPerms(path, contents, 0700) 15 } 16 17 func WriteAtomicWithPerms(path string, contents []byte, permissions os.FileMode) error { 18 19 uuid, err := uuid.GenerateUUID() 20 if err != nil { 21 return err 22 } 23 tempPath := fmt.Sprintf("%s-%s.tmp", path, uuid) 24 25 if err := os.MkdirAll(filepath.Dir(path), permissions); err != nil { 26 return err 27 } 28 fh, err := os.OpenFile(tempPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) 29 if err != nil { 30 return err 31 } 32 if _, err := fh.Write(contents); err != nil { 33 fh.Close() 34 os.Remove(tempPath) 35 return err 36 } 37 if err := fh.Sync(); err != nil { 38 fh.Close() 39 os.Remove(tempPath) 40 return err 41 } 42 if err := fh.Close(); err != nil { 43 os.Remove(tempPath) 44 return err 45 } 46 if err := os.Rename(tempPath, path); err != nil { 47 os.Remove(tempPath) 48 return err 49 } 50 return nil 51 }