dftool.go 2.6 KB

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