1// Copyright 2019 the Go-FUSE Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package fs 6 7import ( 8 "context" 9 "sync" 10 "syscall" 11 12 "github.com/hanwen/go-fuse/v2/fuse" 13) 14 15// MemRegularFile is a filesystem node that holds a read-only data 16// slice in memory. 17type MemRegularFile struct { 18 Inode 19 20 mu sync.Mutex 21 Data []byte 22 Attr fuse.Attr 23} 24 25var _ = (NodeOpener)((*MemRegularFile)(nil)) 26var _ = (NodeReader)((*MemRegularFile)(nil)) 27var _ = (NodeWriter)((*MemRegularFile)(nil)) 28var _ = (NodeSetattrer)((*MemRegularFile)(nil)) 29var _ = (NodeFlusher)((*MemRegularFile)(nil)) 30 31func (f *MemRegularFile) Open(ctx context.Context, flags uint32) (fh FileHandle, fuseFlags uint32, errno syscall.Errno) { 32 return nil, fuse.FOPEN_KEEP_CACHE, OK 33} 34 35func (f *MemRegularFile) Write(ctx context.Context, fh FileHandle, data []byte, off int64) (uint32, syscall.Errno) { 36 f.mu.Lock() 37 defer f.mu.Unlock() 38 end := int64(len(data)) + off 39 if int64(len(f.Data)) < end { 40 n := make([]byte, end) 41 copy(n, f.Data) 42 f.Data = n 43 } 44 45 copy(f.Data[off:off+int64(len(data))], data) 46 47 return uint32(len(data)), 0 48} 49 50var _ = (NodeGetattrer)((*MemRegularFile)(nil)) 51 52func (f *MemRegularFile) Getattr(ctx context.Context, fh FileHandle, out *fuse.AttrOut) syscall.Errno { 53 f.mu.Lock() 54 defer f.mu.Unlock() 55 out.Attr = f.Attr 56 out.Attr.Size = uint64(len(f.Data)) 57 return OK 58} 59 60func (f *MemRegularFile) Setattr(ctx context.Context, fh FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno { 61 f.mu.Lock() 62 defer f.mu.Unlock() 63 if sz, ok := in.GetSize(); ok { 64 f.Data = f.Data[:sz] 65 } 66 out.Attr = f.Attr 67 out.Size = uint64(len(f.Data)) 68 return OK 69} 70 71func (f *MemRegularFile) Flush(ctx context.Context, fh FileHandle) syscall.Errno { 72 return 0 73} 74 75func (f *MemRegularFile) Read(ctx context.Context, fh FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { 76 f.mu.Lock() 77 defer f.mu.Unlock() 78 end := int(off) + len(dest) 79 if end > len(f.Data) { 80 end = len(f.Data) 81 } 82 return fuse.ReadResultData(f.Data[off:end]), OK 83} 84 85// MemSymlink is an inode holding a symlink in memory. 86type MemSymlink struct { 87 Inode 88 Attr fuse.Attr 89 Data []byte 90} 91 92var _ = (NodeReadlinker)((*MemSymlink)(nil)) 93 94func (l *MemSymlink) Readlink(ctx context.Context) ([]byte, syscall.Errno) { 95 return l.Data, OK 96} 97 98var _ = (NodeGetattrer)((*MemSymlink)(nil)) 99 100func (l *MemSymlink) Getattr(ctx context.Context, fh FileHandle, out *fuse.AttrOut) syscall.Errno { 101 out.Attr = l.Attr 102 return OK 103} 104