package nostrfs import ( "context" "sync" "syscall" "github.com/hanwen/go-fuse/v2/fs" "github.com/hanwen/go-fuse/v2/fuse" ) type WriteableFile struct { fs.Inode root *NostrRoot mu sync.Mutex data []byte attr fuse.Attr onWrite func(string) } var ( _ = (fs.NodeOpener)((*WriteableFile)(nil)) _ = (fs.NodeReader)((*WriteableFile)(nil)) _ = (fs.NodeWriter)((*WriteableFile)(nil)) _ = (fs.NodeGetattrer)((*WriteableFile)(nil)) _ = (fs.NodeSetattrer)((*WriteableFile)(nil)) _ = (fs.NodeFlusher)((*WriteableFile)(nil)) ) func (r *NostrRoot) NewWriteableFile(data string, ctime, mtime uint64, onWrite func(string)) *WriteableFile { return &WriteableFile{ root: r, data: []byte(data), attr: fuse.Attr{ Mode: 0666, Ctime: ctime, Mtime: mtime, Size: uint64(len(data)), }, onWrite: onWrite, } } func (f *WriteableFile) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) { return nil, fuse.FOPEN_KEEP_CACHE, fs.OK } func (f *WriteableFile) Write(ctx context.Context, fh fs.FileHandle, data []byte, off int64) (uint32, syscall.Errno) { f.mu.Lock() defer f.mu.Unlock() offset := int(off) end := offset + len(data) if len(f.data) < end { newData := make([]byte, offset+len(data)) copy(newData, f.data) f.data = newData } copy(f.data[offset:], data) f.data = f.data[0:end] f.onWrite(string(f.data)) return uint32(len(data)), fs.OK } func (f *WriteableFile) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOut) syscall.Errno { f.mu.Lock() defer f.mu.Unlock() out.Attr = f.attr out.Attr.Size = uint64(len(f.data)) return fs.OK } func (f *WriteableFile) Setattr(_ context.Context, _ fs.FileHandle, in *fuse.SetAttrIn, _ *fuse.AttrOut) syscall.Errno { f.attr.Mtime = in.Mtime f.attr.Atime = in.Atime f.attr.Ctime = in.Ctime return fs.OK } func (f *WriteableFile) Flush(ctx context.Context, fh fs.FileHandle) syscall.Errno { return fs.OK } func (f *WriteableFile) Read(ctx context.Context, fh fs.FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) { f.mu.Lock() defer f.mu.Unlock() end := int(off) + len(dest) if end > len(f.data) { end = len(f.data) } return fuse.ReadResultData(f.data[off:end]), fs.OK }