Add fuse mount without read
This commit is contained in:
@@ -19,7 +19,7 @@ import (
|
||||
|
||||
func main() {
|
||||
rlog := logutil.NewLogger()
|
||||
log := rlog.Named("main")
|
||||
log := rlog.Named("zurg")
|
||||
|
||||
config, configErr := config.LoadZurgConfig("./config.yml")
|
||||
if configErr != nil {
|
||||
@@ -66,7 +66,7 @@ func main() {
|
||||
}
|
||||
}()
|
||||
log.Infof("Mounting on %s", mountPoint)
|
||||
if err := zfs.Mount(mountPoint); err != nil {
|
||||
if err := zfs.Mount(mountPoint, config, t); err != nil {
|
||||
log.Panicf("Failed to mount: %v", err)
|
||||
}
|
||||
}()
|
||||
@@ -83,5 +83,5 @@ func main() {
|
||||
log.Errorf("Unmount error: %v\n", err)
|
||||
}
|
||||
|
||||
log.Info("Zurg signing off")
|
||||
log.Info("BYE")
|
||||
}
|
||||
|
||||
11
go.mod
11
go.mod
@@ -3,14 +3,11 @@ module github.com/debridmediamanager.com/zurg
|
||||
go 1.21.3
|
||||
|
||||
require (
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/sys v0.4.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 // indirect
|
||||
github.com/mdlayher/sdnotify v1.0.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
)
|
||||
require go.uber.org/multierr v1.10.0 // indirect
|
||||
|
||||
16
go.sum
16
go.sum
@@ -1,11 +1,19 @@
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5 h1:A0NsYy4lDBZAC6QiYeJ4N+XuHIKBpyhAVRMHRQZKTeQ=
|
||||
bazil.org/fuse v0.0.0-20230120002735-62a210ff1fd5/go.mod h1:gG3RZAMXCa/OTes6rr9EwusmR1OH1tDDy+cg9c5YliY=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ3c=
|
||||
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c h1:u6SKchux2yDvFQnDHS3lPnIRmfVJ5Sxy3ao2SIdysLQ=
|
||||
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
|
||||
@@ -3,8 +3,12 @@ package zfs
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"bazil.org/fuse/fs"
|
||||
"github.com/debridmediamanager.com/zurg/internal/config"
|
||||
"github.com/debridmediamanager.com/zurg/internal/torrent"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type FS struct {
|
||||
@@ -13,9 +17,17 @@ type FS struct {
|
||||
umask os.FileMode
|
||||
directIO bool
|
||||
lock sync.RWMutex
|
||||
c config.ConfigInterface
|
||||
t *torrent.TorrentManager
|
||||
log *zap.SugaredLogger
|
||||
initTime time.Time
|
||||
}
|
||||
|
||||
// Root returns the root path
|
||||
func (f *FS) Root() (fs.Node, error) {
|
||||
return nil, nil
|
||||
return Object{
|
||||
fs: f,
|
||||
objType: ROOT,
|
||||
mtime: f.initTime,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2,14 +2,21 @@ 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/logutil"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func Mount(mountpoint string) error {
|
||||
func Mount(mountpoint string, c config.ConfigInterface, t *torrent.TorrentManager) error {
|
||||
rlog := logutil.NewLogger()
|
||||
log := rlog.Named("zfs")
|
||||
|
||||
options := []fuse.MountOption{
|
||||
fuse.AllowOther(),
|
||||
fuse.AllowNonEmptyMount(),
|
||||
@@ -17,21 +24,24 @@ func Mount(mountpoint string) error {
|
||||
fuse.DefaultPermissions(),
|
||||
fuse.FSName("zurgfs"),
|
||||
}
|
||||
c, err := fuse.Mount(mountpoint, options...)
|
||||
conn, err := fuse.Mount(mountpoint, options...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer c.Close()
|
||||
defer conn.Close()
|
||||
|
||||
srv := fs.New(c, nil)
|
||||
srv := fs.New(conn, nil)
|
||||
|
||||
filesys := &FS{
|
||||
uid: uint32(unix.Geteuid()),
|
||||
gid: uint32(unix.Getegid()),
|
||||
umask: os.FileMode(0),
|
||||
uid: uint32(unix.Geteuid()),
|
||||
gid: uint32(unix.Getegid()),
|
||||
umask: os.FileMode(0),
|
||||
c: c,
|
||||
t: t,
|
||||
log: log,
|
||||
initTime: time.Now(),
|
||||
}
|
||||
|
||||
// Serve our tree via FUSE.
|
||||
if err := srv.Serve(filesys); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,49 +2,177 @@ 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
|
||||
objectID string
|
||||
}
|
||||
|
||||
func (o Object) GetObject() (object *torrent.Torrent, err error) {
|
||||
return nil, nil
|
||||
fs *FS
|
||||
objType int
|
||||
parentName string
|
||||
name string
|
||||
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) {
|
||||
return nil, nil
|
||||
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) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (o Object) Read(ctx context.Context, req *fuse.ReadRequest, resp *fuse.ReadResponse) error {
|
||||
return nil
|
||||
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,
|
||||
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) {
|
||||
return nil, nil
|
||||
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 {
|
||||
return fmt.Errorf("Read not yet implemented")
|
||||
}
|
||||
|
||||
// Remove deletes an element
|
||||
func (o Object) Remove(ctx context.Context, req *fuse.RemoveRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o Object) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
|
||||
return nil, nil
|
||||
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 nil
|
||||
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