localfs.go 7.0 KB

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