aboutsummaryrefslogtreecommitdiff
path: root/src/io
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-10-21 16:12:22 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-10-22 10:09:39 +0000
commit16f0f9c8e1e767d10d483939981e3b2242554c33 (patch)
treebdc1f27274140687758c8e7ccd43a05162385d16 /src/io
parent7f98c0eb031d678687a3c07f5e1f11cac12d4171 (diff)
downloadgo-16f0f9c8e1e767d10d483939981e3b2242554c33.tar.gz
go-16f0f9c8e1e767d10d483939981e3b2242554c33.zip
syscall: respect permission bits on file opening on Windows
On Windows, os.Chmod and syscall.Chmod toggle the FILE_ATTRIBUTES_ READONLY flag depending on the permission bits. That's a bit odd but I guess some compromises were made at some point and this is what was chosen to map to a Unix concept that Windows doesn't really have in the same way. That's fine. However, the logic used in Chmod was forgotten from os.Open and syscall.Open, which then manifested itself in various places, most recently, go modules' read-only behavior. This makes syscall.Open consistent with syscall.Chmod and adds a test for the permission _behavior_ using ioutil. By testing the behavior instead of explicitly testing for the attribute bits we care about, we make sure this doesn't regress in unforeseen ways in the future, as well as ensuring the test works on platforms other than Windows. In the process, we fix some tests that never worked and relied on broken behavior, as well as tests that were disabled on Windows due to the broken behavior and had TODO notes. Fixes #35033 Change-Id: I6f7cf54517cbe5f6b1678d1c24f2ab337edcc7f7 Reviewed-on: https://go-review.googlesource.com/c/go/+/202439 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> Reviewed-by: Bryan C. Mills <bcmills@google.com> Reviewed-by: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/io')
-rw-r--r--src/io/ioutil/ioutil_test.go31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/io/ioutil/ioutil_test.go b/src/io/ioutil/ioutil_test.go
index c297847b4e..4945c65445 100644
--- a/src/io/ioutil/ioutil_test.go
+++ b/src/io/ioutil/ioutil_test.go
@@ -5,7 +5,9 @@
package ioutil
import (
+ "bytes"
"os"
+ "path/filepath"
"testing"
)
@@ -63,6 +65,35 @@ func TestWriteFile(t *testing.T) {
os.Remove(filename) // ignore error
}
+func TestReadOnlyWriteFile(t *testing.T) {
+ if os.Getuid() == 0 {
+ t.Skipf("Root can write to read-only files anyway, so skip the read-only test.")
+ }
+
+ // We don't want to use TempFile directly, since that opens a file for us as 0600.
+ tempDir, err := TempDir("", t.Name())
+ defer os.RemoveAll(tempDir)
+ filename := filepath.Join(tempDir, "blurp.txt")
+
+ shmorp := []byte("shmorp")
+ florp := []byte("florp")
+ err = WriteFile(filename, shmorp, 0444)
+ if err != nil {
+ t.Fatalf("WriteFile %s: %v", filename, err)
+ }
+ err = WriteFile(filename, florp, 0444)
+ if err == nil {
+ t.Fatalf("Expected an error when writing to read-only file %s", filename)
+ }
+ got, err := ReadFile(filename)
+ if err != nil {
+ t.Fatalf("ReadFile %s: %v", filename, err)
+ }
+ if !bytes.Equal(got, shmorp) {
+ t.Fatalf("want %s, got %s", shmorp, got)
+ }
+}
+
func TestReadDir(t *testing.T) {
dirname := "rumpelstilzchen"
_, err := ReadDir(dirname)