dftool.go 2.6 KB

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