mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
To avoid user and automation confusion, prefix the temporary files with a ".". That way, if something scans the directory for files, it's less likely to encounter one of our temporary files. This will become very relevant in subsequent patches.
46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
// Package safeio implements convenient I/O routines that provide additional
|
|
// levels of safety in the presence of unexpected failures.
|
|
package safeio
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
)
|
|
|
|
// WriteFile writes data to a file named by filename, atomically.
|
|
// It's a wrapper to ioutil.WriteFile, but provides atomicity (and increased
|
|
// safety) by writing to a temporary file and renaming it at the end.
|
|
//
|
|
// Note this relies on same-directory Rename being atomic, which holds in most
|
|
// reasonably modern filesystems.
|
|
func WriteFile(filename string, data []byte, perm os.FileMode) error {
|
|
// Note we create the temporary file in the same directory, otherwise we
|
|
// would have no expectation of Rename being atomic.
|
|
// We make the file names start with "." so there's no confusion with the
|
|
// originals.
|
|
tmpf, err := ioutil.TempFile(path.Dir(filename), "."+path.Base(filename))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = os.Chmod(tmpf.Name(), perm); err != nil {
|
|
tmpf.Close()
|
|
os.Remove(tmpf.Name())
|
|
return err
|
|
}
|
|
|
|
if _, err = tmpf.Write(data); err != nil {
|
|
tmpf.Close()
|
|
os.Remove(tmpf.Name())
|
|
return err
|
|
}
|
|
|
|
if err = tmpf.Close(); err != nil {
|
|
os.Remove(tmpf.Name())
|
|
return err
|
|
}
|
|
|
|
return os.Rename(tmpf.Name(), filename)
|
|
}
|