From 992647b1572226d0c22e79fa24105cbfe45384b1 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 16 Nov 2017 10:55:24 +0000 Subject: [PATCH] vfs: Don't error a r/w file open without cache; delay error until Read called If we open a file for r/w without the cache we now always return a handle and return an error if the file is ever read from. This fixes incompatibility with cmount under windows. --- vfs/file.go | 8 ++++---- vfs/file_test.go | 4 +++- vfs/write.go | 14 ++++++++++++++ vfs/write_test.go | 9 +++++++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/vfs/file.go b/vfs/file.go index 827614656..728babbb0 100644 --- a/vfs/file.go +++ b/vfs/file.go @@ -382,11 +382,11 @@ func (f *File) Open(flags int) (fd Handle, err error) { if read && write { if CacheMode >= CacheModeMinimal { fd, err = f.OpenRW(flags) - } else if flags&os.O_TRUNC != 0 { - fd, err = f.OpenWrite() } else { - fs.Errorf(f, "Can't open for read and write without cache") - return nil, EPERM + // Open write only and hope the user doesn't + // want to read. If they do they will get an + // EPERM plus an Error log. + fd, err = f.OpenWrite() } } else if write { if CacheMode >= CacheModeWrites { diff --git a/vfs/file_test.go b/vfs/file_test.go index af3b29621..43c856583 100644 --- a/vfs/file_test.go +++ b/vfs/file_test.go @@ -172,7 +172,9 @@ func TestFileOpen(t *testing.T) { require.NoError(t, fd.Close()) fd, err = file.Open(os.O_RDWR) - assert.Equal(t, EPERM, err) + assert.NoError(t, err) + _, ok = fd.(*WriteFileHandle) + assert.True(t, ok) fd, err = file.Open(3) assert.Equal(t, EPERM, err) diff --git a/vfs/write.go b/vfs/write.go index 84f61fb07..b7de11ae2 100644 --- a/vfs/write.go +++ b/vfs/write.go @@ -248,3 +248,17 @@ func (fh *WriteFileHandle) Truncate(size int64) (err error) { // File is correct size return nil } + +// Read reads up to len(p) bytes into p. +func (fh *WriteFileHandle) Read(p []byte) (n int, err error) { + fs.Errorf(fh.remote, "Read: Can't read and write to file without cache") + return 0, EPERM +} + +// ReadAt reads len(p) bytes into p starting at offset off in the +// underlying input source. It returns the number of bytes read (0 <= +// n <= len(p)) and any error encountered. +func (fh *WriteFileHandle) ReadAt(p []byte, off int64) (n int, err error) { + fs.Errorf(fh.remote, "ReadAt: Can't read and write to file without cache") + return 0, EPERM +} diff --git a/vfs/write_test.go b/vfs/write_test.go index 56baa1251..daadeeea8 100644 --- a/vfs/write_test.go +++ b/vfs/write_test.go @@ -56,6 +56,15 @@ func TestWriteFileHandleMethods(t *testing.T) { assert.Equal(t, int64(5), fi.Size()) assert.Equal(t, "file1", fi.Name()) + // Read + var buf = make([]byte, 16) + _, err = fh.Read(buf) + assert.Equal(t, EPERM, err) + + // ReadAt + _, err = fh.ReadAt(buf, 0) + assert.Equal(t, EPERM, err) + // Close assert.NoError(t, fh.Close())