fshAdapter.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package webdav
  2. import (
  3. "bytes"
  4. "context"
  5. "errors"
  6. "io/fs"
  7. "log"
  8. "os"
  9. "imuslab.com/arozos/mod/filesystem"
  10. "imuslab.com/arozos/mod/filesystem/arozfs"
  11. "imuslab.com/arozos/mod/network/webdav"
  12. )
  13. type FshWebDAVAdapter struct {
  14. fsh *filesystem.FileSystemHandler
  15. username string
  16. }
  17. type BufferFsIoHandler struct {
  18. fsa filesystem.FileSystemAbstraction
  19. realpath string
  20. filebytes []byte
  21. reader *bytes.Reader
  22. }
  23. func (b BufferFsIoHandler) Close() error {
  24. return nil
  25. }
  26. func newBufferFsIoHandler(fsa filesystem.FileSystemAbstraction, realpath string) (*BufferFsIoHandler, error) {
  27. if !fsa.FileExists(realpath) {
  28. return nil, os.ErrExist
  29. }
  30. b := BufferFsIoHandler{
  31. fsa: fsa,
  32. realpath: realpath,
  33. filebytes: []byte{},
  34. reader: nil,
  35. }
  36. s, err := b.fsa.Stat(b.realpath)
  37. if err != nil {
  38. return nil, err
  39. }
  40. if s.Size() > int64(28<<20) {
  41. //Larger than 28MB, do not allow buffering
  42. return nil, errors.New("file too large")
  43. }
  44. //Buffer remote file to local and store it in file bytes
  45. if !s.IsDir() {
  46. c, err := b.fsa.ReadFile(b.realpath)
  47. if err != nil {
  48. return nil, err
  49. }
  50. b.filebytes = c
  51. b.reader = bytes.NewReader(b.filebytes)
  52. }
  53. return &b, nil
  54. }
  55. func (b BufferFsIoHandler) Read(p []byte) (n int, err error) {
  56. //fmt.Println("READ", b.realpath)
  57. return b.reader.Read(p)
  58. }
  59. func (b BufferFsIoHandler) Seek(offset int64, whence int) (int64, error) {
  60. //fmt.Println("SEEK", b.realpath)
  61. return b.reader.Seek(offset, whence)
  62. }
  63. func (b BufferFsIoHandler) Readdir(count int) ([]fs.FileInfo, error) {
  64. //fmt.Println("READDIR", b.realpath)
  65. de, err := b.fsa.ReadDir(b.realpath)
  66. if err != nil {
  67. return []fs.FileInfo{}, err
  68. }
  69. if len(de) < count {
  70. de = de[:count]
  71. }
  72. results := []fs.FileInfo{}
  73. for _, e := range de {
  74. i, err := e.Info()
  75. if err != nil {
  76. continue
  77. }
  78. results = append(results, i)
  79. }
  80. return results, nil
  81. }
  82. func (b BufferFsIoHandler) Stat() (fs.FileInfo, error) {
  83. //fmt.Println("FSTAT", b.realpath)
  84. return b.fsa.Stat(b.realpath)
  85. }
  86. func (b BufferFsIoHandler) Write(p []byte) (n int, err error) {
  87. //fmt.Println("WRITE", b.realpath)
  88. r := bytes.NewReader(p)
  89. err = b.fsa.WriteStream(b.realpath, r, 0777)
  90. if err != nil {
  91. return 0, err
  92. }
  93. return len(p), nil
  94. }
  95. func NewFshWebDAVAdapter(fsh *filesystem.FileSystemHandler, username string) *FshWebDAVAdapter {
  96. return &FshWebDAVAdapter{
  97. fsh,
  98. username,
  99. }
  100. }
  101. func (a *FshWebDAVAdapter) requestPathToRealPath(name string) (string, error) {
  102. if len(name) == 0 || name[0:1] != "/" {
  103. name = "/" + name
  104. }
  105. fullVpath := a.fsh.UUID + ":" + name
  106. realRequestPath, err := a.fsh.FileSystemAbstraction.VirtualPathToRealPath(fullVpath, a.username)
  107. if err != nil {
  108. return "", err
  109. }
  110. realRequestPath = arozfs.ToSlash(realRequestPath)
  111. return realRequestPath, nil
  112. }
  113. func (a *FshWebDAVAdapter) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
  114. realRequestPath, err := a.requestPathToRealPath(name)
  115. if err != nil {
  116. return err
  117. }
  118. return a.fsh.FileSystemAbstraction.Mkdir(realRequestPath, perm)
  119. }
  120. func (a *FshWebDAVAdapter) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
  121. //The name come in as the relative path of the request vpath (e.g. user:/Video/test.mp4 will get requested as /Video/test.mp4)
  122. //Merge it into a proper vpath and perform abstraction path translation
  123. realRequestPath, err := a.requestPathToRealPath(name)
  124. if err != nil {
  125. log.Println(err)
  126. return nil, err
  127. }
  128. if a.fsh.RequireBuffer {
  129. //Buffer the remote content to local for access
  130. return newBufferFsIoHandler(a.fsh.FileSystemAbstraction, realRequestPath)
  131. } else {
  132. return a.fsh.FileSystemAbstraction.OpenFile(realRequestPath, flag, perm)
  133. }
  134. }
  135. func (a *FshWebDAVAdapter) RemoveAll(ctx context.Context, name string) error {
  136. realRequestPath, err := a.requestPathToRealPath(name)
  137. if err != nil {
  138. return err
  139. }
  140. return a.fsh.FileSystemAbstraction.RemoveAll(realRequestPath)
  141. }
  142. func (a *FshWebDAVAdapter) Rename(ctx context.Context, oldName, newName string) error {
  143. realOldname, err := a.requestPathToRealPath(oldName)
  144. if err != nil {
  145. return err
  146. }
  147. realNewname, err := a.requestPathToRealPath(newName)
  148. if err != nil {
  149. return err
  150. }
  151. return a.fsh.FileSystemAbstraction.Rename(realOldname, realNewname)
  152. }
  153. func (a *FshWebDAVAdapter) Stat(ctx context.Context, name string) (os.FileInfo, error) {
  154. realRequestPath, err := a.requestPathToRealPath(name)
  155. if err != nil {
  156. return nil, err
  157. }
  158. s, e := a.fsh.FileSystemAbstraction.Stat(realRequestPath)
  159. //fmt.Println("STAT ", realRequestPath, s, e)
  160. return s, e
  161. }