dftool.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package dftool
  2. import (
  3. "errors"
  4. "os/exec"
  5. "path/filepath"
  6. "runtime"
  7. "strconv"
  8. "strings"
  9. "imuslab.com/arozos/mod/disk/diskspace"
  10. )
  11. type Capacity struct {
  12. PhysicalDevice string //The ID of the physical device, like C:/ or /dev/sda1
  13. Used int64 //Used capacity in bytes
  14. Available int64 //Avilable capacity in bytes
  15. Total int64 //Total capacity in bytes
  16. }
  17. func GetCapacityInfoFromPath(realpath string) (*Capacity, error) {
  18. rpathAbs, err := filepath.Abs(realpath)
  19. if err != nil {
  20. return nil, err
  21. }
  22. if runtime.GOOS == "windows" {
  23. //Windows
  24. //Extract disk ID from path
  25. rpathAbs = filepath.ToSlash(filepath.Clean(rpathAbs))
  26. diskRoot := strings.Split(rpathAbs, "/")[0]
  27. //Match the disk space info generated from diskspace
  28. logicDiskInfo := diskspace.GetAllLogicDiskInfo()
  29. for _, ldi := range logicDiskInfo {
  30. if strings.TrimSpace(ldi.Device) == strings.TrimSpace(diskRoot) {
  31. //Matching device ID
  32. return &Capacity{
  33. PhysicalDevice: ldi.Device,
  34. Used: ldi.Used,
  35. Available: ldi.Available,
  36. Total: ldi.Volume,
  37. }, nil
  38. }
  39. }
  40. } else {
  41. //Assume Linux or Mac
  42. //Use command: df -P {abs_path}
  43. cmd := exec.Command("df", "-P", rpathAbs)
  44. out, err := cmd.CombinedOutput()
  45. if err != nil {
  46. return nil, err
  47. }
  48. //Get the last line of the output
  49. diskInfo := strings.TrimSpace(string(out))
  50. tmp := strings.Split(diskInfo, "\n")
  51. targetDiskInfo := strings.Join(tmp[len(tmp)-1:], " ")
  52. for strings.Contains(targetDiskInfo, " ") {
  53. targetDiskInfo = strings.ReplaceAll(targetDiskInfo, " ", " ")
  54. }
  55. diskInfoSlice := strings.Split(targetDiskInfo, " ")
  56. if len(diskInfoSlice) < 4 {
  57. return nil, errors.New("Malformed output for df -P")
  58. }
  59. //Extract capacity information from df output
  60. total, err := strconv.ParseInt(diskInfoSlice[1], 10, 64)
  61. if err != nil {
  62. return nil, errors.New("Malformed output for df -P")
  63. }
  64. used, err := strconv.ParseInt(diskInfoSlice[2], 10, 64)
  65. if err != nil {
  66. return nil, errors.New("Malformed output for df -P")
  67. }
  68. availbe, err := strconv.ParseInt(diskInfoSlice[3], 10, 64)
  69. if err != nil {
  70. return nil, errors.New("Malformed output for df -P")
  71. }
  72. //Return the capacity info struct, capacity is reported in 1024 bytes block
  73. return &Capacity{
  74. PhysicalDevice: diskInfoSlice[0],
  75. Used: used * 1024,
  76. Available: availbe * 1024,
  77. Total: total * 1024,
  78. }, nil
  79. }
  80. return nil, errors.New("Unable to resolve matching disk capacity information")
  81. }