mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-30 02:46:30 +02:00
58 lines
1 KiB
Go
58 lines
1 KiB
Go
package fileutil
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// WriteFileAtomically writes to a file path atomically. It does this by creating a temporary
|
|
// file in the same directory and then renaming it. If anything goes wrong the temporary
|
|
// file is deleted.
|
|
func WriteFileAtomically(filePath string, data []byte, mode os.FileMode) error {
|
|
f, err := os.CreateTemp(filepath.Dir(filePath), filepath.Base(filePath)+".tmp")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tmpPath := f.Name()
|
|
|
|
err = writeFileAndClose(f, data, mode)
|
|
if err != nil {
|
|
_ = os.Remove(tmpPath)
|
|
return err
|
|
}
|
|
|
|
err = os.Rename(tmpPath, filePath)
|
|
if err != nil {
|
|
_ = os.Remove(tmpPath)
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func writeFileAndClose(f *os.File, data []byte, mode os.FileMode) error {
|
|
_, err := f.Write(data)
|
|
if err != nil {
|
|
_ = f.Close()
|
|
return err
|
|
}
|
|
|
|
err = f.Sync()
|
|
if err != nil {
|
|
_ = f.Close()
|
|
return err
|
|
}
|
|
|
|
err = f.Chmod(mode)
|
|
if err != nil {
|
|
_ = f.Close()
|
|
return err
|
|
}
|
|
|
|
err = f.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|