@@ -49,9 +49,10 @@ func Mount(mountpoint string, pcClient *sdk.Client) (*Drive, error) {
49
49
pcClient : pcClient ,
50
50
uid : uint32 (uid ),
51
51
gid : uint32 (gid ),
52
- rdev : 531 ,
53
52
dirPerms : 0o750 ,
54
53
filePerms : 0o640 ,
54
+ dirValid : 2 * time .Second ,
55
+ fileValid : time .Second ,
55
56
},
56
57
conn : conn ,
57
58
}, nil
@@ -70,9 +71,10 @@ type FS struct {
70
71
pcClient * sdk.Client // TODO: define an interface
71
72
uid uint32
72
73
gid uint32
73
- rdev uint32
74
74
dirPerms os.FileMode
75
75
filePerms os.FileMode
76
+ dirValid time.Duration
77
+ fileValid time.Duration
76
78
}
77
79
78
80
// ensure interfaces conpliance
@@ -134,7 +136,7 @@ func (d *Dir) materialiseFolder(ctx context.Context) error {
134
136
135
137
// TODO: is this necessary? perhaps only for the root folder?
136
138
d .Attributes = fuse.Attr {
137
- Valid : time . Second ,
139
+ Valid : d . fs . dirValid ,
138
140
Inode : d .folderID ,
139
141
Atime : fsList .Metadata .Modified .Time ,
140
142
Mtime : fsList .Metadata .Modified .Time ,
@@ -143,9 +145,7 @@ func (d *Dir) materialiseFolder(ctx context.Context) error {
143
145
Nlink : 1 , // TODO: is that right? How else can we find this value?
144
146
Uid : d .fs .uid ,
145
147
Gid : d .fs .gid ,
146
- Rdev : d .fs .rdev ,
147
148
}
148
-
149
149
d .parentFolderID = fsList .Metadata .ParentFolderID
150
150
d .folderID = fsList .Metadata .FolderID
151
151
@@ -154,7 +154,7 @@ func (d *Dir) materialiseFolder(ctx context.Context) error {
154
154
return item .Name , & Dir {
155
155
Type : fuse .DT_Dir ,
156
156
Attributes : fuse.Attr {
157
- Valid : time . Second ,
157
+ Valid : d . fs . dirValid ,
158
158
Inode : item .FolderID ,
159
159
Atime : item .Modified .Time ,
160
160
Mtime : item .Modified .Time ,
@@ -163,9 +163,8 @@ func (d *Dir) materialiseFolder(ctx context.Context) error {
163
163
Nlink : 1 , // the official pCloud client can show other values that 1 - dunno how
164
164
Uid : d .fs .uid ,
165
165
Gid : d .fs .gid ,
166
- Rdev : d .fs .rdev ,
167
166
},
168
- Entries : nil , // will be populated by Dir.Lookup
167
+ Entries : nil , // will be populated upon access by Dir.Lookup or Dir.ReadDirAll
169
168
fs : d .fs ,
170
169
parentFolderID : item .ParentFolderID ,
171
170
folderID : item .FolderID ,
@@ -176,7 +175,7 @@ func (d *Dir) materialiseFolder(ctx context.Context) error {
176
175
Type : fuse .DT_File ,
177
176
// Content: content, // TODO
178
177
Attributes : fuse.Attr {
179
- Valid : time . Second ,
178
+ Valid : d . fs . fileValid ,
180
179
Inode : item .FileID ,
181
180
Size : item .Size ,
182
181
Atime : item .Modified .Time ,
@@ -186,8 +185,11 @@ func (d *Dir) materialiseFolder(ctx context.Context) error {
186
185
Nlink : 1 , // TODO: is that right? How else can we find this value?
187
186
Uid : d .fs .uid ,
188
187
Gid : d .fs .gid ,
189
- Rdev : d .fs .rdev ,
190
188
},
189
+ fs : d .fs ,
190
+ folderID : item .FolderID ,
191
+ fileID : item .FileID ,
192
+ file : nil ,
191
193
}
192
194
})
193
195
@@ -257,23 +259,98 @@ type File struct {
257
259
Type fuse.DirentType
258
260
Content []byte
259
261
Attributes fuse.Attr
262
+ fs * FS
263
+ folderID uint64 // TODO: not needed??
264
+ fileID uint64
265
+ file * sdk.File
260
266
}
261
267
262
268
// ensure interfaces conpliance
263
269
var (
264
270
_ = (fs .Node )((* File )(nil ))
265
271
// _ = (fs.HandleWriter)((*File)(nil))
266
- _ = (fs .HandleReadAller )((* File )(nil ))
272
+ // _ = (fs.HandleReadAller)((*File)(nil)) // NOTE: it's best avoiding to implement this method to avoid costly memory operations with large files.
273
+ _ = (fs .HandleReader )((* File )(nil ))
274
+ _ = (fs .NodeOpener )((* File )(nil ))
275
+ _ = (fs .HandleFlusher )((* File )(nil ))
276
+ _ = (fs .HandleReleaser )((* File )(nil ))
267
277
// _ = (fs.NodeSetattrer)((*File)(nil))
268
278
// _ = (EntryGetter)((*File)(nil))
269
279
)
270
280
271
- func (f File ) Attr (ctx context.Context , a * fuse.Attr ) error {
281
+ func (f * File ) Attr (ctx context.Context , a * fuse.Attr ) error {
272
282
log .Println ("File.Attr called" )
273
283
* a = f .Attributes
274
284
return nil
275
285
}
276
286
277
- func (File ) ReadAll (ctx context.Context ) ([]byte , error ) {
278
- return []byte (nil ), nil // TODO
287
+ type fileHandle struct {
288
+ file * sdk.File
289
+ }
290
+
291
+ func (f * File ) Open (ctx context.Context , req * fuse.OpenRequest , resp * fuse.OpenResponse ) (fs.Handle , error ) {
292
+ log .Println ("File.Open - 1 - req.ID" , req .ID , " - resp.Handle:" , resp .Handle )
293
+
294
+ // TODO: this is temporary - for now, let's focus on a read-only implementation
295
+ if ! req .Flags .IsReadOnly () {
296
+ return nil , fuse .Errno (syscall .EACCES )
297
+ }
298
+
299
+ file , err := f .fs .pcClient .FileOpen (ctx , 0 , sdk .T4FileByID (f .fileID ))
300
+ if err != nil {
301
+ return nil , err
302
+ }
303
+
304
+ f .file = file
305
+ log .Println ("File.Open - 2 - req.ID" , req .ID , " - file.FD:" , file .FD )
306
+ resp .Flags |= fuse .OpenKeepCache
307
+
308
+ return & File {
309
+ Type : f .Type ,
310
+ Attributes : f .Attributes ,
311
+ fs : f .fs ,
312
+ folderID : f .folderID ,
313
+ fileID : f .fileID ,
314
+ file : file ,
315
+ }, nil
316
+ }
317
+
318
+ func (f * File ) Read (ctx context.Context , req * fuse.ReadRequest , resp * fuse.ReadResponse ) error {
319
+ log .Println ("File.Read called - req.ID" , req .ID , " - req.Handle:" , req .Handle )
320
+ if f .file == nil {
321
+ return syscall .ENOENT
322
+ }
323
+
324
+ data , err := f .fs .pcClient .FilePRead (ctx , f .file .FD , uint64 (req .Size ), uint64 (req .Offset ))
325
+ if err != nil {
326
+ return err
327
+ }
328
+ resp .Data = data
329
+
330
+ return nil
331
+ }
332
+
333
+ // Flush is called each time the file or directory is closed.
334
+ // Because there can be multiple file descriptors referring to a
335
+ // single opened file, Flush can be called multiple times.
336
+ func (f * File ) Flush (ctx context.Context , req * fuse.FlushRequest ) error {
337
+ log .Println ("File.Flush called - req.ID" , req .ID , " - req.Handle:" , req .Handle )
338
+ if f .file != nil {
339
+ err := f .fs .pcClient .FileClose (ctx , f .file .FD )
340
+ f .file = nil
341
+ return err
342
+ }
343
+
344
+ return nil
345
+ }
346
+
347
+ // A ReleaseRequest asks to release (close) an open file handle.
348
+ func (f * File ) Release (ctx context.Context , req * fuse.ReleaseRequest ) error {
349
+ if f .file != nil {
350
+ err := f .fs .pcClient .FileClose (ctx , f .file .FD )
351
+ f .file = nil
352
+ return err
353
+ }
354
+
355
+ return nil
279
356
}
0 commit comments