161 lines
3.3 KiB
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
|
|
}
|