Pārlūkot izejas kodu

Set permission on atomic file write

Perform chmod before rename with the atomic file writer.
Ensure writeErr is set on short write and file is removed on write error.

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
Derek McGowan 9 gadi atpakaļ
vecāks
revīzija
1cd7490281
2 mainītis faili ar 19 papildinājumiem un 4 dzēšanām
  1. 10 3
      pkg/ioutils/fswriters.go
  2. 9 1
      pkg/ioutils/fswriters_test.go

+ 10 - 3
pkg/ioutils/fswriters.go

@@ -15,13 +15,15 @@ func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, err
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
+
 	abspath, err := filepath.Abs(filename)
 	abspath, err := filepath.Abs(filename)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	return &atomicFileWriter{
 	return &atomicFileWriter{
-		f:  f,
-		fn: abspath,
+		f:    f,
+		fn:   abspath,
+		perm: perm,
 	}, nil
 	}, nil
 }
 }
 
 
@@ -34,6 +36,7 @@ func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error {
 	n, err := f.Write(data)
 	n, err := f.Write(data)
 	if err == nil && n < len(data) {
 	if err == nil && n < len(data) {
 		err = io.ErrShortWrite
 		err = io.ErrShortWrite
+		f.(*atomicFileWriter).writeErr = err
 	}
 	}
 	if err1 := f.Close(); err == nil {
 	if err1 := f.Close(); err == nil {
 		err = err1
 		err = err1
@@ -45,6 +48,7 @@ type atomicFileWriter struct {
 	f        *os.File
 	f        *os.File
 	fn       string
 	fn       string
 	writeErr error
 	writeErr error
+	perm     os.FileMode
 }
 }
 
 
 func (w *atomicFileWriter) Write(dt []byte) (int, error) {
 func (w *atomicFileWriter) Write(dt []byte) (int, error) {
@@ -57,7 +61,7 @@ func (w *atomicFileWriter) Write(dt []byte) (int, error) {
 
 
 func (w *atomicFileWriter) Close() (retErr error) {
 func (w *atomicFileWriter) Close() (retErr error) {
 	defer func() {
 	defer func() {
-		if retErr != nil {
+		if retErr != nil || w.writeErr != nil {
 			os.Remove(w.f.Name())
 			os.Remove(w.f.Name())
 		}
 		}
 	}()
 	}()
@@ -68,6 +72,9 @@ func (w *atomicFileWriter) Close() (retErr error) {
 	if err := w.f.Close(); err != nil {
 	if err := w.f.Close(); err != nil {
 		return err
 		return err
 	}
 	}
+	if err := os.Chmod(w.f.Name(), w.perm); err != nil {
+		return err
+	}
 	if w.writeErr == nil {
 	if w.writeErr == nil {
 		return os.Rename(w.f.Name(), w.fn)
 		return os.Rename(w.f.Name(), w.fn)
 	}
 	}

+ 9 - 1
pkg/ioutils/fswriters_test.go

@@ -16,7 +16,7 @@ func TestAtomicWriteToFile(t *testing.T) {
 	defer os.RemoveAll(tmpDir)
 	defer os.RemoveAll(tmpDir)
 
 
 	expected := []byte("barbaz")
 	expected := []byte("barbaz")
-	if err := AtomicWriteFile(filepath.Join(tmpDir, "foo"), expected, 0600); err != nil {
+	if err := AtomicWriteFile(filepath.Join(tmpDir, "foo"), expected, 0666); err != nil {
 		t.Fatalf("Error writing to file: %v", err)
 		t.Fatalf("Error writing to file: %v", err)
 	}
 	}
 
 
@@ -28,4 +28,12 @@ func TestAtomicWriteToFile(t *testing.T) {
 	if bytes.Compare(actual, expected) != 0 {
 	if bytes.Compare(actual, expected) != 0 {
 		t.Fatalf("Data mismatch, expected %q, got %q", expected, actual)
 		t.Fatalf("Data mismatch, expected %q, got %q", expected, actual)
 	}
 	}
+
+	st, err := os.Stat(filepath.Join(tmpDir, "foo"))
+	if err != nil {
+		t.Fatalf("Error statting file: %v", err)
+	}
+	if expected := os.FileMode(0666); st.Mode() != expected {
+		t.Fatalf("Mode mismatched, expected %o, got %o", expected, st.Mode())
+	}
 }
 }