restic/internal/fuse/meta_dir.go

86 lines
1.7 KiB
Go

//go:build darwin || freebsd || linux
// +build darwin freebsd linux
package fuse
import (
"context"
"os"
"github.com/restic/restic/internal/debug"
"bazil.org/fuse"
"bazil.org/fuse/fs"
)
// ensure that *DirSnapshots implements these interfaces
var _ = fs.HandleReadDirAller(&MetaDir{})
var _ = fs.NodeStringLookuper(&MetaDir{})
// MetaDir is a fuse directory which contains other directories.
type MetaDir struct {
inode uint64
root *Root
entries map[string]fs.Node
}
// NewMetaDir returns a new meta dir.
func NewMetaDir(root *Root, inode uint64, entries map[string]fs.Node) *MetaDir {
debug.Log("new meta dir with %d entries, inode %d", len(entries), inode)
return &MetaDir{
root: root,
inode: inode,
entries: entries,
}
}
// Attr returns the attributes for the root node.
func (d *MetaDir) Attr(ctx context.Context, attr *fuse.Attr) error {
attr.Inode = d.inode
attr.Mode = os.ModeDir | 0555
attr.Uid = d.root.uid
attr.Gid = d.root.gid
debug.Log("attr: %v", attr)
return nil
}
// ReadDirAll returns all entries of the root node.
func (d *MetaDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
debug.Log("ReadDirAll()")
items := []fuse.Dirent{
{
Inode: d.inode,
Name: ".",
Type: fuse.DT_Dir,
},
{
Inode: d.root.inode,
Name: "..",
Type: fuse.DT_Dir,
},
}
for name := range d.entries {
items = append(items, fuse.Dirent{
Inode: fs.GenerateDynamicInode(d.inode, name),
Name: name,
Type: fuse.DT_Dir,
})
}
return items, nil
}
// Lookup returns a specific entry from the root node.
func (d *MetaDir) Lookup(ctx context.Context, name string) (fs.Node, error) {
debug.Log("Lookup(%s)", name)
if dir, ok := d.entries[name]; ok {
return dir, nil
}
return nil, fuse.ENOENT
}