Skip to content

Commit

Permalink
Implement and test read only MemMapFs file handles
Browse files Browse the repository at this point in the history
Fixes spf13#53
  • Loading branch information
mbertschler committed Jan 4, 2016
1 parent 0236403 commit f0b9fc1
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 7 deletions.
7 changes: 4 additions & 3 deletions filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestFilterReadOnly(t *testing.T) {
if err == nil {
t.Errorf("Did not fail to create file")
}
t.Logf("ERR=%s", err)
// t.Logf("ERR=%s", err)
}

func TestFilterReadonlyRemoveAndRead(t *testing.T) {
Expand Down Expand Up @@ -59,9 +59,10 @@ func TestFilterRegexp(t *testing.T) {
fs.AddFilter(NewRegexpFilter(regexp.MustCompile(`\.txt$`)))
_, err := fs.Create("/file.html")
if err == nil {

t.Errorf("Did not fail to create file")
}
t.Logf("ERR=%s", err)
// t.Logf("ERR=%s", err)
}

func TestFilterRORegexpChain(t *testing.T) {
Expand All @@ -73,7 +74,7 @@ func TestFilterRORegexpChain(t *testing.T) {
if err == nil {
t.Errorf("Did not fail to create file")
}
t.Logf("ERR=%s", err)
// t.Logf("ERR=%s", err)
}

func TestFilterRegexReadDir(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions mem/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,18 @@ type File struct {
at int64
readDirCount int64
closed bool
readOnly bool
fileData *FileData
}

func NewFileHandle(data *FileData) *File {
return &File{fileData: data}
}

func NewReadOnlyFileHandle(data *FileData) *File {
return &File{fileData: data, readOnly: true}
}

func (f File) Data() *FileData {
return f.fileData
}
Expand Down Expand Up @@ -203,6 +208,9 @@ func (f *File) Seek(offset int64, whence int) (int64, error) {
}

func (f *File) Write(b []byte) (n int, err error) {
if f.readOnly {
return 0, &os.PathError{"write", f.fileData.name, errors.New("file handle is read only")}
}
n = len(b)
cur := atomic.LoadInt64(&f.at)
f.fileData.Lock()
Expand Down
23 changes: 21 additions & 2 deletions memmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,22 @@ func normalizePath(path string) string {
}

func (m *MemMapFs) Open(name string) (File, error) {
f, err := m.open(name)
if f != nil {
return mem.NewReadOnlyFileHandle(f), err
}
return nil, err
}

func (m *MemMapFs) openWrite(name string) (File, error) {
f, err := m.open(name)
if f != nil {
return mem.NewFileHandle(f), err
}
return nil, err
}

func (m *MemMapFs) open(name string) (*mem.FileData, error) {
name = normalizePath(name)

m.mu.RLock()
Expand All @@ -171,7 +187,7 @@ func (m *MemMapFs) Open(name string) (File, error) {
if !ok {
return nil, &os.PathError{"open", name, ErrFileNotFound}
}
return mem.NewFileHandle(f), nil
return f, nil
}

func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
Expand All @@ -185,13 +201,16 @@ func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
}

func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
file, err := m.Open(name)
file, err := m.openWrite(name)
if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
file, err = m.Create(name)
}
if err != nil {
return nil, err
}
if flag == os.O_RDONLY {
file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
}
if flag&os.O_APPEND > 0 {
_, err = file.Seek(0, os.SEEK_END)
if err != nil {
Expand Down
45 changes: 43 additions & 2 deletions memmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func checkPathError(t *testing.T, err error, op string) {
// Fails if multiple file objects use the same file.at counter in MemMapFs
func TestMultipleOpenFiles(t *testing.T) {
defer removeAllTestFiles(t)
const fileName = "./afero-demo2.txt"
const fileName = "afero-demo2.txt"

var data = make([][]byte, len(Fss))

Expand All @@ -113,7 +113,7 @@ func TestMultipleOpenFiles(t *testing.T) {
path := filepath.Join(dir, fileName)
fh1, err := fs.Create(path)
if err != nil {
t.Error("os.Create failed: " + err.Error())
t.Error("fs.Create failed: " + err.Error())
}
_, err = fh1.Write([]byte("test"))
if err != nil {
Expand Down Expand Up @@ -167,3 +167,44 @@ func TestMultipleOpenFiles(t *testing.T) {
}
}
}

// Test if file.Write() fails when opened as read only
func TestReadOnly(t *testing.T) {
defer removeAllTestFiles(t)
const fileName = "afero-demo.txt"

for _, fs := range Fss {
dir := testDir(fs)
path := filepath.Join(dir, fileName)

f, err := fs.Create(path)
if err != nil {
t.Error(fs.Name()+":", "fs.Create failed: "+err.Error())
}
_, err = f.Write([]byte("test"))
if err != nil {
t.Error(fs.Name()+":", "Write failed: "+err.Error())
}
f.Close()

f, err = fs.Open(path)
if err != nil {
t.Error("fs.Open failed: " + err.Error())
}
_, err = f.Write([]byte("data"))
if err == nil {
t.Error(fs.Name()+":", "No write error")
}
f.Close()

f, err = fs.OpenFile(path, os.O_RDONLY, 0644)
if err != nil {
t.Error("fs.Open failed: " + err.Error())
}
_, err = f.Write([]byte("data"))
if err == nil {
t.Error(fs.Name()+":", "No write error")
}
f.Close()
}
}

0 comments on commit f0b9fc1

Please sign in to comment.