JCS-pub/client/internal/mount/vfs/fuse_file.go

161 lines
3.3 KiB
Go

package vfs
import (
"os"
"time"
"gitlink.org.cn/cloudream/jcs-pub/client/internal/mount/fuse"
"gitlink.org.cn/cloudream/jcs-pub/client/internal/mount/vfs/cache"
clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
"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 clitypes.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 {
info := n.vfs.cache.Stat(n.pathComps)
if info == nil {
return n.size
}
return info.Size
}
func (n *FuseFileNode) Mode() os.FileMode {
return n.mode
}
func (n *FuseFileNode) ModTime() time.Time {
info := n.vfs.cache.Stat(n.pathComps)
if info == nil {
return n.modTime
}
return info.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], clitypes.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
chd *cache.CacheFileHandle
}
func newFileHandle(entry *FuseFileNode, chd *cache.CacheFileHandle) *FuseFileHandle {
return &FuseFileHandle{
entry: entry,
chd: chd,
}
}
func (hd *FuseFileHandle) Entry() fuse.FsFile {
return hd.entry
}
func (hd *FuseFileHandle) ReadAt(buf []byte, off int64) (int, error) {
return hd.chd.ReadAt(buf, off)
}
func (hd *FuseFileHandle) WriteAt(buf []byte, off int64) (int, error) {
return hd.chd.WriteAt(buf, off)
}
func (hd *FuseFileHandle) Sync() error {
return hd.chd.Sync()
}
func (hd *FuseFileHandle) Close() error {
return hd.chd.Close()
}
func (hd *FuseFileHandle) Release() error {
// TODO 其他清理工作
return nil
}