defuse
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
package zfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse/fs"
|
||||
"github.com/debridmediamanager.com/zurg/internal/config"
|
||||
"github.com/debridmediamanager.com/zurg/internal/torrent"
|
||||
"github.com/debridmediamanager.com/zurg/pkg/chunk"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type FS struct {
|
||||
uid uint32
|
||||
gid uint32
|
||||
umask os.FileMode
|
||||
directIO bool
|
||||
lock sync.RWMutex
|
||||
c config.ConfigInterface
|
||||
t *torrent.TorrentManager
|
||||
log *zap.SugaredLogger
|
||||
initTime time.Time
|
||||
chunk *chunk.Manager
|
||||
}
|
||||
|
||||
// Root returns the root path
|
||||
func (f *FS) Root() (fs.Node, error) {
|
||||
return Object{
|
||||
fs: f,
|
||||
objType: ROOT,
|
||||
mtime: f.initTime,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package zfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
"github.com/debridmediamanager.com/zurg/internal/config"
|
||||
"github.com/debridmediamanager.com/zurg/internal/torrent"
|
||||
"github.com/debridmediamanager.com/zurg/pkg/chunk"
|
||||
"github.com/debridmediamanager.com/zurg/pkg/logutil"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func Mount(mountpoint string, cfg config.ConfigInterface, tMgr *torrent.TorrentManager, cMgr *chunk.Manager) error {
|
||||
rlog := logutil.NewLogger()
|
||||
log := rlog.Named("zfs")
|
||||
|
||||
options := []fuse.MountOption{
|
||||
fuse.AllowOther(),
|
||||
fuse.AllowNonEmptyMount(),
|
||||
fuse.MaxReadahead(uint32(128 << 10)),
|
||||
fuse.DefaultPermissions(),
|
||||
fuse.FSName("zurgfs"),
|
||||
}
|
||||
conn, err := fuse.Mount(mountpoint, options...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
srv := fs.New(conn, nil)
|
||||
|
||||
filesys := &FS{
|
||||
uid: uint32(unix.Geteuid()),
|
||||
gid: uint32(unix.Getegid()),
|
||||
umask: os.FileMode(0),
|
||||
c: cfg,
|
||||
t: tMgr,
|
||||
log: log,
|
||||
initTime: time.Now(),
|
||||
chunk: cMgr,
|
||||
}
|
||||
|
||||
if err := srv.Serve(filesys); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Unmount(mountpoint string) error {
|
||||
fuse.Unmount(mountpoint)
|
||||
return nil
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
package zfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse"
|
||||
"bazil.org/fuse/fs"
|
||||
"github.com/debridmediamanager.com/zurg/internal/torrent"
|
||||
)
|
||||
|
||||
// define variable as rootObject id
|
||||
const (
|
||||
ROOT = 0
|
||||
DIRECTORY = 1
|
||||
TORRENT = 2
|
||||
FILE = 3
|
||||
)
|
||||
|
||||
type Object struct {
|
||||
fs *FS
|
||||
objType int
|
||||
parentName string
|
||||
name string
|
||||
file *torrent.File
|
||||
size uint64
|
||||
mtime time.Time
|
||||
}
|
||||
|
||||
// Attr returns the attributes for a directory
|
||||
func (o Object) Attr(ctx context.Context, attr *fuse.Attr) error {
|
||||
if o.objType == FILE {
|
||||
attr.Mode = 0644
|
||||
} else {
|
||||
attr.Mode = os.ModeDir | 0755
|
||||
}
|
||||
attr.Size = o.size
|
||||
|
||||
attr.Uid = o.fs.uid
|
||||
attr.Gid = o.fs.gid
|
||||
|
||||
attr.Ctime = o.mtime
|
||||
attr.Mtime = o.mtime
|
||||
|
||||
attr.Blocks = (attr.Size + 511) >> 9
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadDirAll shows all files in the current directory
|
||||
func (o Object) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
|
||||
dirs := []fuse.Dirent{}
|
||||
switch o.objType {
|
||||
case ROOT:
|
||||
for _, directory := range o.fs.c.GetDirectories() {
|
||||
dirs = append(dirs, fuse.Dirent{
|
||||
Name: directory,
|
||||
Type: fuse.DT_Dir,
|
||||
})
|
||||
}
|
||||
case DIRECTORY:
|
||||
seen := make(map[string]bool)
|
||||
for _, item := range o.fs.t.GetByDirectory(o.name) {
|
||||
if item.Progress != 100 {
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[item.Name]; exists {
|
||||
continue
|
||||
}
|
||||
seen[item.Name] = true
|
||||
dirs = append(dirs, fuse.Dirent{
|
||||
Name: item.Name,
|
||||
Type: fuse.DT_Dir,
|
||||
})
|
||||
}
|
||||
case TORRENT:
|
||||
finalName := make(map[string]bool)
|
||||
for _, item := range o.fs.t.FindAllTorrentsWithName(o.parentName, o.name) {
|
||||
for _, file := range item.SelectedFiles {
|
||||
if file.Link == "" {
|
||||
// log.Println("File has no link, skipping", file.Path)
|
||||
continue
|
||||
}
|
||||
filename := filepath.Base(file.Path)
|
||||
if finalName[filename] {
|
||||
// fragment := davextra.GetLinkFragment(file.Link)
|
||||
// filename = davextra.InsertLinkFragment(filename, fragment)
|
||||
continue
|
||||
}
|
||||
finalName[filename] = true
|
||||
dirs = append(dirs, fuse.Dirent{
|
||||
Name: filename,
|
||||
Type: fuse.DT_File,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirs, nil
|
||||
}
|
||||
|
||||
// Lookup tests if a file is existent in the current directory
|
||||
func (o Object) Lookup(ctx context.Context, name string) (fs.Node, error) {
|
||||
switch o.objType {
|
||||
case ROOT:
|
||||
for _, directory := range o.fs.c.GetDirectories() {
|
||||
if directory == name {
|
||||
return Object{
|
||||
fs: o.fs,
|
||||
objType: DIRECTORY,
|
||||
parentName: o.name,
|
||||
name: name,
|
||||
mtime: o.fs.initTime,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
case DIRECTORY:
|
||||
for _, item := range o.fs.t.GetByDirectory(o.name) {
|
||||
if item.Name == name && item.Progress == 100 {
|
||||
return Object{
|
||||
fs: o.fs,
|
||||
objType: TORRENT,
|
||||
parentName: o.name,
|
||||
name: name,
|
||||
mtime: convertRFC3339toTime(item.Added),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
case TORRENT:
|
||||
for _, item := range o.fs.t.FindAllTorrentsWithName(o.parentName, o.name) {
|
||||
for _, file := range item.SelectedFiles {
|
||||
if strings.HasSuffix(file.Path, name) && file.Link != "" {
|
||||
return Object{
|
||||
fs: o.fs,
|
||||
objType: FILE,
|
||||
parentName: o.name,
|
||||
name: name,
|
||||
file: &file,
|
||||
size: uint64(file.Bytes),
|
||||
mtime: convertRFC3339toTime(item.Added),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, syscall.ENOENT
|
||||
}
|
||||
|
||||
// Open a file
|
||||
func (o Object) Open(ctx context.Context, req *fuse.OpenRequest, resp *fuse.OpenResponse) (fs.Handle, error) {
|
||||
resp.Flags |= fuse.OpenDirectIO
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// Read reads some bytes or the whole file
|
||||
func (o Object) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||
o.fs.log.Debugf("Read %s (total size %d) req offset %d req size %d", o.name, o.size, req.Offset, req.Size)
|
||||
data, err := o.fs.chunk.GetChunk(o.file, req.Offset, int64(req.Size))
|
||||
if nil != err {
|
||||
o.fs.log.Warnf("%v", err)
|
||||
return syscall.EIO
|
||||
}
|
||||
|
||||
resp.Data = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// Remove deletes an element
|
||||
func (o Object) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
|
||||
return fmt.Errorf("Remove not yet implemented")
|
||||
}
|
||||
|
||||
// Rename renames an element
|
||||
func (o Object) Rename(ctx context.Context, req *fuse.RenameRequest, newDir fs.Node) error {
|
||||
return fmt.Errorf("Rename not yet implemented")
|
||||
}
|
||||
|
||||
func convertRFC3339toTime(input string) time.Time {
|
||||
layout := "2006-01-02T15:04:05.000Z"
|
||||
t, err := time.Parse(layout, input)
|
||||
if err != nil {
|
||||
return time.Now()
|
||||
}
|
||||
return t
|
||||
}
|
||||
Reference in New Issue
Block a user