static.go 7.1 KB

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