...
1
16
17 package continuity
18
19 import (
20 "bytes"
21 "io"
22 "os"
23 "path/filepath"
24 )
25
26
27
28 func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error {
29 buf := bytes.NewBuffer(data)
30 return atomicWriteFile(filename, buf, int64(len(data)), perm)
31 }
32
33
34
35 func atomicWriteFile(filename string, r io.Reader, dataSize int64, perm os.FileMode) error {
36 f, err := os.CreateTemp(filepath.Dir(filename), ".tmp-"+filepath.Base(filename))
37 if err != nil {
38 return err
39 }
40 needClose := true
41 defer func() {
42 if needClose {
43 f.Close()
44 }
45 }()
46
47 err = os.Chmod(f.Name(), perm)
48 if err != nil {
49 return err
50 }
51 n, err := io.Copy(f, r)
52 if err == nil && n < dataSize {
53 return io.ErrShortWrite
54 }
55 if err != nil {
56 return err
57 }
58 if err = f.Sync(); err != nil {
59 return err
60 }
61
62 needClose = false
63 if err := f.Close(); err != nil {
64 return err
65 }
66
67 return os.Rename(f.Name(), filename)
68 }
69
View as plain text