mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 23:02:16 +00:00
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
|
package common
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
)
|
||
|
|
||
|
// WriteFileAtomic creates a temporary file with data and the perm given and
|
||
|
// swaps it atomically with filename if successful.
|
||
|
func WriteFileAtomic(filename string, data []byte, perm os.FileMode) error {
|
||
|
var (
|
||
|
dir = filepath.Dir(filename)
|
||
|
// Create in case it doesn't exist and force kernel
|
||
|
// flush, which still leaves the potential of lingering disk cache.
|
||
|
// Never overwrites files
|
||
|
flag = os.O_WRONLY | os.O_CREATE | os.O_SYNC | os.O_TRUNC | os.O_EXCL
|
||
|
)
|
||
|
|
||
|
tempFile := filepath.Join(dir, "write-file-atomic-"+RandStr(32))
|
||
|
f, err := os.OpenFile(tempFile, flag, perm)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
// Clean up in any case. Defer stacking order is last-in-first-out.
|
||
|
defer os.Remove(f.Name())
|
||
|
defer f.Close()
|
||
|
|
||
|
if n, err := f.Write(data); err != nil {
|
||
|
return err
|
||
|
} else if n < len(data) {
|
||
|
return io.ErrShortWrite
|
||
|
}
|
||
|
// Close the file before renaming it, otherwise it will cause "The process
|
||
|
// cannot access the file because it is being used by another process." on windows.
|
||
|
f.Close()
|
||
|
|
||
|
return os.Rename(f.Name(), filename)
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------
|
||
|
|
||
|
func Tempfile(prefix string) (*os.File, string) {
|
||
|
file, err := ioutil.TempFile("", prefix)
|
||
|
if err != nil {
|
||
|
PanicCrisis(err)
|
||
|
}
|
||
|
return file, file.Name()
|
||
|
}
|
||
|
|
||
|
func Tempdir(prefix string) (*os.File, string) {
|
||
|
tempDir := os.TempDir() + "/" + prefix + RandStr(12)
|
||
|
err := EnsureDir(tempDir, 0700)
|
||
|
if err != nil {
|
||
|
panic(Fmt("Error creating temp dir: %v", err))
|
||
|
}
|
||
|
dir, err := os.Open(tempDir)
|
||
|
if err != nil {
|
||
|
panic(Fmt("Error opening temp dir: %v", err))
|
||
|
}
|
||
|
return dir, tempDir
|
||
|
}
|