fs_sys.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. package projection //import "github.com/kpmy/mipfs/dav_ipfs/projection"
  2. import (
  3. "fmt"
  4. "github.com/kpmy/mipfs/dav_ipfs"
  5. "github.com/kpmy/mipfs/ipfs_api"
  6. "github.com/streamrail/concurrent-map"
  7. "golang.org/x/net/webdav"
  8. "io"
  9. "log"
  10. "os"
  11. "strings"
  12. "time"
  13. )
  14. const Active = true
  15. const Passive = false
  16. const ProjectionRoot = ".fs"
  17. type Extension interface {
  18. ConnectTo(root string)
  19. Open(chain []string) (webdav.File, error)
  20. os.FileInfo
  21. webdav.File
  22. }
  23. type item struct {
  24. name string
  25. }
  26. func (i *item) Size() int64 {
  27. return 0
  28. }
  29. func (i *item) Mode() os.FileMode {
  30. return 0
  31. }
  32. func (i *item) ModTime() time.Time {
  33. return time.Now()
  34. }
  35. func (i *item) IsDir() bool {
  36. return false
  37. }
  38. func (i *item) Sys() interface{} {
  39. return nil
  40. }
  41. func (i *item) Close() error {
  42. return nil
  43. }
  44. func (i *item) Read(p []byte) (n int, err error) {
  45. return 0, io.EOF
  46. }
  47. func (i *item) Seek(offset int64, whence int) (int64, error) {
  48. log.Println("seek")
  49. return 0, nil
  50. }
  51. func (i *item) Write(p []byte) (n int, err error) {
  52. return 0, webdav.ErrForbidden
  53. }
  54. func (i *item) Readdir(count int) (ret []os.FileInfo, err error) {
  55. return nil, webdav.ErrForbidden
  56. }
  57. func (i *item) Stat() (os.FileInfo, error) {
  58. return i, nil
  59. }
  60. func (i *item) Name() string {
  61. return i.name
  62. }
  63. type locator struct {
  64. }
  65. func (l *locator) Size() int64 {
  66. return 0
  67. }
  68. func (l *locator) Mode() os.FileMode {
  69. return os.ModeDir
  70. }
  71. func (l *locator) ModTime() time.Time {
  72. return time.Now()
  73. }
  74. func (l *locator) IsDir() bool {
  75. return true
  76. }
  77. func (l *locator) Sys() interface{} {
  78. return nil
  79. }
  80. func (l *locator) Close() error {
  81. return nil
  82. }
  83. func (l *locator) Read(p []byte) (n int, err error) {
  84. return 0, webdav.ErrForbidden
  85. }
  86. func (l *locator) Seek(offset int64, whence int) (int64, error) {
  87. return 0, webdav.ErrForbidden
  88. }
  89. func (l *locator) Write(p []byte) (n int, err error) {
  90. return 0, webdav.ErrForbidden
  91. }
  92. type ext struct {
  93. locator
  94. root string
  95. name string
  96. }
  97. func (e *ext) Name() string {
  98. return e.name
  99. }
  100. func (e *ext) Readdir(count int) (ret []os.FileInfo, err error) {
  101. log.Println(e.root)
  102. var ch <-chan string
  103. if ch, err = ipfs_api.Shell().Refs(e.root, true); err == nil {
  104. for s := range ch {
  105. ret = append(ret, &item{name: s})
  106. }
  107. }
  108. return
  109. }
  110. func (e *ext) Stat() (os.FileInfo, error) {
  111. return e, nil
  112. }
  113. func (e *ext) Open(chain []string) (ret webdav.File, err error) {
  114. if len(chain) == 1 {
  115. i := &item{name: chain[0]}
  116. ret = i
  117. } else {
  118. err = os.ErrPermission
  119. }
  120. return
  121. }
  122. func (e *ext) ConnectTo(root string) {
  123. e.root = root
  124. }
  125. type cat struct {
  126. locator
  127. pl map[string]Extension
  128. }
  129. func (c *cat) Name() string {
  130. return ProjectionRoot
  131. }
  132. func (c *cat) Readdir(count int) (ret []os.FileInfo, err error) {
  133. for _, v := range c.pl {
  134. ret = append(ret, v)
  135. }
  136. return
  137. }
  138. func (c *cat) Stat() (os.FileInfo, error) {
  139. return c, nil
  140. }
  141. type projection struct {
  142. inner webdav.FileSystem
  143. root string
  144. cache cmap.ConcurrentMap
  145. all *cat
  146. set func(string)
  147. get func() string
  148. }
  149. func isProjection(split []string) bool {
  150. return strings.ToLower(split[0]) == ProjectionRoot
  151. }
  152. func (p *projection) Mkdir(name string, perm os.FileMode) (err error) {
  153. ls := splitPath(name)
  154. switch {
  155. case len(ls) > 1 && isProjection(ls):
  156. err = os.ErrPermission
  157. case len(ls) == 1 && isProjection(ls):
  158. err = p.inner.Mkdir(strings.ToLower(name), perm)
  159. default:
  160. err = p.inner.Mkdir(name, perm)
  161. }
  162. return
  163. }
  164. func (p *projection) OpenFile(name string, flag int, perm os.FileMode) (ret webdav.File, err error) {
  165. log.Println("open", name)
  166. ls := splitPath(name)
  167. switch {
  168. case isProjection(ls) && len(ls) == 1:
  169. ret = p.all
  170. case isProjection(ls) && len(ls) > 1:
  171. if e, ok := p.all.pl[ls[1]]; ok {
  172. e.ConnectTo(p.root)
  173. if len(ls) > 2 {
  174. ret, err = e.Open(ls[2:])
  175. } else {
  176. ret = e
  177. }
  178. } else {
  179. err = os.ErrNotExist
  180. }
  181. default:
  182. ret, err = p.inner.OpenFile(name, flag, perm)
  183. }
  184. return
  185. }
  186. func (p *projection) RemoveAll(name string) (err error) {
  187. ls := splitPath(name)
  188. switch {
  189. case isProjection(ls):
  190. err = os.ErrPermission
  191. default:
  192. err = p.inner.RemoveAll(name)
  193. }
  194. return
  195. }
  196. func (p *projection) Rename(oldName, newName string) (err error) {
  197. ls := splitPath(oldName)
  198. switch {
  199. case isProjection(ls):
  200. err = os.ErrPermission
  201. default:
  202. err = p.inner.Rename(oldName, newName)
  203. }
  204. return
  205. }
  206. func (p *projection) Stat(name string) (fi os.FileInfo, err error) {
  207. log.Println("stat", name)
  208. ls := splitPath(name)
  209. switch {
  210. case isProjection(ls):
  211. fi = &cat{}
  212. default:
  213. fi, err = p.inner.Stat(name)
  214. }
  215. return
  216. }
  217. func (p *projection) String() string {
  218. return fmt.Sprint(p.inner)
  219. }
  220. func NewPS(get func() string, set func(string), active bool) (fs webdav.FileSystem, ls webdav.LockSystem) {
  221. var pr *projection
  222. if active {
  223. pr = &projection{get: get}
  224. pr.set = func(hash string) {
  225. pr.root = hash
  226. set(hash)
  227. }
  228. xs := dav_ipfs.NewFS(pr.get, pr.set)
  229. ls = dav_ipfs.NewLS(xs)
  230. pr.inner = xs
  231. pr.cache = cmap.New()
  232. pr.all = &cat{}
  233. pr.all.pl = map[string]Extension{"all": &ext{name: "all"}}
  234. fs = pr
  235. } else {
  236. xs := dav_ipfs.NewFS(get, set)
  237. ls = dav_ipfs.NewLS(xs)
  238. fs = xs
  239. }
  240. return
  241. }