diff --git a/lib/osutil/atomic.go b/lib/osutil/atomic.go index d5f7b1217..ac374bd60 100644 --- a/lib/osutil/atomic.go +++ b/lib/osutil/atomic.go @@ -93,7 +93,12 @@ func (w *AtomicWriter) Close() error { return err } - err := w.fs.Rename(w.next.Name(), w.path) + info, err := w.fs.Lstat(w.path) + if err != nil && !fs.IsNotExist(err) { + w.err = err + return err + } + err = w.fs.Rename(w.next.Name(), w.path) if runtime.GOOS == "windows" && fs.IsPermission(err) { // On Windows, we might not be allowed to rename over the file // because it's read-only. Get us some write permissions and try @@ -105,6 +110,12 @@ func (w *AtomicWriter) Close() error { w.err = err return err } + if info != nil { + if err := w.fs.Chmod(w.path, info.Mode()); err != nil { + w.err = err + return err + } + } // fsync the directory too if fd, err := w.fs.Open(filepath.Dir(w.next.Name())); err == nil { diff --git a/lib/osutil/atomic_test.go b/lib/osutil/atomic_test.go index 3de74bff3..70c5b90d6 100644 --- a/lib/osutil/atomic_test.go +++ b/lib/osutil/atomic_test.go @@ -110,4 +110,10 @@ func testCreateAtomicReplace(t *testing.T, oldPerms os.FileMode) { if !bytes.Equal(bs, []byte("hello")) { t.Error("incorrect data") } + + if info, err := os.Stat(testfile); err != nil { + t.Fatal(err) + } else if info.Mode() != oldPerms { + t.Fatalf("Perms changed during atomic write: 0%o", info.Mode()) + } }