diff options
author | Fabricio Voznika <fvoznika@google.com> | 2018-05-10 12:37:46 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-05-10 12:38:36 -0700 |
commit | 5a509c47a20e0b81b95bb4932e8b19dfc6a402e2 (patch) | |
tree | 6c7e78b4d2c2d888ed0f68a993107e8272b010d8 /runsc/fsgofer | |
parent | 2d3c6dc2efb1d9957836d70d1a59634b96ea74d4 (diff) |
Open file as read-write when mount points to a file
This is to allow files mapped directly, like /etc/hosts, to be writable.
Closes #40
PiperOrigin-RevId: 196155920
Change-Id: Id2027e421cef5f94a0951c3e18b398a77c285bbd
Diffstat (limited to 'runsc/fsgofer')
-rw-r--r-- | runsc/fsgofer/fsgofer.go | 12 | ||||
-rw-r--r-- | runsc/fsgofer/fsgofer_test.go | 50 |
2 files changed, 60 insertions, 2 deletions
diff --git a/runsc/fsgofer/fsgofer.go b/runsc/fsgofer/fsgofer.go index be2ac5f3c..11dd28cef 100644 --- a/runsc/fsgofer/fsgofer.go +++ b/runsc/fsgofer/fsgofer.go @@ -98,7 +98,17 @@ func (a *attachPoint) Attach(appPath string) (p9.File, error) { } root := filepath.Join(a.prefix, appPath) - f, err := os.OpenFile(root, openFlags|syscall.O_RDONLY, 0) + fi, err := os.Stat(root) + if err != nil { + return nil, err + } + + mode := syscall.O_RDWR + if a.conf.ROMount || fi.IsDir() { + mode = syscall.O_RDONLY + } + + f, err := os.OpenFile(root, mode|openFlags, 0) if err != nil { return nil, fmt.Errorf("unable to open file %q, err: %v", root, err) } diff --git a/runsc/fsgofer/fsgofer_test.go b/runsc/fsgofer/fsgofer_test.go index 58d04aefa..249f67bf9 100644 --- a/runsc/fsgofer/fsgofer_test.go +++ b/runsc/fsgofer/fsgofer_test.go @@ -18,6 +18,7 @@ import ( "fmt" "io/ioutil" "os" + "path" "syscall" "testing" @@ -102,7 +103,7 @@ func setup(ft fileType) (string, string, error) { return "", "", fmt.Errorf("ioutil.TempDir() failed, err: %v", err) } - // First attach with writable configuiration to setup tree. + // First attach with writable configuration to setup tree. a := NewAttachPoint(path, Config{}) root, err := a.Attach("/") if err != nil { @@ -574,3 +575,50 @@ func TestReaddir(t *testing.T) { } }) } + +// Test that attach point can be written to when it points to a file, e.g. +// /etc/hosts. +func TestAttachFile(t *testing.T) { + conf := Config{ROMount: false} + dir, err := ioutil.TempDir("", "root-") + if err != nil { + t.Fatalf("ioutil.TempDir() failed, err: %v", err) + } + defer os.RemoveAll(dir) + + path := path.Join(dir, "test") + if _, err := os.Create(path); err != nil { + t.Fatalf("os.Create(%q) failed, err: %v", path, err) + } + + a := NewAttachPoint(path, conf) + root, err := a.Attach("/") + if err != nil { + t.Fatalf("Attach(%q) failed, err: %v", "/", err) + } + + if _, _, _, err := root.Open(p9.ReadWrite); err != nil { + t.Fatalf("Open(ReadWrite) failed, err: %v", err) + } + defer root.Close() + + b := []byte("foobar") + w, err := root.WriteAt(b, 0) + if err != nil { + t.Fatalf("Write() failed, err: %v", err) + } + if w != len(b) { + t.Fatalf("Write() was partial, got: %d, expected: %d", w, len(b)) + } + rBuf := make([]byte, len(b)) + r, err := root.ReadAt(rBuf, 0) + if err != nil { + t.Fatalf("ReadAt() failed, err: %v", err) + } + if r != len(rBuf) { + t.Fatalf("ReadAt() was partial, got: %d, expected: %d", r, len(rBuf)) + } + if string(rBuf) != "foobar" { + t.Fatalf("ReadAt() wrong data, got: %s, expected: %s", string(rBuf), "foobar") + } +} |