first commit
This commit is contained in:
156
fs/fs.go
Normal file
156
fs/fs.go
Normal file
@@ -0,0 +1,156 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/knusbaum/go9p/fs"
|
||||
"github.com/knusbaum/go9p/proto"
|
||||
|
||||
"storrent/client"
|
||||
)
|
||||
|
||||
type Dir struct {
|
||||
stat proto.Stat
|
||||
parent fs.Dir
|
||||
man *client.Manager
|
||||
fsys *fs.FS
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func New(e *client.Manager) *fs.FS {
|
||||
fsys, root := fs.NewFS("storrent", "storrent", 0555)
|
||||
root.AddChild(&fs.WrappedFile{
|
||||
File: fs.NewBaseFile(fsys.NewStat("ctl", "storrent", "storrent", 0222)),
|
||||
WriteF: func(fid uint64, offset uint64, data []byte) (uint32, error) {
|
||||
cmd := strings.TrimSpace(string(data))
|
||||
if strings.HasPrefix(cmd, "add ") {
|
||||
path := strings.TrimSpace(cmd[4:])
|
||||
_, err := e.Add(path)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(len(data)), nil
|
||||
}
|
||||
return 0, fmt.Errorf("unknown command: %s", cmd)
|
||||
},
|
||||
})
|
||||
|
||||
root.AddChild(fs.NewDynamicFile(
|
||||
fsys.NewStat("list", "storrent", "storrent", 0444),
|
||||
func() []byte {
|
||||
data := e.List()
|
||||
if len(data) > 0 {
|
||||
return append(data, '\n')
|
||||
}
|
||||
return data
|
||||
},
|
||||
))
|
||||
|
||||
dir := &Dir{
|
||||
stat: *fsys.NewStat("torrents", "storrent", "storrent", 0555|proto.DMDIR),
|
||||
man: e,
|
||||
fsys: fsys,
|
||||
}
|
||||
dir.stat.Qid.Qtype = uint8(dir.stat.Mode >> 24)
|
||||
root.AddChild(dir)
|
||||
return fsys
|
||||
}
|
||||
|
||||
func (d *Dir) Stat() proto.Stat {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
return d.stat
|
||||
}
|
||||
|
||||
func (d *Dir) WriteStat(s *proto.Stat) error {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
d.stat = *s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Dir) SetParent(p fs.Dir) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
d.parent = p
|
||||
}
|
||||
|
||||
func (d *Dir) Parent() fs.Dir {
|
||||
d.RLock()
|
||||
defer d.RUnlock()
|
||||
return d.parent
|
||||
}
|
||||
|
||||
func (d *Dir) Children() map[string]fs.FSNode {
|
||||
data := d.man.List()
|
||||
m := make(map[string]fs.FSNode)
|
||||
if len(data) == 0 {
|
||||
return m
|
||||
}
|
||||
for _, name := range strings.Split(string(data), "\n") {
|
||||
id, err := strconv.Atoi(name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
m[name] = d.newTorrentDir(id)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (d *Dir) newTorrentDir(id int) fs.FSNode {
|
||||
dir := fs.NewStaticDir(d.fsys.NewStat(strconv.Itoa(id), "storrent", "storrent", 0555))
|
||||
dir.AddChild(&fs.WrappedFile{
|
||||
File: fs.NewBaseFile(d.fsys.NewStat("ctl", "storrent", "storrent", 0222)),
|
||||
WriteF: func(fid uint64, offset uint64, data []byte) (uint32, error) {
|
||||
cmd := strings.TrimSpace(string(data))
|
||||
var err error
|
||||
switch {
|
||||
case cmd == "start":
|
||||
err = d.man.Start(id)
|
||||
case cmd == "stop":
|
||||
err = d.man.Stop(id)
|
||||
case cmd == "seed":
|
||||
err = d.man.Seed(id)
|
||||
case cmd == "remove":
|
||||
err = d.man.Remove(id)
|
||||
case strings.HasPrefix(cmd, "peer "):
|
||||
err = d.man.AddPeer(id, strings.TrimSpace(cmd[5:]))
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown command: %s", cmd)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint32(len(data)), nil
|
||||
},
|
||||
})
|
||||
|
||||
dir.AddChild(d.newStatusFile(id, "name"))
|
||||
dir.AddChild(d.newStatusFile(id, "state"))
|
||||
dir.AddChild(d.newStatusFile(id, "progress"))
|
||||
dir.AddChild(d.newStatusFile(id, "size"))
|
||||
dir.AddChild(d.newStatusFile(id, "down"))
|
||||
dir.AddChild(d.newStatusFile(id, "up"))
|
||||
dir.AddChild(d.newStatusFile(id, "pieces"))
|
||||
dir.AddChild(d.newStatusFile(id, "peers"))
|
||||
return dir
|
||||
}
|
||||
|
||||
func (d *Dir) newStatusFile(id int, field string) fs.FSNode {
|
||||
return fs.NewDynamicFile(
|
||||
d.fsys.NewStat(field, "storrent", "storrent", 0444),
|
||||
func() []byte {
|
||||
data, err := d.man.Status(id, field)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
if len(data) > 0 {
|
||||
return append(data, '\n')
|
||||
}
|
||||
return data
|
||||
},
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user