123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- package main
- import (
- "context"
- "log"
- "path/filepath"
- "strings"
- "sync"
- "syscall"
- "github.com/hanwen/go-fuse/v2/fs"
- "github.com/hanwen/go-fuse/v2/fuse"
- )
- type configFile struct {
- fs.MemRegularFile
- mu sync.Mutex
- StringData *string
- }
- func (f *configFile) Write(ctx context.Context, fh fs.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
- }
- copy(f.Data[off:off+int64(len(data))], data)
- str := string(data)
- *f.StringData = str
- return uint32(len(data)), 0
- }
- func (f *configFile) Read(ctx context.Context, fh fs.FileHandle, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
- f.mu.Lock()
- f.Data = []byte(*f.StringData)
- 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
- }
- // inMemoryFS is the root of the tree
- type inMemoryFS struct {
- fs.Inode
- configs map[string]*string
- }
- // Ensure that we implement NodeOnAdder
- var _ = (fs.NodeOnAdder)((*inMemoryFS)(nil))
- // OnAdd is called on mounting the file system. Use it to populate
- // the file system tree.
- func (root *inMemoryFS) OnAdd(ctx context.Context) {
- for name, content := range root.configs {
- dir, base := filepath.Split(name)
- p := &root.Inode
- // Add directories leading up to the file.
- for _, component := range strings.Split(dir, "/") {
- if len(component) == 0 {
- continue
- }
- ch := p.GetChild(component)
- if ch == nil {
- // Create a directory
- ch = p.NewPersistentInode(ctx, &fs.Inode{},
- fs.StableAttr{Mode: syscall.S_IFDIR})
- // Add it
- p.AddChild(component, ch, true)
- }
- p = ch
- }
- // Make a file out of the content bytes. This type
- // provides the open/read/flush methods.
- embedder := &configFile{StringData: content}
- embedder.Data = []byte(*content)
- // Create the file. The Inode must be persistent,
- // because its life time is not under control of the
- // kernel.
- child := p.NewPersistentInode(ctx, embedder, fs.StableAttr{})
- // And add it
- p.AddChild(base, child, true)
- }
- }
- // This demonstrates how to build a file system in memory. The
- // read/write logic for the file is provided by the MemRegularFile type.
- func StartFuse(mountPoint string, configs map[string]*string) {
- root := &inMemoryFS{configs: configs}
- server, err := fs.Mount(mountPoint, root, &fs.Options{
- MountOptions: fuse.MountOptions{Debug: true},
- })
- if err != nil {
- log.Panic(err)
- }
- log.Printf("Mounted on %s", mountPoint)
- log.Printf("Unmount by calling 'fusermount -u %s'", mountPoint)
- // Wait until unmount before exiting
- server.Wait()
- }
|