overwriteFileIfChanged checks that the contents of f == data, and overwrites f if they differ. It also ensures that f's permissions are set to perm.
(path string, data []byte, perm os.FileMode)
| 104 | // overwriteFileIfChanged checks that the contents of f == data, and overwrites |
| 105 | // f if they differ. It also ensures that f's permissions are set to perm. |
| 106 | func overwriteFileIfChanged(path string, data []byte, perm os.FileMode) (changed bool, err error) { |
| 107 | flag := os.O_RDWR | os.O_CREATE |
| 108 | file, err := os.OpenFile(path, flag, perm) |
| 109 | if errors.Is(err, os.ErrNotExist) { |
| 110 | if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { |
| 111 | return false, err |
| 112 | } |
| 113 | |
| 114 | // Definitely a new file if we had to make the directory. |
| 115 | return true, os.WriteFile(path, data, perm) |
| 116 | } |
| 117 | if err != nil { |
| 118 | return false, err |
| 119 | } |
| 120 | defer file.Close() |
| 121 | |
| 122 | fi, err := file.Stat() |
| 123 | if err != nil || fi.Mode().Perm() != perm { |
| 124 | if err := file.Chmod(perm); err != nil { |
| 125 | return false, err |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | // Fast path - check if the lengths differ. |
| 130 | if err == nil && fi.Size() != int64(len(data)) { |
| 131 | return true, overwriteFile(file, data, 0) |
| 132 | } |
| 133 | |
| 134 | r := bufio.NewReader(file) |
| 135 | for offset := range data { |
| 136 | b, err := r.ReadByte() |
| 137 | if err != nil || b != data[offset] { |
| 138 | return true, overwriteFile(file, data, offset) |
| 139 | } |
| 140 | } |
| 141 | return false, nil |
| 142 | } |
| 143 | |
| 144 | // overwriteFile truncates f to len(data) and writes data[offset:] beginning at |
| 145 | // the same offset in f. |
no test coverage detected