44 "context"
55 "fmt"
66 "path"
7+ "strings"
78 "syscall"
89
910 "github.com/hanwen/go-fuse/v2/fs"
@@ -51,6 +52,9 @@ func (n *FSNode) Getattr(ctx context.Context, fh fs.FileHandle, out *fuse.AttrOu
5152 out .Mode = node .Attr .Mode
5253 out .Nlink = node .Attr .Nlink
5354 out .Owner = node .Attr .Owner
55+ out .Atimensec = node .Attr .Atimensec
56+ out .Mtimensec = node .Attr .Mtimensec
57+ out .Ctimensec = node .Attr .Ctimensec
5458
5559 return fs .OK
5660}
@@ -78,21 +82,14 @@ func metaToAttr(metadata *BlobFsMetadata) fuse.Attr {
7882 }
7983}
8084
81- func (n * FSNode ) Lookup (ctx context.Context , name string , out * fuse.EntryOut ) (* fs.Inode , syscall.Errno ) {
82- n .log ("Lookup called with name: %s" , name )
83-
84- // Construct the full of this file path from root
85- fullPath := path .Join (n .bfsNode .Path , name )
86-
87- id := GenerateFsID (fullPath )
88- metadata , err := n .filesystem .Metadata .GetFsNode (ctx , id )
85+ func (n * FSNode ) inodeFromFsId (ctx context.Context , fsId string ) (* fs.Inode , * fuse.Attr , error ) {
86+ metadata , err := n .filesystem .Metadata .GetFsNode (ctx , fsId )
8987 if err != nil {
90- return nil , syscall .ENOENT
88+ return nil , nil , syscall .ENOENT
9189 }
9290
9391 // Fill out the child node's attributes
9492 attr := metaToAttr (metadata )
95- out .Attr = attr
9693
9794 // Create a new Inode on lookup
9895 node := n .NewInode (ctx ,
@@ -105,9 +102,46 @@ func (n *FSNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*
105102 Attr : attr ,
106103 Target : "" ,
107104 }, attr : attr },
108- fs.StableAttr {Mode : metadata .Mode , Ino : metadata .Ino },
105+ fs.StableAttr {Mode : metadata .Mode , Ino : metadata .Ino , Gen : metadata . Gen },
109106 )
110107
108+ return node , & attr , nil
109+ }
110+
111+ func (n * FSNode ) Lookup (ctx context.Context , name string , out * fuse.EntryOut ) (* fs.Inode , syscall.Errno ) {
112+ fullPath := path .Join (n .bfsNode .Path , name ) // Construct the full of this file path from root
113+ n .log ("Lookup called with path: %s" , fullPath )
114+
115+ // Force caching of a specific full path if the path contains a special illegal character '%'
116+ // This is a hack to trigger caching from external callers without going through the GRPC service directly
117+ if strings .Contains (fullPath , "%" ) {
118+ sourcePath := strings .ReplaceAll (fullPath , "%" , "/" )
119+
120+ if ! n .filesystem .Client .HostsAvailable () {
121+ return nil , syscall .ENOENT
122+ }
123+
124+ n .log ("Storing content from source with path: %s" , sourcePath )
125+ _ , err := n .filesystem .Client .StoreContentFromSource (sourcePath , 0 )
126+ if err != nil {
127+ return nil , syscall .ENOENT
128+ }
129+
130+ node , attr , err := n .inodeFromFsId (ctx , GenerateFsID (sourcePath ))
131+ if err != nil {
132+ return nil , syscall .ENOENT
133+ }
134+
135+ out .Attr = * attr
136+ return node , fs .OK
137+ }
138+
139+ node , attr , err := n .inodeFromFsId (ctx , GenerateFsID (fullPath ))
140+ if err != nil {
141+ return nil , syscall .ENOENT
142+ }
143+
144+ out .Attr = * attr
111145 return node , fs .OK
112146}
113147
@@ -118,6 +152,11 @@ func (n *FSNode) Opendir(ctx context.Context) syscall.Errno {
118152
119153func (n * FSNode ) Open (ctx context.Context , flags uint32 ) (fh fs.FileHandle , fuseFlags uint32 , errno syscall.Errno ) {
120154 n .log ("Open called with flags: %v" , flags )
155+
156+ if ! n .filesystem .Client .HostsAvailable () {
157+ return nil , 0 , syscall .EIO
158+ }
159+
121160 return nil , 0 , fs .OK
122161}
123162
0 commit comments