Files
zurg/internal/zfs/zfs.go
Ben Sarmiento ff93baa6c1 Fix repair :)
2023-11-18 23:39:42 +01:00

184 lines
5.0 KiB
Go

package zfs
import (
"strings"
"github.com/debridmediamanager.com/zurg/internal/config"
"github.com/debridmediamanager.com/zurg/internal/torrent"
"github.com/debridmediamanager.com/zurg/pkg/chunk"
cmap "github.com/orcaman/concurrent-map/v2"
"github.com/winfsp/cgofuse/fuse"
"go.uber.org/zap"
)
type ZurgFS struct {
fuse.FileSystemBase
TorrentManager *torrent.TorrentManager
Config config.ConfigInterface
Chunk *chunk.Manager
Log *zap.SugaredLogger
}
func NewZurgFS(tm *torrent.TorrentManager, cfg config.ConfigInterface, chunk *chunk.Manager, log *zap.SugaredLogger) *ZurgFS {
return &ZurgFS{
TorrentManager: tm,
Config: cfg,
Chunk: chunk,
Log: log,
}
}
func (fs *ZurgFS) Open(path string, flags int) (errc int, fh uint64) {
segments := splitIntoSegments(path)
switch len(segments) {
case 0:
return 0, 0
case 1:
if _, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT, ^uint64(0)
}
return 0, 0
case 2:
if directory, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT, ^uint64(0)
} else if _, torFound := directory.Get(segments[1]); !torFound {
return -fuse.ENOENT, ^uint64(0)
}
return 0, 0
case 3:
if directory, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT, ^uint64(0)
} else if torrent, torFound := directory.Get(segments[1]); !torFound {
return -fuse.ENOENT, ^uint64(0)
} else if file, fileFound := torrent.SelectedFiles.Get(segments[2]); !fileFound {
return -fuse.ENOENT, ^uint64(0)
} else {
return 0, file.ZurgFS
}
}
return -fuse.ENOENT, ^uint64(0)
}
func (fs *ZurgFS) Getattr(path string, stat *fuse.Stat_t, fh uint64) (errc int) {
segments := splitIntoSegments(path)
switch len(segments) {
case 0:
stat.Mode = fuse.S_IFDIR | 0555
return 0
case 1:
if _, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT
}
stat.Mode = fuse.S_IFDIR | 0555
return 0
case 2:
if directory, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT
} else if _, torFound := directory.Get(segments[1]); !torFound {
return -fuse.ENOENT
}
stat.Mode = fuse.S_IFDIR | 0555
return 0
case 3:
if directory, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT
} else if torrent, torFound := directory.Get(segments[1]); !torFound {
return -fuse.ENOENT
} else if file, fileFound := torrent.SelectedFiles.Get(segments[2]); !fileFound {
return -fuse.ENOENT
} else {
stat.Mode = fuse.S_IFREG | 0444
stat.Size = file.Bytes
return 0
}
}
return -fuse.ENOENT
}
func (fs *ZurgFS) Read(path string, buff []byte, ofst int64, fh uint64) (n int) {
segments := splitIntoSegments(path)
if len(segments) != 3 {
return -fuse.ENOENT
} else if directory, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT
} else if torrent, torFound := directory.Get(segments[1]); !torFound {
return -fuse.ENOENT
} else if file, fileFound := torrent.SelectedFiles.Get(segments[2]); !fileFound {
return -fuse.ENOENT
} else {
size := int64(len(buff))
endofst := ofst + size
if endofst > file.Bytes {
endofst = file.Bytes
}
if endofst < ofst {
return 0
}
// let's request a bigger chunk than we need
if size < int64(fs.Config.GetNetworkBufferSize()) {
size = int64(fs.Config.GetNetworkBufferSize())
}
response, err := fs.Chunk.GetChunk(file, ofst, size)
if err != nil {
return -fuse.ENOENT
}
n = copy(buff, response[:endofst-ofst])
return n
}
}
func (fs *ZurgFS) Readdir(path string,
fill func(name string, stat *fuse.Stat_t, ofst int64) bool,
ofst int64,
fh uint64) (errc int) {
segments := splitIntoSegments(path)
switch len(segments) {
case 0:
fill(".", nil, 0)
fill("..", nil, 0)
fs.TorrentManager.DirectoryMap.IterCb(func(directoryName string, _ cmap.ConcurrentMap[string, *torrent.Torrent]) {
fill(directoryName, nil, 0)
})
case 1:
fill(".", nil, 0)
fill("..", nil, 0)
if torrents, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT
} else {
torrents.IterCb(func(accessKey string, _ *torrent.Torrent) {
fill(accessKey, nil, 0)
})
}
case 2:
fill(".", nil, 0)
fill("..", nil, 0)
if torrents, dirFound := fs.TorrentManager.DirectoryMap.Get(segments[0]); !dirFound {
return -fuse.ENOENT
} else if tor, torFound := torrents.Get(segments[1]); !torFound {
return -fuse.ENOENT
} else {
tor.SelectedFiles.IterCb(func(filename string, _ *torrent.File) {
fill(filename, nil, 0)
})
}
default:
return -fuse.ENOENT
}
return 0
}
func splitIntoSegments(path string) []string {
segments := strings.Split(path, "/")
// remove empty segments
for i := 0; i < len(segments); i++ {
if segments[i] == "" {
segments = append(segments[:i], segments[i+1:]...)
i--
}
}
return segments
}