directoryHandler.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package user
  2. import (
  3. "errors"
  4. "log"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. fs "imuslab.com/arozos/mod/filesystem"
  9. )
  10. func (u *User) GetHomeDirectory() (string, error) {
  11. //Return the realpath of the user home directory
  12. for _, dir := range u.HomeDirectories.Storages {
  13. if dir.UUID == "user" {
  14. //This is the target user root
  15. root := filepath.ToSlash(filepath.Clean(dir.Path) + "/users/" + u.Username + "/")
  16. os.MkdirAll(root, 0755)
  17. return root, nil
  18. }
  19. }
  20. return "", errors.New("User root not found. Is this a permission group instead of a real user?")
  21. }
  22. func (u *User) GetAllFileSystemHandler() []*fs.FileSystemHandler {
  23. results := []*fs.FileSystemHandler{}
  24. uuids := []string{}
  25. //Get all FileSystem Handler from this user's Home Directory (aka base directory)
  26. for _, store := range u.HomeDirectories.Storages {
  27. if store.Closed == false {
  28. //Only return opened file system handlers
  29. results = append(results, store)
  30. uuids = append(uuids, store.UUID)
  31. }
  32. }
  33. //Get all the FileSystem handler that is accessable by this user
  34. for _, pg := range u.PermissionGroup {
  35. //For each permission group that this user is in
  36. for _, store := range pg.StoragePool.Storages {
  37. //Get each of the storage of this permission group is assigned to
  38. if !inSlice(uuids, store.UUID) {
  39. if store.Closed == false {
  40. //Only return opened file system handlers
  41. results = append(results, store)
  42. uuids = append(uuids, store.UUID)
  43. }
  44. }
  45. }
  46. }
  47. return results
  48. }
  49. func (u *User) VirtualPathToRealPath(vpath string) (string, error) {
  50. //Get all usable filesystem handler from the user's home directory and permission groups
  51. userFsHandlers := u.GetAllFileSystemHandler()
  52. //Clear the path
  53. virtualPath := filepath.ToSlash(filepath.Clean(vpath))
  54. //Check for path escape
  55. if len(virtualPath) > 2 && virtualPath[:2] == ".." {
  56. return "", errors.New("Request path out of storage root")
  57. }
  58. //Check for valid virtual device id
  59. vid, subpath, err := getIDFromVirtualPath(vpath)
  60. if err != nil {
  61. return "", err
  62. }
  63. //Look for the handler with the same virtualPath ID
  64. for _, storage := range userFsHandlers {
  65. if storage.UUID == vid {
  66. //This storage is the one we are looking at
  67. //Check if this has been closed
  68. if storage.Closed == true {
  69. return "", errors.New("Request Filesystem Handler has been closed by another process")
  70. }
  71. if storage.Hierarchy == "user" {
  72. return filepath.ToSlash(filepath.Clean(storage.Path) + "/users/" + u.Username + subpath), nil
  73. } else {
  74. return filepath.ToSlash(filepath.Clean(storage.Path) + subpath), nil
  75. }
  76. }
  77. }
  78. return "", errors.New("Translation failed: Vitrual storage ID not found")
  79. }
  80. func (u *User) RealPathToVirtualPath(rpath string) (string, error) {
  81. //Get all usable filesystem handler
  82. userFsHandlers := u.GetAllFileSystemHandler()
  83. //Clear the path
  84. realPath := filepath.ToSlash(filepath.Clean(rpath))
  85. //Check for path escape
  86. if len(realPath) > 2 && realPath[:2] == ".." {
  87. //Fix: 20 May 2021: Allow using ../folder as virtual root directory
  88. //Check if there are vroots that actually use relative path as root directory.
  89. allowSpecialCasePassThrough := false
  90. for _, fsh := range userFsHandlers {
  91. thisVrootPath := fsh.Path
  92. log.Println(filepath.ToSlash(realPath[:len(thisVrootPath)]), thisVrootPath)
  93. if len(realPath) > len(thisVrootPath) && filepath.ToSlash(realPath[:len(thisVrootPath)]) == filepath.ToSlash(thisVrootPath) {
  94. allowSpecialCasePassThrough = true
  95. }
  96. }
  97. if !allowSpecialCasePassThrough {
  98. return "", errors.New("Request path out of storage root")
  99. }
  100. }
  101. //Look for a real path of a virtual device that the realpath is containing
  102. for _, storage := range userFsHandlers {
  103. thisStorageRoot := filepath.Clean(filepath.ToSlash(storage.Path))
  104. thisStorageRootAbs, err := filepath.Abs(thisStorageRoot)
  105. if err != nil {
  106. //Fail to abs this path. Maybe this is a emulated file system?
  107. thisStorageRootAbs = thisStorageRoot
  108. }
  109. thisStorageRootAbs = filepath.ToSlash(filepath.Clean(thisStorageRootAbs))
  110. pathContained := false
  111. subPath := ""
  112. if len(realPath) > len(thisStorageRoot) && filepath.ToSlash(realPath[:len(thisStorageRoot)]) == filepath.ToSlash(thisStorageRoot) {
  113. //This realpath is in contained inside this storage root
  114. pathContained = true
  115. subtractionPath := thisStorageRoot
  116. if storage.Hierarchy == "user" {
  117. subtractionPath = thisStorageRoot + "/users/" + u.Username + "/"
  118. }
  119. if len(subtractionPath) < len(realPath) {
  120. subPath = realPath[len(subtractionPath):]
  121. }
  122. } else if len(realPath) > len(thisStorageRootAbs) && filepath.ToSlash(realPath[:len(thisStorageRootAbs)]) == filepath.ToSlash(thisStorageRootAbs) {
  123. //The realpath contains the absolute path of this storage root
  124. pathContained = true
  125. subtractionPath := thisStorageRootAbs
  126. if storage.Hierarchy == "user" {
  127. subtractionPath = thisStorageRootAbs + "/users/" + u.Username + "/"
  128. }
  129. if len(subtractionPath) < len(realPath) {
  130. subPath = realPath[len(subtractionPath):]
  131. }
  132. } else if filepath.ToSlash(realPath) == filepath.ToSlash(thisStorageRoot) {
  133. //Storage Root's root
  134. pathContained = true
  135. subPath = ""
  136. }
  137. if len(subPath) > 1 && subPath[:1] == "/" {
  138. subPath = subPath[1:]
  139. }
  140. if pathContained == true {
  141. //This storage is one of the root of the given realpath. Translate it into this
  142. if storage.Closed == true {
  143. return "", errors.New("Request Filesystem Handler has been closed by another process")
  144. }
  145. return storage.UUID + ":/" + subPath, nil
  146. }
  147. }
  148. return "", errors.New("Unable to resolve realpath in virtual devices root path")
  149. }
  150. //Get a file system handler from a virtual path, this file system handler might not be the highest prioity one
  151. func (u *User) GetFileSystemHandlerFromVirtualPath(vpath string) (*fs.FileSystemHandler, error) {
  152. fsHandlers := u.GetAllFileSystemHandler()
  153. handler, err := getHandlerFromVirtualPath(fsHandlers, vpath)
  154. return handler, err
  155. }
  156. func (u *User) GetFileSystemHandlerFromRealPath(rpath string) (*fs.FileSystemHandler, error) {
  157. vpath, err := u.RealPathToVirtualPath(rpath)
  158. if err != nil {
  159. return &fs.FileSystemHandler{}, err
  160. }
  161. return u.GetFileSystemHandlerFromVirtualPath(vpath)
  162. }
  163. /*
  164. PRIVATE FUNCTIONS HANDLERS
  165. */
  166. //Get a fs handler from a virtual path, quick function for getIDFromHandler + GetHandlerFromID
  167. func getHandlerFromVirtualPath(storages []*fs.FileSystemHandler, vpath string) (*fs.FileSystemHandler, error) {
  168. vid, _, err := getIDFromVirtualPath(vpath)
  169. if err != nil {
  170. return &fs.FileSystemHandler{}, err
  171. }
  172. return getHandlerFromID(storages, vid)
  173. }
  174. //Get a fs handler from the given virtial device id
  175. func getHandlerFromID(storages []*fs.FileSystemHandler, vid string) (*fs.FileSystemHandler, error) {
  176. for _, storage := range storages {
  177. if storage.UUID == vid {
  178. //This storage is the one we are looking at
  179. return storage, nil
  180. }
  181. }
  182. return &fs.FileSystemHandler{}, errors.New("Handler Not Found")
  183. }
  184. //Get the ID part of a virtual path, return ID, subpath and error
  185. func getIDFromVirtualPath(vpath string) (string, string, error) {
  186. if strings.Contains(vpath, ":") == false {
  187. return "", "", errors.New("Path missing Virtual Device ID. Given: " + vpath)
  188. }
  189. //Clean up the virutal path
  190. vpath = filepath.ToSlash(filepath.Clean(vpath))
  191. tmp := strings.Split(vpath, ":")
  192. vdID := tmp[0]
  193. pathSlice := tmp[1:]
  194. path := strings.Join(pathSlice, ":")
  195. return vdID, path, nil
  196. }