@@ -3,12 +3,13 @@ package dmfs
33import (
44 "context"
55 "fmt"
6- "log "
6+ "sync "
77 "syscall"
88 "time"
99
1010 "github.com/hanwen/go-fuse/v2/fs"
1111 "github.com/hanwen/go-fuse/v2/fuse"
12+ "github.com/pkg/errors"
1213)
1314
1415/*
@@ -19,14 +20,25 @@ import (
1920type rootNode struct {
2021 fs.Inode
2122
23+ loading bool
2224 nsNodes map [string ]* namespaceNode
25+
26+ mx sync.Mutex
2327}
2428
25- // implement the interfaces
26- var _ = (fs .NodeReaddirer )((* rootNode )(nil ))
27- var _ = (fs .NodeRenamer )((* rootNode )(nil ))
28- var _ = (fs .NodeRmdirer )((* rootNode )(nil ))
29- var _ = (fs .NodeLookuper )((* rootNode )(nil ))
29+ // Implement required interfaces
30+ var (
31+ _ = (fs .NodeReaddirer )((* rootNode )(nil ))
32+ _ = (fs .NodeRenamer )((* rootNode )(nil ))
33+ _ = (fs .NodeRmdirer )((* rootNode )(nil ))
34+ _ = (fs .NodeLookuper )((* rootNode )(nil ))
35+ _ = (fs .NodeGetattrer )((* rootNode )(nil ))
36+ )
37+
38+ var (
39+ // ErrAlreadyLoading error if a load process is already running
40+ ErrAlreadyLoading = errors .New ("already loading" )
41+ )
3042
3143// Create new root Node
3244func newRootNode () * rootNode {
@@ -37,19 +49,50 @@ func newRootNode() *rootNode {
3749
3850// On dir access, load namespaces and groups
3951func (root * rootNode ) Readdir (ctx context.Context ) (fs.DirStream , syscall.Errno ) {
40- fmt .Println ("read root" )
52+ r := make ([]fuse.DirEntry , 0 )
53+
54+ // Load namespaces and groups
55+ err := root .load (func (name string ) {
56+ r = append (r , fuse.DirEntry {
57+ Name : name ,
58+ Mode : syscall .S_IFDIR ,
59+ })
60+ })
61+
62+ // If already loading, use current cache
63+ if err != nil && err != ErrAlreadyLoading {
64+ fmt .Println (err )
65+ return nil , syscall .EIO
66+ }
67+
68+ return fs .NewListDirStream (r ), 0
69+ }
70+
71+ // Load groups and namespaces
72+ func (root * rootNode ) load (nsCB func (name string )) error {
73+ if root .loading {
74+ return ErrAlreadyLoading
75+ }
76+
77+ root .mx .Lock ()
78+ root .loading = true
79+
80+ defer func () {
81+ // Unlock and set loading to false
82+ // at the end
83+ root .loading = false
84+ root .mx .Unlock ()
85+ }()
86+
4187 // Use dataStore to retrieve
4288 // groups and namespaces
4389 err := data .loadUserAttributes ()
4490 if err != nil {
45- log .Fatal (err )
46- return nil , syscall .ENOENT
91+ return err
4792 }
4893
49- r := make ([]fuse.DirEntry , len (data .userAttributes .Namespace ))
50-
5194 // Loop Namespaces and add childs in as folders
52- for i , namespace := range data .userAttributes .Namespace {
95+ for _ , namespace := range data .userAttributes .Namespace {
5396 nsName := removeNSName (namespace .Name )
5497
5598 // Find namespace node
@@ -62,13 +105,12 @@ func (root *rootNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno)
62105 v .nsInfo .Groups = namespace .Groups
63106 }
64107
65- r [i ] = fuse.DirEntry {
66- Name : nsName ,
67- Mode : syscall .S_IFDIR ,
108+ if nsCB != nil {
109+ nsCB (nsName )
68110 }
69111 }
70112
71- return fs . NewListDirStream ( r ), 0
113+ return nil
72114}
73115
74116// Lookup -> something tries to lookup a file (namespace)
@@ -117,7 +159,7 @@ func (root *rootNode) Rename(ctx context.Context, name string, newParent fs.Inod
117159 // Don't rename default ns
118160 if name == "default" {
119161 fmt .Println ("Can't rename default namespace!" )
120- return syscall .EPERM
162+ return syscall .EIO
121163 }
122164
123165 // Get real namespace names
@@ -129,13 +171,20 @@ func (root *rootNode) Rename(ctx context.Context, name string, newParent fs.Inod
129171 _ , err := data .libdm .UpdateNamespace (oldNSName , newNSName )
130172 if err != nil {
131173 fmt .Println (err )
132- return syscall .ENONET
174+ return syscall .EIO
133175 }
134176
135177 // Return success
136178 return 0
137179}
138180
181+ // Set attributes for files
182+ func (root * rootNode ) Getattr (ctx context.Context , f fs.FileHandle , out * fuse.AttrOut ) syscall.Errno {
183+ // Set owner/group
184+ data .setUserAttr (out )
185+ return 0
186+ }
187+
139188func (root * rootNode ) debug (arg ... interface {}) {
140189 if data .mounter .Debug {
141190 fmt .Println (arg ... )
0 commit comments