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 }