storj/private/fpath/atomic.go
Andrew Harding 2461ccd469 pkg/private/fpath: subsume AtomicWriteFile
AtomicWriteFile is useful primitive to use throughout the codebase

Change-Id: I338fc4505ba20d5aece09ddc257286f46298e083
2019-12-03 18:14:08 +00:00

43 lines
1018 B
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package fpath
import (
"io/ioutil"
"os"
"path/filepath"
"github.com/zeebo/errs"
)
// AtomicWriteFile is a helper to atomically write the data to the outfile.
func AtomicWriteFile(outfile string, data []byte, mode os.FileMode) (err error) {
// TODO: provide better atomicity guarantees, like fsyncing the parent
// directory and, on windows, using MoveFileEx with MOVEFILE_WRITE_THROUGH.
fh, err := ioutil.TempFile(filepath.Dir(outfile), filepath.Base(outfile))
if err != nil {
return errs.Wrap(err)
}
defer func() {
if err != nil {
err = errs.Combine(err, fh.Close())
err = errs.Combine(err, os.Remove(fh.Name()))
}
}()
if _, err := fh.Write(data); err != nil {
return errs.Wrap(err)
}
if err := fh.Sync(); err != nil {
return errs.Wrap(err)
}
if err := fh.Close(); err != nil {
return errs.Wrap(err)
}
if err := os.Rename(fh.Name(), outfile); err != nil {
return errs.Wrap(err)
}
return nil
}