Commit a3bb2189 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

fs: implement Write for MemRegularFile

Change-Id: Iac5c1a8329ceb0d8538029bd737cfede2af4d9a2
parent e9498b6b
...@@ -6,6 +6,7 @@ package fs ...@@ -6,6 +6,7 @@ package fs
import ( import (
"context" "context"
"sync"
"syscall" "syscall"
"github.com/hanwen/go-fuse/v2/fuse" "github.com/hanwen/go-fuse/v2/fuse"
...@@ -15,35 +16,65 @@ import ( ...@@ -15,35 +16,65 @@ import (
// slice in memory. // slice in memory.
type MemRegularFile struct { type MemRegularFile struct {
Inode Inode
mu sync.Mutex
Data []byte Data []byte
Attr fuse.Attr Attr fuse.Attr
} }
var _ = (NodeOpener)((*MemRegularFile)(nil)) var _ = (NodeOpener)((*MemRegularFile)(nil))
var _ = (NodeReader)((*MemRegularFile)(nil)) var _ = (NodeReader)((*MemRegularFile)(nil))
var _ = (NodeWriter)((*MemRegularFile)(nil))
var _ = (NodeSetattrer)((*MemRegularFile)(nil))
var _ = (NodeFlusher)((*MemRegularFile)(nil)) var _ = (NodeFlusher)((*MemRegularFile)(nil))
func (f *MemRegularFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) { func (f *MemRegularFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) {
if flags&(syscall.O_RDWR) != 0 || flags&syscall.O_WRONLY != 0 { return nil, fuse.FOPEN_KEEP_CACHE, OK
return nil, 0, syscall.EPERM }
func (f *MemRegularFile) Write(ctx context.Context, fh FileHandle, data []byte, off int64) (uint32, syscall.Errno) {
f.mu.Lock()
defer f.mu.Unlock()
end := int64(len(data)) + off
if int64(len(f.Data)) < end {
n := make([]byte, end)
copy(n, f.Data)
f.Data = n
} }
return nil, fuse.FOPEN_KEEP_CACHE, OK copy(f.Data[off:off+int64(len(data))], data)
return uint32(len(data)), 0
} }
var _ = (NodeGetattrer)((*MemRegularFile)(nil)) var _ = (NodeGetattrer)((*MemRegularFile)(nil))
func (f *MemRegularFile) Getattr(ctx context.Context, fh FileHandle, out *fuse.AttrOut) syscall.Errno { func (f *MemRegularFile) Getattr(ctx context.Context, fh FileHandle, out *fuse.AttrOut) syscall.Errno {
f.mu.Lock()
defer f.mu.Unlock()
out.Attr = f.Attr out.Attr = f.Attr
out.Attr.Size = uint64(len(f.Data)) out.Attr.Size = uint64(len(f.Data))
return OK return OK
} }
func (f *MemRegularFile) Setattr(ctx context.Context, fh FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
f.mu.Lock()
defer f.mu.Unlock()
if sz, ok := in.GetSize(); ok {
f.Data = f.Data[:sz]
}
out.Attr = f.Attr
out.Size = uint64(len(f.Data))
return OK
}
func (f *MemRegularFile) Flush(ctx context.Context, fh FileHandle) syscall.Errno { func (f *MemRegularFile) Flush(ctx context.Context, fh FileHandle) syscall.Errno {
return 0 return 0
} }
func (f *MemRegularFile) Read(ctx context.Context, fh FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { func (f *MemRegularFile) Read(ctx context.Context, fh FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
f.mu.Lock()
defer f.mu.Unlock()
end := int(off) + len(dest) end := int(off) + len(dest)
if end > len(f.Data) { if end > len(f.Data) {
end = len(f.Data) end = len(f.Data)
......
...@@ -64,7 +64,6 @@ func TestDefaultOwner(t *testing.T) { ...@@ -64,7 +64,6 @@ func TestDefaultOwner(t *testing.T) {
} else if st.Uid != 42 || st.Gid != 43 { } else if st.Uid != 42 || st.Gid != 43 {
t.Fatalf("Got Lstat %d, %d want 42,43", st.Uid, st.Gid) t.Fatalf("Got Lstat %d, %d want 42,43", st.Uid, st.Gid)
} }
} }
func TestDataFile(t *testing.T) { func TestDataFile(t *testing.T) {
...@@ -116,6 +115,17 @@ func TestDataFile(t *testing.T) { ...@@ -116,6 +115,17 @@ func TestDataFile(t *testing.T) {
if got != want { if got != want {
t.Errorf("got %q want %q", got, want) t.Errorf("got %q want %q", got, want)
} }
replace := []byte("replaced!")
if err := ioutil.WriteFile(mntDir+"/file", replace, 0644); err != nil {
t.Fatalf("WriteFile: %v", err)
}
if gotBytes, err := ioutil.ReadFile(mntDir + "/file"); err != nil {
t.Fatalf("ReadFile: %v", err)
} else if bytes.Compare(replace, gotBytes) != 0 {
t.Fatalf("read: got %q want %q", gotBytes, replace)
}
} }
func TestDataFileLargeRead(t *testing.T) { func TestDataFileLargeRead(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment