static.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. package filesystem
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "os"
  7. "os/exec"
  8. "path/filepath"
  9. "runtime"
  10. "strconv"
  11. "strings"
  12. "net/url"
  13. mimetype "github.com/gabriel-vasile/mimetype"
  14. "imuslab.com/arozos/mod/filesystem/shortcut"
  15. )
  16. //Structure definations
  17. type FileData struct {
  18. Filename string
  19. Filepath string
  20. Realpath string
  21. IsDir bool
  22. Filesize int64
  23. Displaysize string
  24. ModTime int64
  25. IsShared bool
  26. Shortcut *shortcut.ShortcutData //This will return nil or undefined if it is not a shortcut file
  27. }
  28. type TrashedFile struct {
  29. Filename string
  30. Filepath string
  31. FileExt string
  32. IsDir bool
  33. Filesize int64
  34. RemoveTimestamp int64
  35. RemoveDate string
  36. OriginalPath string
  37. OriginalFilename string
  38. }
  39. type FileProperties struct {
  40. VirtualPath string
  41. StoragePath string
  42. Basename string
  43. VirtualDirname string
  44. StorageDirname string
  45. Ext string
  46. MimeType string
  47. Filesize int64
  48. Permission string
  49. LastModTime string
  50. LastModUnix int64
  51. IsDirectory bool
  52. }
  53. //Check if the two file system are identical.
  54. func MatchingFileSystem(fsa *FileSystemHandler, fsb *FileSystemHandler) bool {
  55. if fsa.Filesystem == fsb.Filesystem {
  56. return true
  57. }
  58. return false
  59. }
  60. func GetFileDataFromPath(vpath string, realpath string, sizeRounding int) FileData {
  61. fileSize := GetFileSize(realpath)
  62. displaySize := GetFileDisplaySize(fileSize, sizeRounding)
  63. modtime, _ := GetModTime(realpath)
  64. var shortcutInfo *shortcut.ShortcutData = nil
  65. if filepath.Ext(realpath) == ".shortcut" {
  66. scd, err := shortcut.ReadShortcut(realpath)
  67. if err == nil {
  68. shortcutInfo = scd
  69. }
  70. }
  71. return FileData{
  72. Filename: filepath.Base(realpath),
  73. Filepath: vpath,
  74. Realpath: filepath.ToSlash(realpath),
  75. IsDir: IsDir(realpath),
  76. Filesize: fileSize,
  77. Displaysize: displaySize,
  78. ModTime: modtime,
  79. IsShared: false,
  80. Shortcut: shortcutInfo,
  81. }
  82. }
  83. func CheckMounted(mountpoint string) bool {
  84. if runtime.GOOS == "windows" {
  85. //Windows
  86. //Check if the given folder exists
  87. info, err := os.Stat(mountpoint)
  88. if os.IsNotExist(err) {
  89. return false
  90. }
  91. return info.IsDir()
  92. } else {
  93. //Linux
  94. cmd := exec.Command("mountpoint", mountpoint)
  95. out, err := cmd.CombinedOutput()
  96. if err != nil {
  97. return false
  98. }
  99. outstring := strings.TrimSpace(string(out))
  100. if strings.Contains(outstring, " is a mountpoint") {
  101. return true
  102. } else {
  103. return false
  104. }
  105. }
  106. }
  107. func MountDevice(mountpt string, mountdev string, filesystem string) error {
  108. //Check if running under sudo mode and in linux
  109. if runtime.GOOS == "linux" {
  110. //Try to mount the file system
  111. if mountdev == "" {
  112. return errors.New("Disk with automount enabled has no mountdev value: " + mountpt)
  113. }
  114. if mountpt == "" {
  115. return errors.New("Invalid storage.json. Mount point not given or not exists for " + mountdev)
  116. }
  117. //Check if device exists
  118. if !fileExists(mountdev) {
  119. //Device driver not exists.
  120. return errors.New("Device not exists: " + mountdev)
  121. }
  122. //Mount the device
  123. if CheckMounted(mountpt) {
  124. log.Println(mountpt + " already mounted.")
  125. } else {
  126. log.Println("Mounting " + mountdev + "(" + filesystem + ") to " + filepath.Clean(mountpt))
  127. cmd := exec.Command("mount", "-t", filesystem, mountdev, filepath.Clean(mountpt))
  128. cmd.Stdout = os.Stdout
  129. cmd.Stderr = os.Stderr
  130. cmd.Run()
  131. }
  132. //Check if the path exists
  133. if !fileExists(mountpt) {
  134. //Mounted but path still not found. Skip this device
  135. return errors.New("Unable to find " + mountpt)
  136. }
  137. } else {
  138. return errors.New("Unsupported platform")
  139. }
  140. return nil
  141. }
  142. func GetFileSize(filename string) int64 {
  143. fi, err := os.Stat(filename)
  144. if err != nil {
  145. return 0
  146. }
  147. // get the size
  148. return fi.Size()
  149. }
  150. func IsInsideHiddenFolder(path string) bool {
  151. thisPathInfo := filepath.ToSlash(filepath.Clean(path))
  152. pathData := strings.Split(thisPathInfo, "/")
  153. for _, thispd := range pathData {
  154. if len(thispd) > 0 && thispd[:1] == "." {
  155. //This path contain one of the folder is hidden
  156. return true
  157. }
  158. }
  159. return false
  160. }
  161. /*
  162. Wildcard Replacement Glob, design to hanle path with [ or ] inside.
  163. You can also pass in normal path for globing if you are not sure.
  164. */
  165. func WGlob(path string) ([]string, error) {
  166. files, err := filepath.Glob(path)
  167. if err != nil {
  168. return []string{}, err
  169. }
  170. if strings.Contains(path, "[") == true || strings.Contains(path, "]") == true {
  171. if len(files) == 0 {
  172. //Handle reverse check. Replace all [ and ] with *
  173. newSearchPath := strings.ReplaceAll(path, "[", "?")
  174. newSearchPath = strings.ReplaceAll(newSearchPath, "]", "?")
  175. //Scan with all the similar structure except [ and ]
  176. tmpFilelist, _ := filepath.Glob(newSearchPath)
  177. for _, file := range tmpFilelist {
  178. file = filepath.ToSlash(file)
  179. if strings.Contains(file, filepath.ToSlash(filepath.Dir(path))) {
  180. files = append(files, file)
  181. }
  182. }
  183. }
  184. }
  185. //Convert all filepaths to slash
  186. for i := 0; i < len(files); i++ {
  187. files[i] = filepath.ToSlash(files[i])
  188. }
  189. return files, nil
  190. }
  191. /*
  192. Get Directory size, require filepath and include Hidden files option(true / false)
  193. Return total file size and file count
  194. */
  195. func GetDirctorySize(filename string, includeHidden bool) (int64, int) {
  196. var size int64 = 0
  197. var fileCount int = 0
  198. err := filepath.Walk(filename, func(thisFilename string, info os.FileInfo, err error) error {
  199. if err != nil {
  200. return err
  201. }
  202. if !info.IsDir() {
  203. if includeHidden {
  204. //append all into the file count and size
  205. size += info.Size()
  206. fileCount++
  207. } else {
  208. //Check if this is hidden
  209. if !IsInsideHiddenFolder(thisFilename) {
  210. size += info.Size()
  211. fileCount++
  212. }
  213. }
  214. }
  215. return err
  216. })
  217. if err != nil {
  218. return 0, fileCount
  219. }
  220. return size, fileCount
  221. }
  222. func GetFileDisplaySize(filesize int64, rounding int) string {
  223. precisionString := "%." + strconv.Itoa(rounding) + "f"
  224. var bytes float64
  225. bytes = float64(filesize)
  226. var kilobytes float64
  227. kilobytes = (bytes / 1024)
  228. if kilobytes < 1 {
  229. return fmt.Sprintf(precisionString, bytes) + "Bytes"
  230. }
  231. var megabytes float64
  232. megabytes = (float64)(kilobytes / 1024)
  233. if megabytes < 1 {
  234. return fmt.Sprintf(precisionString, kilobytes) + "KB"
  235. }
  236. var gigabytes float64
  237. gigabytes = (megabytes / 1024)
  238. if gigabytes < 1 {
  239. return fmt.Sprintf(precisionString, megabytes) + "MB"
  240. }
  241. var terabytes float64
  242. terabytes = (gigabytes / 1024)
  243. if terabytes < 1 {
  244. return fmt.Sprintf(precisionString, gigabytes) + "GB"
  245. }
  246. var petabytes float64
  247. petabytes = (terabytes / 1024)
  248. if petabytes < 1 {
  249. return fmt.Sprintf(precisionString, terabytes) + "TB"
  250. }
  251. var exabytes float64
  252. exabytes = (petabytes / 1024)
  253. if exabytes < 1 {
  254. return fmt.Sprintf(precisionString, petabytes) + "PB"
  255. }
  256. var zettabytes float64
  257. zettabytes = (exabytes / 1024)
  258. if zettabytes < 1 {
  259. return fmt.Sprintf(precisionString, exabytes) + "EB"
  260. }
  261. return fmt.Sprintf(precisionString, zettabytes) + "ZB"
  262. }
  263. func DecodeURI(inputPath string) string {
  264. inputPath = strings.ReplaceAll(inputPath, "+", "{{plus_sign}}")
  265. inputPath, _ = url.QueryUnescape(inputPath)
  266. inputPath = strings.ReplaceAll(inputPath, "{{plus_sign}}", "+")
  267. return inputPath
  268. }
  269. func GetMime(filepath string) (string, string, error) {
  270. mime, err := mimetype.DetectFile(filepath)
  271. return mime.String(), mime.Extension(), err
  272. }
  273. func GetModTime(filepath string) (int64, error) {
  274. f, err := os.Open(filepath)
  275. if err != nil {
  276. return -1, err
  277. }
  278. statinfo, err := f.Stat()
  279. if err != nil {
  280. return -1, err
  281. }
  282. f.Close()
  283. return statinfo.ModTime().Unix(), nil
  284. }