diskutil.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package diskinfo
  2. import (
  3. "errors"
  4. "path/filepath"
  5. "strings"
  6. "log"
  7. "imuslab.com/bokofs/bokofsd/mod/diskinfo/blkid"
  8. "imuslab.com/bokofs/bokofsd/mod/diskinfo/df"
  9. "imuslab.com/bokofs/bokofsd/mod/diskinfo/fdisk"
  10. "imuslab.com/bokofs/bokofsd/mod/diskinfo/lsblk"
  11. )
  12. // GetAllDisks retrieves all disks on the system.
  13. func GetAllDisks() ([]*Disk, error) {
  14. allBlockDevices, err := lsblk.GetLSBLKOutput()
  15. if err != nil {
  16. return nil, err
  17. }
  18. disks := []*Disk{}
  19. for _, blockDevice := range allBlockDevices {
  20. if blockDevice.Type == "disk" {
  21. thisDisk, err := GetDiskInfo(blockDevice.Name)
  22. if err != nil {
  23. return nil, err
  24. }
  25. disks = append(disks, thisDisk)
  26. }
  27. }
  28. return disks, nil
  29. }
  30. // DevicePathIsValidDisk checks if the given device path is a disk.
  31. func DevicePathIsValidDisk(path string) bool {
  32. //Make sure the path has a prefix and a trailing slash
  33. if !strings.HasPrefix(path, "/dev/") {
  34. path = "/dev/" + path
  35. }
  36. path = strings.TrimSuffix(path, "/")
  37. allBlockDevices, err := lsblk.GetLSBLKOutput()
  38. if err != nil {
  39. log.Println("Error getting block devices:", err)
  40. return false
  41. }
  42. for _, blockDevice := range allBlockDevices {
  43. if "/dev/"+blockDevice.Name == path {
  44. return blockDevice.Type == "disk"
  45. }
  46. }
  47. return false
  48. }
  49. // DevicePathIsPartition checks if the given device path is a valid partition.
  50. func DevicePathIsValidPartition(path string) bool {
  51. //Make sure the path has a prefix and a trailing slash
  52. if !strings.HasPrefix(path, "/dev/") {
  53. path = "/dev/" + path
  54. }
  55. path = strings.TrimSuffix(path, "/")
  56. allBlockDevices, err := lsblk.GetLSBLKOutput()
  57. if err != nil {
  58. return false
  59. }
  60. for _, blockDevice := range allBlockDevices {
  61. if !strings.HasPrefix(path, "/dev/"+blockDevice.Name) {
  62. //Skip this block device
  63. //This is not a partition of this block device
  64. continue
  65. }
  66. for _, child := range blockDevice.Children {
  67. if "/dev/"+child.Name == path {
  68. //As there are too many partition types
  69. //We can only check if the block device is not a disk and exists
  70. return true
  71. }
  72. }
  73. }
  74. return false
  75. }
  76. // GetDiskInfo retrieves the disk information for a given disk name.
  77. // e.g. "sda"
  78. // for partitions, use the GetPartitionInfo function
  79. func GetDiskInfo(diskname string) (*Disk, error) {
  80. if diskname == "" {
  81. return nil, errors.New("disk name is empty")
  82. }
  83. //Make sure the diskname is something like sda
  84. diskname = strings.TrimPrefix(diskname, "/dev/")
  85. //Create a new disk object
  86. thisDisk := &Disk{
  87. Name: diskname,
  88. Size: 0,
  89. BlockType: "disk",
  90. Partitions: []*Partition{},
  91. }
  92. //Try to get the disk model and identifier
  93. diskInfo, err := fdisk.GetDiskModelAndIdentifier(diskname)
  94. if err == nil {
  95. thisDisk.Model = diskInfo.Model
  96. thisDisk.Identifier = diskInfo.Identifier
  97. thisDisk.DiskLabel = diskInfo.DiskLabel
  98. }
  99. //Calculation variables for total disk used space
  100. totalDiskUseSpace := int64(0)
  101. //Populate the partitions
  102. allBlockDevices, err := lsblk.GetLSBLKOutput()
  103. if err != nil {
  104. return nil, err
  105. }
  106. for _, blockDevice := range allBlockDevices {
  107. if blockDevice.Name == diskname {
  108. thisDisk.Size = blockDevice.Size
  109. for _, partition := range blockDevice.Children {
  110. //Get the partition information from blkid
  111. partition := &Partition{
  112. Name: partition.Name,
  113. Size: partition.Size,
  114. Path: filepath.Join("/dev", partition.Name),
  115. BlockType: partition.Type,
  116. MountPoint: partition.MountPoint,
  117. }
  118. //Get the partition ID
  119. blkInfo, err := blkid.GetPartitionIDFromDevicePath(partition.Name)
  120. if err == nil {
  121. partition.UUID = blkInfo.UUID
  122. partition.PartUUID = blkInfo.PartUUID
  123. partition.PartLabel = blkInfo.PartLabel
  124. partition.BlockSize = blkInfo.BlockSize
  125. partition.BlockType = blkInfo.Type
  126. partition.FsType = blkInfo.Type
  127. }
  128. //Get the disk usage information
  129. diskUsage, err := df.GetDiskUsageByPath(partition.Name)
  130. if err == nil {
  131. partition.Used = diskUsage.Used
  132. partition.Free = diskUsage.Available
  133. }
  134. thisDisk.Partitions = append(thisDisk.Partitions, partition)
  135. }
  136. }
  137. }
  138. //Calculate the total disk used space
  139. for _, partition := range thisDisk.Partitions {
  140. totalDiskUseSpace += partition.Used
  141. }
  142. thisDisk.Used = totalDiskUseSpace
  143. thisDisk.Free = thisDisk.Size - totalDiskUseSpace
  144. return thisDisk, nil
  145. }
  146. func GetPartitionInfo(partitionName string) (*Partition, error) {
  147. partition := &Partition{
  148. Name: partitionName,
  149. }
  150. partInfo, err := blkid.GetPartitionIDFromDevicePath(partitionName)
  151. if err == nil {
  152. partition.UUID = partInfo.UUID
  153. partition.PartUUID = partInfo.PartUUID
  154. partition.PartLabel = partInfo.PartLabel
  155. partition.BlockSize = partInfo.BlockSize
  156. partition.BlockType = partInfo.Type
  157. partition.FsType = partInfo.Type
  158. }
  159. //Get the disk usage information
  160. diskUsage, err := df.GetDiskUsageByPath(partitionName)
  161. if err == nil {
  162. partition.Used = diskUsage.Used
  163. partition.Free = diskUsage.Available
  164. partition.MountPoint = diskUsage.MountedOn
  165. }
  166. return partition, nil
  167. }
  168. // GetDevicePathFromPartitionID retrieves the device path for a given partition ID.
  169. func GetDevicePathFromPartitionID(diskID string) (string, error) {
  170. if diskID == "" {
  171. return "", errors.New("disk ID is empty")
  172. }
  173. // Try to get the block device info
  174. allBlockDevices, err := lsblk.GetLSBLKOutput()
  175. if err != nil {
  176. return "", err
  177. }
  178. for _, blockDevice := range allBlockDevices {
  179. //Check each of the children to see if there is a partition with the given ID
  180. for _, child := range blockDevice.Children {
  181. if child.Name == diskID {
  182. return child.Name, nil
  183. }
  184. }
  185. }
  186. return "", errors.New("disk ID not found")
  187. }