diskfs.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package diskfs
  2. import (
  3. "bufio"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "os"
  8. "os/exec"
  9. "strings"
  10. "imuslab.com/arozos/mod/utils"
  11. )
  12. /*
  13. diskfs.go
  14. This module handle file system creation and formatting
  15. */
  16. // Storage Device meta was generated by lsblk
  17. // Partitions like sdX0
  18. type PartitionMeta struct {
  19. Name string `json:"name"`
  20. MajMin string `json:"maj:min"`
  21. Rm bool `json:"rm"`
  22. Size int64 `json:"size"`
  23. Ro bool `json:"ro"`
  24. Type string `json:"type"`
  25. Mountpoint string `json:"mountpoint"`
  26. }
  27. // Block device, usually disk or rom, like sdX
  28. type BlockDeviceMeta struct {
  29. Name string `json:"name"`
  30. MajMin string `json:"maj:min"`
  31. Rm bool `json:"rm"`
  32. Size int64 `json:"size"`
  33. Ro bool `json:"ro"`
  34. Type string `json:"type"`
  35. Mountpoint string `json:"mountpoint"`
  36. Children []PartitionMeta `json:"children,omitempty"`
  37. }
  38. // A collection of information for lsblk output
  39. type StorageDevicesMeta struct {
  40. Blockdevices []BlockDeviceMeta `json:"blockdevices"`
  41. }
  42. // Check if the file format driver is installed on this host
  43. // if a format is supported, mkfs.(format) should be symlinked under /sbin
  44. func FormatPackageInstalled(fsType string) bool {
  45. return utils.FileExists("/sbin/mkfs." + fsType)
  46. }
  47. // Create file system, support ntfs, ext4 and fat32 only
  48. func FormatStorageDevice(fsType string, devicePath string) error {
  49. // Check if the filesystem type is supported
  50. switch fsType {
  51. case "ext4":
  52. // Format the device with the specified filesystem type
  53. cmd := exec.Command("sudo", "mkfs."+fsType, devicePath)
  54. output, err := cmd.CombinedOutput()
  55. if err != nil {
  56. return errors.New("unable to format device: " + string(output))
  57. }
  58. return nil
  59. case "vfat", "fat", "fat32":
  60. //Check if mkfs.fat exists
  61. if !FormatPackageInstalled("vfat") {
  62. return errors.New("unable to format device as fat (vfat). dosfstools not installed?")
  63. }
  64. // Format the device with the specified filesystem type
  65. cmd := exec.Command("sudo", "mkfs.vfat", devicePath)
  66. output, err := cmd.CombinedOutput()
  67. if err != nil {
  68. return errors.New("unable to format device: " + string(output))
  69. }
  70. return nil
  71. case "ntfs":
  72. //Check if ntfs-3g exists
  73. if !FormatPackageInstalled("ntfs") {
  74. return errors.New("unable to format device as ntfs: ntfs-3g not installed?")
  75. }
  76. //Format the drive
  77. cmd := exec.Command("sudo", "mkfs.ntfs", devicePath)
  78. output, err := cmd.CombinedOutput()
  79. if err != nil {
  80. return errors.New("unable to format device: " + string(output))
  81. }
  82. return nil
  83. default:
  84. return fmt.Errorf("unsupported filesystem type: %s", fsType)
  85. }
  86. }
  87. // List all the storage device in the system, set minSize to 0 for no filter
  88. func ListAllStorageDevices() (*StorageDevicesMeta, error) {
  89. cmd := exec.Command("sudo", "lsblk", "-b", "--json")
  90. output, err := cmd.CombinedOutput()
  91. if err != nil {
  92. return nil, fmt.Errorf("lsblk error: %v", err)
  93. }
  94. var devices StorageDevicesMeta
  95. err = json.Unmarshal([]byte(output), &devices)
  96. return &devices, err
  97. }
  98. // Check if a device is mounted given the path name, like /dev/sdc
  99. func DeviceIsMounted(devicePath string) (bool, error) {
  100. // Open the mountinfo file
  101. file, err := os.Open("/proc/mounts")
  102. if err != nil {
  103. return false, fmt.Errorf("error opening /proc/mounts: %v", err)
  104. }
  105. defer file.Close()
  106. // Scan the mountinfo file line by line
  107. scanner := bufio.NewScanner(file)
  108. for scanner.Scan() {
  109. line := scanner.Text()
  110. fields := strings.Fields(line)
  111. if len(fields) >= 2 && fields[0] == devicePath {
  112. // Device is mounted
  113. return true, nil
  114. }
  115. }
  116. // Device is not mounted
  117. return false, nil
  118. }
  119. // UnmountDevice unmounts the specified device.
  120. // Remember to use full path (e.g. /dev/md0) in the devicePath
  121. func UnmountDevice(devicePath string) error {
  122. // Construct the bash command to unmount the device
  123. cmd := exec.Command("sudo", "bash", "-c", fmt.Sprintf("umount %s", devicePath))
  124. // Run the command
  125. err := cmd.Run()
  126. if err != nil {
  127. return fmt.Errorf("error unmounting device: %v", err)
  128. }
  129. return nil
  130. }
  131. // Force Version of Unmount (dangerous)
  132. // Remember to use full path (e.g. /dev/md0) in the devicePath
  133. func ForceUnmountDevice(devicePath string) error {
  134. // Construct the bash command to unmount the device
  135. cmd := exec.Command("sudo", "bash", "-c", fmt.Sprintf("umount -l %s", devicePath))
  136. // Run the command
  137. err := cmd.Run()
  138. if err != nil {
  139. return fmt.Errorf("error unmounting device: %v", err)
  140. }
  141. return nil
  142. }
  143. // DANGER: Wipe the whole disk given the disk path
  144. func WipeDisk(diskPath string) error {
  145. // Unmount the disk
  146. isMounted, _ := DeviceIsMounted(diskPath)
  147. if isMounted {
  148. umountCmd := exec.Command("sudo", "umount", diskPath)
  149. if err := umountCmd.Run(); err != nil {
  150. return fmt.Errorf("error unmounting disk %s: %v", diskPath, err)
  151. }
  152. }
  153. // Wipe all filesystem signatures on the entire disk
  154. wipeCmd := exec.Command("sudo", "wipefs", "--all", "--force", diskPath)
  155. if err := wipeCmd.Run(); err != nil {
  156. return fmt.Errorf("error wiping filesystem signatures on %s: %v", diskPath, err)
  157. }
  158. return nil
  159. }