|
@@ -8,14 +8,20 @@
|
|
|
package atomicfile // import "tailscale.com/atomicfile"
|
|
package atomicfile // import "tailscale.com/atomicfile"
|
|
|
|
|
|
|
|
import (
|
|
import (
|
|
|
|
|
+ "fmt"
|
|
|
"os"
|
|
"os"
|
|
|
"path/filepath"
|
|
"path/filepath"
|
|
|
"runtime"
|
|
"runtime"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-// WriteFile writes data to filename+some suffix, then renames it
|
|
|
|
|
-// into filename. The perm argument is ignored on Windows.
|
|
|
|
|
|
|
+// WriteFile writes data to filename+some suffix, then renames it into filename.
|
|
|
|
|
+// The perm argument is ignored on Windows. If the target filename already
|
|
|
|
|
+// exists but is not a regular file, WriteFile returns an error.
|
|
|
func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
|
|
func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
|
|
|
|
|
+ fi, err := os.Stat(filename)
|
|
|
|
|
+ if err == nil && !fi.Mode().IsRegular() {
|
|
|
|
|
+ return fmt.Errorf("%s already exists and is not a regular file", filename)
|
|
|
|
|
+ }
|
|
|
f, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename)+".tmp")
|
|
f, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename)+".tmp")
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|