Skip to content

Commit a71d099

Browse files
authored
Merge pull request #62 from brianneville/atomic-plugin-write
containerz/server: atomically write plugin file
2 parents 4eb750f + f9b3099 commit a71d099

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

server/deploy.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ func diskSpace(loc string) (uint64, error) {
200200
// moveFile moves a file by copying it and deleting the source. This is needed because os.Rename
201201
// only works within one device (i.e. mountpoint). The replication server's temp location and
202202
// actual location may be on different devices.
203+
// To ensure that the completed file is created atomically, the copy is done to a temp location
204+
// within the destination directory, and then the file is renamed within that destination directory.
203205
func moveFile(sourcePath, destPath string) error {
204206
// idempotent create of the destPath directory
205207
if err := os.MkdirAll(filepath.Dir(destPath), 0755); err != nil {
@@ -210,16 +212,19 @@ func moveFile(sourcePath, destPath string) error {
210212
if err != nil {
211213
return fmt.Errorf("unable to open source file: %s", err)
212214
}
213-
outputFile, err := os.Create(destPath)
215+
outputTmp, err := os.CreateTemp(filepath.Dir(destPath), "tmp-")
214216
if err != nil {
215217
inputFile.Close()
216-
return fmt.Errorf("unable to open dest file: %s", err)
218+
return fmt.Errorf("unable to create a temp file with error %s", err)
217219
}
218-
defer outputFile.Close()
219-
_, err = io.Copy(outputFile, inputFile)
220+
_, err = io.Copy(outputTmp, inputFile)
220221
inputFile.Close()
221222
if err != nil {
222-
return fmt.Errorf("writing to output file failed: %s", err)
223+
return fmt.Errorf("writing to temp output file failed: %s", err)
224+
}
225+
if err := os.Rename(outputTmp.Name(), destPath); err != nil {
226+
return fmt.Errorf("failed renaming temp file %s to output file %s with error %s",
227+
outputTmp.Name(), destPath, err)
223228
}
224229
// Success, now delete the original file.
225230
err = os.Remove(sourcePath)

0 commit comments

Comments
 (0)