package vfs import ( "os" "time" cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" "gitlink.org.cn/cloudream/storage/client2/internal/mount/fuse" "gitlink.org.cn/cloudream/storage/client2/internal/mount/vfs/cache" "gorm.io/gorm" ) type FuseFileNode struct { vfs *Vfs pathComps []string size int64 modTime time.Time mode os.FileMode } func newFileFromCache(info cache.CacheEntryInfo, vfs *Vfs) *FuseFileNode { return &FuseFileNode{ vfs: vfs, pathComps: info.PathComps, size: info.Size, modTime: info.ModTime, mode: info.Mode, } } func newFileFromObject(vfs *Vfs, pathComps []string, obj cdssdk.Object) *FuseFileNode { return &FuseFileNode{ vfs: vfs, pathComps: pathComps, size: obj.Size, modTime: obj.UpdateTime, mode: os.FileMode(0755), // TODO Object元数据中是没有保存权限的 } } func (n *FuseFileNode) Name() string { return n.pathComps[len(n.pathComps)-1] } func (n *FuseFileNode) Size() int64 { return n.size } func (n *FuseFileNode) Mode() os.FileMode { return n.mode } func (n *FuseFileNode) ModTime() time.Time { return n.modTime } func (n *FuseFileNode) IsDir() bool { return false } func (n *FuseFileNode) Truncate(size uint64) error { cacheFile := n.loadCacheFile() if cacheFile == nil { return fuse.ErrNotExists } defer cacheFile.Release() return cacheFile.Truncate(int64(size)) } func (n *FuseFileNode) SetModTime(time time.Time) error { cacheFile := n.loadCacheFile() if cacheFile == nil { return fuse.ErrNotExists } defer cacheFile.Release() return cacheFile.SetModTime(time) } func (n *FuseFileNode) Open(flags uint32) (fuse.FileHandle, uint32, error) { cacheFile := n.loadCacheFile() if cacheFile == nil { // 如果文件不存在,也不进行创建,因为创建不应该调用这个接口 return nil, 0, fuse.ErrNotExists } defer cacheFile.Release() hd := cacheFile.Open(flags) return newFileHandle(n, hd), flags, nil } func (n *FuseFileNode) loadCacheFile() *cache.CacheFile { if len(n.pathComps) <= 2 { return n.vfs.cache.LoadFile(n.pathComps, nil) } cdsObj, err := n.vfs.db.Object().GetByFullPath(n.vfs.db.DefCtx(), n.pathComps[0], n.pathComps[1], cdssdk.JoinObjectPath(n.pathComps[2:]...)) if err == nil { file := n.vfs.cache.LoadFile(n.pathComps, &cdsObj) if file == nil { return nil } return file } if err == gorm.ErrRecordNotFound { return n.vfs.cache.LoadFile(n.pathComps, nil) } return nil } type FuseFileHandle struct { entry *FuseFileNode readWriter *cache.CacheFileReadWriter } func newFileHandle(entry *FuseFileNode, readWriter *cache.CacheFileReadWriter) *FuseFileHandle { return &FuseFileHandle{ entry: entry, readWriter: readWriter, } } func (hd *FuseFileHandle) Entry() fuse.FsFile { return hd.entry } func (hd *FuseFileHandle) ReadAt(buf []byte, off int64) (int, error) { return hd.readWriter.ReadAt(buf, off) } func (hd *FuseFileHandle) WriteAt(buf []byte, off int64) (int, error) { return hd.readWriter.WriteAt(buf, off) } func (hd *FuseFileHandle) Sync() error { return hd.readWriter.Sync() } func (hd *FuseFileHandle) Close() error { return hd.readWriter.Close() } func (hd *FuseFileHandle) Release() error { // TODO 其他清理工作 return nil }