1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package zipfs
/*
This provides a practical example of mounting Go-fuse path filesystems
on top of each other.
It is a file system that configures a Zip filesystem at /zipmount when
symlinking path/to/zipfile to /config/zipmount
*/
import (
"context"
"log"
"syscall"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
)
// MultiZipFs is a filesystem that mounts zipfiles.
type MultiZipFs struct {
fs.Inode
}
func (root *MultiZipFs) OnAdd(ctx context.Context) {
n := root.NewPersistentInode(ctx, &configRoot{}, fs.StableAttr{Mode: syscall.S_IFDIR})
root.AddChild("config", n, false)
}
type configRoot struct {
fs.Inode
}
var _ = (fs.NodeUnlinker)((*configRoot)(nil))
var _ = (fs.NodeSymlinker)((*configRoot)(nil))
func (r *configRoot) Unlink(ctx context.Context, basename string) syscall.Errno {
if r.GetChild(basename) == nil {
return syscall.ENOENT
}
// XXX RmChild should return Inode?
_, parent := r.Parent()
ch := parent.GetChild(basename)
if ch == nil {
return syscall.ENOENT
}
success, _ := parent.RmChild(basename)
if !success {
return syscall.EIO
}
ch.RmAllChildren()
parent.RmChild(basename)
parent.NotifyEntry(basename)
return 0
}
func (r *configRoot) Symlink(ctx context.Context, target string, base string, out *fuse.EntryOut) (*fs.Inode, syscall.Errno) {
root, err := NewArchiveFileSystem(target)
if err != nil {
log.Println("NewZipArchiveFileSystem failed.", err)
return nil, syscall.EINVAL
}
_, parent := r.Parent()
ch := r.NewPersistentInode(ctx, root, fs.StableAttr{Mode: syscall.S_IFDIR})
parent.AddChild(base, ch, false)
link := r.NewPersistentInode(ctx, &fs.MemSymlink{
Data: []byte(target),
}, fs.StableAttr{Mode: syscall.S_IFLNK})
r.AddChild(base, link, false)
return link, 0
}
|