2018-06-16 06:48:45 +00:00
|
|
|
// +build !netbsd
|
2017-06-18 18:56:01 +00:00
|
|
|
// +build !openbsd
|
2018-03-04 13:30:06 +00:00
|
|
|
// +build !solaris
|
2017-06-18 18:56:01 +00:00
|
|
|
// +build !windows
|
|
|
|
|
|
|
|
package fuse
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
2017-07-23 12:21:03 +00:00
|
|
|
|
|
|
|
"github.com/restic/restic/internal/debug"
|
2017-06-18 18:56:01 +00:00
|
|
|
|
|
|
|
"golang.org/x/net/context"
|
|
|
|
|
|
|
|
"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
|
|
|
|
|
|
|
|
if !d.root.cfg.OwnerIsRoot {
|
|
|
|
attr.Uid = uint32(os.Getuid())
|
|
|
|
attr.Gid = uint32(os.Getgid())
|
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|