| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- package diskfs
- import (
- "bufio"
- "errors"
- "fmt"
- "os"
- "os/exec"
- "strconv"
- "strings"
- "imuslab.com/arozos/mod/utils"
- )
- /*
- diskfs.go
- This module handle file system creation and formatting
- */
- // Storage Device meta was generated by lsblk
- type StorageDeviceMeta struct {
- Name string
- Size int64
- RO bool
- DevType string
- MountPoint string
- }
- // Check if the file format driver is installed on this host
- // if a format is supported, mkfs.(format) should be symlinked under /sbin
- func FormatPackageInstalled(fsType string) bool {
- return utils.FileExists("/sbin/mkfs." + fsType)
- }
- // Create file system, support ntfs, ext4 and fat32 only
- func FormatStorageDevice(fsType string, devicePath string) error {
- // Check if the filesystem type is supported
- switch fsType {
- case "ext4":
- // Format the device with the specified filesystem type
- cmd := exec.Command("sudo", "mkfs."+fsType, devicePath)
- output, err := cmd.CombinedOutput()
- if err != nil {
- return errors.New("unable to format device: " + string(output))
- }
- return nil
- case "vfat", "fat", "fat32":
- //Check if mkfs.fat exists
- if !FormatPackageInstalled("vfat") {
- return errors.New("unable to format device as fat (vfat). dosfstools not installed?")
- }
- // Format the device with the specified filesystem type
- cmd := exec.Command("sudo", "mkfs.vfat", devicePath)
- output, err := cmd.CombinedOutput()
- if err != nil {
- return errors.New("unable to format device: " + string(output))
- }
- return nil
- case "ntfs":
- //Check if ntfs-3g exists
- if !FormatPackageInstalled("ntfs") {
- return errors.New("unable to format device as ntfs: ntfs-3g not installed?")
- }
- //Format the drive
- cmd := exec.Command("sudo", "mkfs.ntfs", devicePath)
- output, err := cmd.CombinedOutput()
- if err != nil {
- return errors.New("unable to format device: " + string(output))
- }
- return nil
- default:
- return fmt.Errorf("unsupported filesystem type: %s", fsType)
- }
- }
- // List all the storage device in the system, set minSize to 0 for no filter
- func ListAllStorageDevices(minSize int64) ([]*StorageDeviceMeta, error) {
- cmd := exec.Command("sudo", "lsblk", "-b")
- output, err := cmd.CombinedOutput()
- if err != nil {
- return nil, fmt.Errorf("lsblk error: %v", err)
- }
- // Split the output into lines
- lines := strings.Split(string(output), "\n")
- var devices []*StorageDeviceMeta
- // Parse each line to extract device information
- for _, line := range lines[1:] { // Skip the header line
- fields := strings.Fields(line)
- if len(fields) < 7 {
- continue
- }
- size, err := strconv.ParseInt(fields[3], 10, 64)
- if err != nil {
- return nil, fmt.Errorf("error parsing device size: %v", err)
- }
- ro := fields[4] == "1"
- device := &StorageDeviceMeta{
- Name: fields[0],
- Size: size,
- RO: ro,
- DevType: fields[5],
- MountPoint: fields[6],
- }
- // Filter devices based on minimum size
- if size >= minSize {
- devices = append(devices, device)
- }
- }
- return devices, nil
- }
- // Check if a device is mounted given the path name, like /dev/sdc
- func DeviceIsMounted(devicePath string) (bool, error) {
- // Open the mountinfo file
- file, err := os.Open("/proc/mounts")
- if err != nil {
- return false, fmt.Errorf("error opening /proc/mounts: %v", err)
- }
- defer file.Close()
- // Scan the mountinfo file line by line
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := scanner.Text()
- fields := strings.Fields(line)
- if len(fields) >= 2 && fields[0] == devicePath {
- // Device is mounted
- return true, nil
- }
- }
- // Device is not mounted
- return false, nil
- }
- // UnmountDevice unmounts the specified device.
- // Remember to use full path (e.g. /dev/md0) in the devicePath
- func UnmountDevice(devicePath string) error {
- // Construct the bash command to unmount the device
- cmd := exec.Command("sudo", "bash", "-c", fmt.Sprintf("umount %s", devicePath))
- // Run the command
- err := cmd.Run()
- if err != nil {
- return fmt.Errorf("error unmounting device: %v", err)
- }
- return nil
- }
- // DANGER: Wipe the whole disk given the disk path
- func WipeDisk(diskPath string) error {
- // Unmount the disk
- isMounted, _ := DeviceIsMounted(diskPath)
- if isMounted {
- umountCmd := exec.Command("sudo", "umount", diskPath)
- if err := umountCmd.Run(); err != nil {
- return fmt.Errorf("error unmounting disk %s: %v", diskPath, err)
- }
- }
- // Wipe all filesystem signatures on the entire disk
- wipeCmd := exec.Command("sudo", "wipefs", "--all", "--force", diskPath)
- if err := wipeCmd.Run(); err != nil {
- return fmt.Errorf("error wiping filesystem signatures on %s: %v", diskPath, err)
- }
- return nil
- }
|