1// +build darwin freebsd linux 2 3package fuse 4 5import ( 6 "context" 7 "os" 8 9 "github.com/restic/restic/internal/debug" 10 11 "bazil.org/fuse" 12 "bazil.org/fuse/fs" 13) 14 15// ensure that *DirSnapshots implements these interfaces 16var _ = fs.HandleReadDirAller(&MetaDir{}) 17var _ = fs.NodeStringLookuper(&MetaDir{}) 18 19// MetaDir is a fuse directory which contains other directories. 20type MetaDir struct { 21 inode uint64 22 root *Root 23 entries map[string]fs.Node 24} 25 26// NewMetaDir returns a new meta dir. 27func NewMetaDir(root *Root, inode uint64, entries map[string]fs.Node) *MetaDir { 28 debug.Log("new meta dir with %d entries, inode %d", len(entries), inode) 29 30 return &MetaDir{ 31 root: root, 32 inode: inode, 33 entries: entries, 34 } 35} 36 37// Attr returns the attributes for the root node. 38func (d *MetaDir) Attr(ctx context.Context, attr *fuse.Attr) error { 39 attr.Inode = d.inode 40 attr.Mode = os.ModeDir | 0555 41 attr.Uid = d.root.uid 42 attr.Gid = d.root.gid 43 44 debug.Log("attr: %v", attr) 45 return nil 46} 47 48// ReadDirAll returns all entries of the root node. 49func (d *MetaDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) { 50 debug.Log("ReadDirAll()") 51 items := []fuse.Dirent{ 52 { 53 Inode: d.inode, 54 Name: ".", 55 Type: fuse.DT_Dir, 56 }, 57 { 58 Inode: d.root.inode, 59 Name: "..", 60 Type: fuse.DT_Dir, 61 }, 62 } 63 64 for name := range d.entries { 65 items = append(items, fuse.Dirent{ 66 Inode: fs.GenerateDynamicInode(d.inode, name), 67 Name: name, 68 Type: fuse.DT_Dir, 69 }) 70 } 71 72 return items, nil 73} 74 75// Lookup returns a specific entry from the root node. 76func (d *MetaDir) Lookup(ctx context.Context, name string) (fs.Node, error) { 77 debug.Log("Lookup(%s)", name) 78 79 if dir, ok := d.entries[name]; ok { 80 return dir, nil 81 } 82 83 return nil, fuse.ENOENT 84} 85