fixup/getDrives.go

127 lines
2.7 KiB
Go

package main
import (
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
type DevInfo struct {
Name string
IsRaw bool
Type string
Parent string // raw device if this entry is a partition
}
func doDrives2() {
parts, err := parseProcPartitions()
if err != nil {
log.Printf("Error reading /proc/partitions: %v\n", err)
os.Exit(1)
}
// Determine raw devices and type
devs := make(map[string]*DevInfo)
for _, p := range parts {
devs[p.Name] = &DevInfo{Name: p.Name}
}
for _, info := range devs {
sysPath := filepath.Join("/sys/block", info.Name)
if exists(sysPath) {
info.IsRaw = true
typ := detectType(sysPath)
info.Type = typ
} else {
info.IsRaw = false
info.Parent = findParent(info.Name, devs)
}
}
for _, info := range devs {
devPath := "/dev/" + info.Name
if info.IsRaw {
addDrive(devPath, log.Sprintf("-> %-8s (raw)", info.Type))
} else {
if info.Parent != "" {
log.Printf("%-12s -> partition of /dev/%s\n", devPath, info.Parent)
} else {
log.Printf("%-12s -> unknown (no parent found)\n", devPath)
}
}
}
}
/*
// parseProcPartitions parses /proc/partitions entries
func parseProcPartitions() ([]struct {
Name string
}, error) {
f, err := os.Open("/proc/partitions")
if err != nil {
return nil, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
var parts []struct{ Name string }
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "major") {
continue
}
fields := strings.Fields(line)
if len(fields) < 4 {
continue
}
parts = append(parts, struct{ Name string }{Name: fields[3]})
}
return parts, scanner.Err()
}
*/
// exists checks if the given path exists
func exists(path string) bool {
_, err := os.Lstat(path)
return err == nil
}
// detectType determines device type by resolving sysPath and inspecting parent directories
func detectType(sysPath string) string {
resolved, err := filepath.EvalSymlinks(sysPath)
if err != nil {
return "unknown"
}
resolved = filepath.ToSlash(resolved)
switch {
case strings.Contains(resolved, "/nvme"):
return "NVMe"
case strings.Contains(resolved, "/mmc_host") || strings.Contains(resolved, "/mmc"):
return "MMC/SD"
case strings.Contains(resolved, "/usb"):
return "USB"
case strings.Contains(resolved, "/loop"):
return "Loop"
case strings.Contains(resolved, "/ram"):
return "RAM disk"
default:
return "SCSI/SATA"
}
}
// findParent identifies the raw device for a partition, based on name heuristics
func findParent(name string, devs map[string]*DevInfo) string {
for candidate := range devs {
if candidate == name {
continue
}
if strings.HasPrefix(name, candidate) {
return candidate
}
}
return ""
}