localfs.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package localfs
  2. import (
  3. "errors"
  4. "io"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "time"
  10. "imuslab.com/arozos/mod/common"
  11. )
  12. /*
  13. filesystemAbstraction.go
  14. This file contains all the abstraction funtion of a local file system.
  15. */
  16. type LocalFileSystemAbstraction struct {
  17. UUID string
  18. Rootpath string
  19. Hierarchy string
  20. ReadOnly bool
  21. }
  22. func NewLocalFileSystemAbstraction(uuid, root, hierarchy string, readonly bool) LocalFileSystemAbstraction {
  23. return LocalFileSystemAbstraction{
  24. UUID: uuid,
  25. Rootpath: root,
  26. Hierarchy: hierarchy,
  27. ReadOnly: readonly,
  28. }
  29. }
  30. func (l LocalFileSystemAbstraction) Chmod(filename string, mode os.FileMode) error {
  31. return os.Chmod(filename, mode)
  32. }
  33. func (l LocalFileSystemAbstraction) Chown(filename string, uid int, gid int) error {
  34. return os.Chown(filename, uid, gid)
  35. }
  36. func (l LocalFileSystemAbstraction) Chtimes(filename string, atime time.Time, mtime time.Time) error {
  37. return os.Chtimes(filename, atime, mtime)
  38. }
  39. func (l LocalFileSystemAbstraction) Create(filename string) (*os.File, error) {
  40. return os.Create(filename)
  41. }
  42. func (l LocalFileSystemAbstraction) Mkdir(filename string, mode os.FileMode) error {
  43. return os.Mkdir(filename, mode)
  44. }
  45. func (l LocalFileSystemAbstraction) MkdirAll(filename string, mode os.FileMode) error {
  46. return os.MkdirAll(filename, mode)
  47. }
  48. func (l LocalFileSystemAbstraction) Name() string {
  49. return ""
  50. }
  51. func (l LocalFileSystemAbstraction) Open(filename string) (*os.File, error) {
  52. return os.Open(filename)
  53. }
  54. func (l LocalFileSystemAbstraction) OpenFile(filename string, flag int, perm os.FileMode) (*os.File, error) {
  55. return os.OpenFile(filename, flag, perm)
  56. }
  57. func (l LocalFileSystemAbstraction) Remove(filename string) error {
  58. return os.Remove(filename)
  59. }
  60. func (l LocalFileSystemAbstraction) RemoveAll(path string) error {
  61. return os.RemoveAll(path)
  62. }
  63. func (l LocalFileSystemAbstraction) Rename(oldname, newname string) error {
  64. return os.Rename(oldname, newname)
  65. }
  66. func (l LocalFileSystemAbstraction) Stat(filename string) (os.FileInfo, error) {
  67. return os.Stat(filename)
  68. }
  69. /*
  70. Abstraction Utilities
  71. */
  72. func (l LocalFileSystemAbstraction) VirtualPathToRealPath(subpath string, username string) (string, error) {
  73. subpath = filepath.ToSlash(subpath)
  74. if strings.HasPrefix(subpath, l.UUID+":") {
  75. //This is full virtual path. Trim the uuid and correct the subpath
  76. subpath = subpath[len(l.UUID+":"):]
  77. }
  78. if l.Hierarchy == "user" {
  79. return filepath.ToSlash(filepath.Join(l.Rootpath, "users", username, subpath)), nil
  80. } else if l.Hierarchy == "public" {
  81. return filepath.ToSlash(filepath.Join(l.Rootpath, subpath)), nil
  82. }
  83. return "", errors.New("unsupported filesystem hierarchy")
  84. }
  85. func (l LocalFileSystemAbstraction) RealPathToVirtualPath(fullpath string, username string) (string, error) {
  86. /*
  87. thisStorageRootAbs, err := filepath.Abs(l.Rootpath)
  88. if err != nil {
  89. //Fail to abs this path. Maybe this is a emulated file system?
  90. thisStorageRootAbs = l.Rootpath
  91. }
  92. thisStorageRootAbs = filepath.ToSlash(filepath.Clean(thisStorageRootAbs))
  93. subPath := ""
  94. if len(fullpath) > len(l.Rootpath) && filepath.ToSlash(fullpath[:len(l.Rootpath)]) == filepath.ToSlash(l.Rootpath) {
  95. //This realpath is in contained inside this storage root
  96. subtractionPath := l.Rootpath
  97. if l.Hierarchy == "user" {
  98. //Check if this file is belongs to this user
  99. startOffset := len(filepath.Clean(l.Rootpath) + "/users/")
  100. if len(fullpath) < startOffset+len(username) {
  101. //This file is not owned by this user
  102. return "", errors.New("File not owned by this user")
  103. } else {
  104. userNameMatch := fullpath[startOffset : startOffset+len(username)]
  105. if userNameMatch != username {
  106. //This file is not owned by this user
  107. return "", errors.New("File not owned by this user")
  108. }
  109. }
  110. //Generate subtraction path
  111. subtractionPath = filepath.ToSlash(filepath.Clean(filepath.Join(l.Rootpath, "users", username)))
  112. }
  113. if len(subtractionPath) < len(fullpath) {
  114. subPath = fullpath[len(subtractionPath):]
  115. }
  116. } else if len(fullpath) > len(thisStorageRootAbs) && filepath.ToSlash(fullpath[:len(thisStorageRootAbs)]) == filepath.ToSlash(thisStorageRootAbs) {
  117. //The realpath contains the absolute path of this storage root
  118. subtractionPath := thisStorageRootAbs
  119. if l.Hierarchy == "user" {
  120. subtractionPath = thisStorageRootAbs + "/users/" + username + "/"
  121. }
  122. if len(subtractionPath) < len(fullpath) {
  123. subPath = fullpath[len(subtractionPath):]
  124. }
  125. } else if filepath.ToSlash(fullpath) == filepath.ToSlash(l.Rootpath) {
  126. //Storage Root's root
  127. subPath = ""
  128. }
  129. if len(subPath) > 1 && subPath[:1] == "/" {
  130. subPath = subPath[1:]
  131. }
  132. */
  133. fullpath = filepath.ToSlash(fullpath)
  134. if strings.HasPrefix(fullpath, l.UUID+":") && !common.FileExists(fullpath) {
  135. return "", errors.New("invalid usage: Given path is vpath")
  136. }
  137. prefix := filepath.ToSlash(filepath.Join(l.Rootpath, "users", username))
  138. if l.Hierarchy == "public" {
  139. prefix = filepath.ToSlash(l.Rootpath)
  140. }
  141. fullpath = filepath.ToSlash(filepath.Clean(fullpath))
  142. subPath := strings.TrimPrefix(fullpath, prefix)
  143. return l.UUID + ":" + filepath.ToSlash(subPath), nil
  144. }
  145. func (l LocalFileSystemAbstraction) FileExists(realpath string) bool {
  146. return common.FileExists(realpath)
  147. }
  148. func (l LocalFileSystemAbstraction) IsDir(realpath string) bool {
  149. if !l.FileExists(realpath) {
  150. return false
  151. }
  152. fi, err := l.Stat(realpath)
  153. if err != nil {
  154. log.Fatal(err)
  155. return false
  156. }
  157. switch mode := fi.Mode(); {
  158. case mode.IsDir():
  159. return true
  160. case mode.IsRegular():
  161. return false
  162. }
  163. return false
  164. }
  165. func (l LocalFileSystemAbstraction) Glob(realpathWildcard string) ([]string, error) {
  166. return filepath.Glob(realpathWildcard)
  167. }
  168. func (l LocalFileSystemAbstraction) GetFileSize(realpath string) int64 {
  169. fi, err := os.Stat(realpath)
  170. if err != nil {
  171. return 0
  172. }
  173. // get the size
  174. return fi.Size()
  175. }
  176. func (l LocalFileSystemAbstraction) GetModTime(realpath string) (int64, error) {
  177. f, err := os.Open(realpath)
  178. if err != nil {
  179. return -1, err
  180. }
  181. statinfo, err := f.Stat()
  182. if err != nil {
  183. return -1, err
  184. }
  185. f.Close()
  186. return statinfo.ModTime().Unix(), nil
  187. }
  188. func (l LocalFileSystemAbstraction) WriteFile(filename string, content []byte, mode os.FileMode) error {
  189. return os.WriteFile(filename, content, mode)
  190. }
  191. func (l LocalFileSystemAbstraction) ReadFile(filename string) ([]byte, error) {
  192. return os.ReadFile(filename)
  193. }
  194. func (l LocalFileSystemAbstraction) WriteStream(filename string, stream io.Reader, mode os.FileMode) error {
  195. f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, mode)
  196. if err != nil {
  197. return err
  198. }
  199. _, err = io.Copy(f, stream)
  200. f.Close()
  201. return err
  202. }
  203. func (l LocalFileSystemAbstraction) ReadStream(filename string) (io.ReadCloser, error) {
  204. f, err := os.OpenFile(filename, os.O_RDONLY, 0644)
  205. if err != nil {
  206. return nil, err
  207. }
  208. return f, nil
  209. }
  210. func (l LocalFileSystemAbstraction) Walk(root string, walkFn filepath.WalkFunc) error {
  211. return filepath.Walk(root, walkFn)
  212. }