Parcourir la source

lib/osutil: Preserve perms in AtomicWriter (fixes #tbd) (#6885)

Simon Frei il y a 5 ans
Parent
commit
fd8bea6179
2 fichiers modifiés avec 18 ajouts et 1 suppressions
  1. 12 1
      lib/osutil/atomic.go
  2. 6 0
      lib/osutil/atomic_test.go

+ 12 - 1
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 {

+ 6 - 0
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())
+	}
 }