123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- package projection //import "github.com/kpmy/mipfs/dav_ipfs/projection"
- import (
- "fmt"
- "github.com/kpmy/mipfs/dav_ipfs"
- "github.com/kpmy/mipfs/ipfs_api"
- "github.com/streamrail/concurrent-map"
- "golang.org/x/net/webdav"
- "io"
- "log"
- "os"
- "strings"
- "time"
- )
- const Active = true
- const Passive = false
- const ProjectionRoot = ".fs"
- type Extension interface {
- ConnectTo(root string)
- Open(chain []string) (webdav.File, error)
- os.FileInfo
- webdav.File
- }
- type item struct {
- name string
- }
- func (i *item) Size() int64 {
- return 0
- }
- func (i *item) Mode() os.FileMode {
- return 0
- }
- func (i *item) ModTime() time.Time {
- return time.Now()
- }
- func (i *item) IsDir() bool {
- return false
- }
- func (i *item) Sys() interface{} {
- return nil
- }
- func (i *item) Close() error {
- return nil
- }
- func (i *item) Read(p []byte) (n int, err error) {
- return 0, io.EOF
- }
- func (i *item) Seek(offset int64, whence int) (int64, error) {
- log.Println("seek")
- return 0, nil
- }
- func (i *item) Write(p []byte) (n int, err error) {
- return 0, webdav.ErrForbidden
- }
- func (i *item) Readdir(count int) (ret []os.FileInfo, err error) {
- return nil, webdav.ErrForbidden
- }
- func (i *item) Stat() (os.FileInfo, error) {
- return i, nil
- }
- func (i *item) Name() string {
- return i.name
- }
- type locator struct {
- }
- func (l *locator) Size() int64 {
- return 0
- }
- func (l *locator) Mode() os.FileMode {
- return os.ModeDir
- }
- func (l *locator) ModTime() time.Time {
- return time.Now()
- }
- func (l *locator) IsDir() bool {
- return true
- }
- func (l *locator) Sys() interface{} {
- return nil
- }
- func (l *locator) Close() error {
- return nil
- }
- func (l *locator) Read(p []byte) (n int, err error) {
- return 0, webdav.ErrForbidden
- }
- func (l *locator) Seek(offset int64, whence int) (int64, error) {
- return 0, webdav.ErrForbidden
- }
- func (l *locator) Write(p []byte) (n int, err error) {
- return 0, webdav.ErrForbidden
- }
- type ext struct {
- locator
- root string
- name string
- }
- func (e *ext) Name() string {
- return e.name
- }
- func (e *ext) Readdir(count int) (ret []os.FileInfo, err error) {
- log.Println(e.root)
- var ch <-chan string
- if ch, err = ipfs_api.Shell().Refs(e.root, true); err == nil {
- for s := range ch {
- ret = append(ret, &item{name: s})
- }
- }
- return
- }
- func (e *ext) Stat() (os.FileInfo, error) {
- return e, nil
- }
- func (e *ext) Open(chain []string) (ret webdav.File, err error) {
- if len(chain) == 1 {
- i := &item{name: chain[0]}
- ret = i
- } else {
- err = os.ErrPermission
- }
- return
- }
- func (e *ext) ConnectTo(root string) {
- e.root = root
- }
- type cat struct {
- locator
- pl map[string]Extension
- }
- func (c *cat) Name() string {
- return ProjectionRoot
- }
- func (c *cat) Readdir(count int) (ret []os.FileInfo, err error) {
- for _, v := range c.pl {
- ret = append(ret, v)
- }
- return
- }
- func (c *cat) Stat() (os.FileInfo, error) {
- return c, nil
- }
- type projection struct {
- inner webdav.FileSystem
- root string
- cache cmap.ConcurrentMap
- all *cat
- set func(string)
- get func() string
- }
- func isProjection(split []string) bool {
- return strings.ToLower(split[0]) == ProjectionRoot
- }
- func (p *projection) Mkdir(name string, perm os.FileMode) (err error) {
- ls := splitPath(name)
- switch {
- case len(ls) > 1 && isProjection(ls):
- err = os.ErrPermission
- case len(ls) == 1 && isProjection(ls):
- err = p.inner.Mkdir(strings.ToLower(name), perm)
- default:
- err = p.inner.Mkdir(name, perm)
- }
- return
- }
- func (p *projection) OpenFile(name string, flag int, perm os.FileMode) (ret webdav.File, err error) {
- log.Println("open", name)
- ls := splitPath(name)
- switch {
- case isProjection(ls) && len(ls) == 1:
- ret = p.all
- case isProjection(ls) && len(ls) > 1:
- if e, ok := p.all.pl[ls[1]]; ok {
- e.ConnectTo(p.root)
- if len(ls) > 2 {
- ret, err = e.Open(ls[2:])
- } else {
- ret = e
- }
- } else {
- err = os.ErrNotExist
- }
- default:
- ret, err = p.inner.OpenFile(name, flag, perm)
- }
- return
- }
- func (p *projection) RemoveAll(name string) (err error) {
- ls := splitPath(name)
- switch {
- case isProjection(ls):
- err = os.ErrPermission
- default:
- err = p.inner.RemoveAll(name)
- }
- return
- }
- func (p *projection) Rename(oldName, newName string) (err error) {
- ls := splitPath(oldName)
- switch {
- case isProjection(ls):
- err = os.ErrPermission
- default:
- err = p.inner.Rename(oldName, newName)
- }
- return
- }
- func (p *projection) Stat(name string) (fi os.FileInfo, err error) {
- log.Println("stat", name)
- ls := splitPath(name)
- switch {
- case isProjection(ls):
- fi = &cat{}
- default:
- fi, err = p.inner.Stat(name)
- }
- return
- }
- func (p *projection) String() string {
- return fmt.Sprint(p.inner)
- }
- func NewPS(get func() string, set func(string), active bool) (fs webdav.FileSystem, ls webdav.LockSystem) {
- var pr *projection
- if active {
- pr = &projection{get: get}
- pr.set = func(hash string) {
- pr.root = hash
- set(hash)
- }
- xs := dav_ipfs.NewFS(pr.get, pr.set)
- ls = dav_ipfs.NewLS(xs)
- pr.inner = xs
- pr.cache = cmap.New()
- pr.all = &cat{}
- pr.all.pl = map[string]Extension{"all": &ext{name: "all"}}
- fs = pr
- } else {
- xs := dav_ipfs.NewFS(get, set)
- ls = dav_ipfs.NewLS(xs)
- fs = xs
- }
- return
- }
|