pkg/private/fpath: subsume AtomicWriteFile
AtomicWriteFile is useful primitive to use throughout the codebase Change-Id: I338fc4505ba20d5aece09ddc257286f46298e083
This commit is contained in:
parent
4d2881b711
commit
2461ccd469
@ -6,9 +6,6 @@ package process
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
@ -18,6 +15,7 @@ import (
|
|||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"storj.io/storj/pkg/cfgstruct"
|
"storj.io/storj/pkg/cfgstruct"
|
||||||
|
"storj.io/storj/private/fpath"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SaveConfigOption is a function that updates the options for SaveConfig.
|
// SaveConfigOption is a function that updates the options for SaveConfig.
|
||||||
@ -201,7 +199,7 @@ func SaveConfig(cmd *cobra.Command, outfile string, opts ...SaveConfigOption) er
|
|||||||
lines = append(lines, nil)
|
lines = append(lines, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return errs.Wrap(atomicWrite(outfile, 0600, bytes.Join(lines, nl)))
|
return errs.Wrap(fpath.AtomicWriteFile(outfile, bytes.Join(lines, nl), 0600))
|
||||||
}
|
}
|
||||||
|
|
||||||
// readSourceAnnotation is a helper to return the source annotation or cfgstruct.AnySource if unset.
|
// readSourceAnnotation is a helper to return the source annotation or cfgstruct.AnySource if unset.
|
||||||
@ -218,30 +216,3 @@ func readBoolAnnotation(flag *pflag.Flag, key string) bool {
|
|||||||
annotation := flag.Annotations[key]
|
annotation := flag.Annotations[key]
|
||||||
return len(annotation) > 0 && annotation[0] == "true"
|
return len(annotation) > 0 && annotation[0] == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
// atomicWrite is a helper to atomically write the data to the outfile.
|
|
||||||
func atomicWrite(outfile string, mode os.FileMode, data []byte) (err error) {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
42
private/fpath/atomic.go
Normal file
42
private/fpath/atomic.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user