blkid.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package blkid
  2. /*
  3. Package blkid provides functions to retrieve block device information
  4. Usually this will only return partitions info
  5. */
  6. import (
  7. "bufio"
  8. "errors"
  9. "os/exec"
  10. "regexp"
  11. "strconv"
  12. "strings"
  13. )
  14. type BlockDevice struct {
  15. Device string // Device name (e.g., /dev/sda1)
  16. UUID string // UUID of the device
  17. BlockSize int // Block size in bytes
  18. Type string // Type of the device (e.g., ext4, ntfs)
  19. PartUUID string // Partition UUID
  20. PartLabel string // Partition label
  21. }
  22. // GetBlockDevices retrieves block devices using the `blkid` command.
  23. func GetPartitionIdInfo() ([]BlockDevice, error) {
  24. //Check if the current user have superuser privileges
  25. cmd := exec.Command("id", "-u")
  26. userIDOutput, err := cmd.Output()
  27. if err != nil {
  28. return nil, err
  29. }
  30. // Check if the user ID is 0 (root)
  31. // If not, run blkid without sudo
  32. if strings.TrimSpace(string(userIDOutput)) == "0" {
  33. cmd = exec.Command("blkid")
  34. } else {
  35. cmd = exec.Command("sudo", "blkid")
  36. }
  37. output, err := cmd.Output()
  38. if err != nil {
  39. return nil, err
  40. }
  41. scanner := bufio.NewScanner(strings.NewReader(string(output)))
  42. devices := []BlockDevice{}
  43. re := regexp.MustCompile(`(\S+):\s+(.*)`)
  44. for scanner.Scan() {
  45. line := scanner.Text()
  46. matches := re.FindStringSubmatch(line)
  47. if len(matches) != 3 {
  48. continue
  49. }
  50. device := matches[1]
  51. attributes := matches[2]
  52. deviceInfo := BlockDevice{Device: device}
  53. for _, attr := range strings.Split(attributes, " ") {
  54. kv := strings.SplitN(attr, "=", 2)
  55. if len(kv) != 2 {
  56. continue
  57. }
  58. key := kv[0]
  59. value := strings.Trim(kv[1], `"`)
  60. switch key {
  61. case "UUID":
  62. deviceInfo.UUID = value
  63. case "BLOCK_SIZE":
  64. // Convert block size to int if possible
  65. blockSize, err := strconv.Atoi(value)
  66. if err == nil {
  67. deviceInfo.BlockSize = blockSize
  68. } else {
  69. deviceInfo.BlockSize = 0
  70. }
  71. case "TYPE":
  72. deviceInfo.Type = value
  73. case "PARTUUID":
  74. deviceInfo.PartUUID = value
  75. case "PARTLABEL":
  76. deviceInfo.PartLabel = value
  77. }
  78. }
  79. devices = append(devices, deviceInfo)
  80. }
  81. if err := scanner.Err(); err != nil {
  82. return nil, err
  83. }
  84. return devices, nil
  85. }
  86. // GetBlockDeviceIDFromDevicePath retrieves block device information for a given device path.
  87. func GetPartitionIDFromDevicePath(devpath string) (*BlockDevice, error) {
  88. devpath = strings.TrimPrefix(devpath, "/dev/")
  89. if strings.Contains(devpath, "/") {
  90. return nil, errors.New("invalid device path")
  91. }
  92. devpath = "/dev/" + devpath
  93. devices, err := GetPartitionIdInfo()
  94. if err != nil {
  95. return nil, err
  96. }
  97. for _, device := range devices {
  98. if device.Device == devpath {
  99. return &device, nil
  100. }
  101. }
  102. return nil, errors.New("device not found")
  103. }