diff options
Diffstat (limited to 'doDrives.go')
| -rw-r--r-- | doDrives.go | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/doDrives.go b/doDrives.go new file mode 100644 index 0000000..bc22dae --- /dev/null +++ b/doDrives.go @@ -0,0 +1,138 @@ +package main + +import ( + "bufio" + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" + + "go.wit.com/log" +) + +func doDrives() { + parts, err := parseProcPartitions() + if err != nil { + panic(err) + } + + for _, p := range parts { + fmt.Printf("Device: /dev/%s\tSize: %d KiB\n", p.Name, p.Blocks) + } + + blockDir := "/sys/block" + mounts := getMountedDevices() + + log.Info("doDrives()", mounts) + + err = filepath.WalkDir(blockDir, func(path string, d fs.DirEntry, err error) error { + if path == blockDir { + return nil // skip root + } + if d.IsDir() && filepath.Dir(path) == blockDir { + dev := d.Name() + devPath := "/dev/" + dev + fmt.Printf("Drive: %s\n", devPath) + + // Look for partitions + partitions, err := filepath.Glob(filepath.Join(blockDir, dev, dev+"*")) + if err != nil { + return err + } + + hasPartition := false + used := false + for _, part := range partitions { + partName := filepath.Base(part) + if partName == dev { + continue // skip the main device + } + hasPartition = true + partDev := "/dev/" + partName + isMounted := mounts[partDev] + fmt.Printf(" Partition: %s [%v]\n", partDev, isMounted) + if isMounted { + used = true + } + } + + if !hasPartition { + fmt.Println(" No partitions found.") + } + + if !used { + fmt.Println(" → Drive appears to be unused.") + } + } + return nil + }) + + if err != nil { + panic(err) + } +} + +// getMountedDevices reads /proc/self/mountinfo and returns a map of mounted device paths +func getMountedDevices() map[string]bool { + f, err := os.Open("/proc/self/mountinfo") + if err != nil { + panic(err) + } + defer f.Close() + + mounted := make(map[string]bool) + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + fields := strings.Fields(line) + if len(fields) < 10 { + continue + } + // Device path is after the last '-' token + for i, field := range fields { + if field == "-" && i+2 < len(fields) { + dev := fields[i+2] + if strings.HasPrefix(dev, "/dev/") { + mounted[dev] = true + } + break + } + } + } + return mounted +} + +type Partition struct { + Major int + Minor int + Blocks int64 + Name string +} + +func parseProcPartitions() ([]Partition, error) { + f, err := os.Open("/proc/partitions") + if err != nil { + return nil, err + } + defer f.Close() + + var partitions []Partition + scanner := bufio.NewScanner(f) + + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, "major") || line == "" { + continue // Skip header and empty lines + } + + var p Partition + _, err := fmt.Sscanf(line, "%d %d %d %s", &p.Major, &p.Minor, &p.Blocks, &p.Name) + if err != nil { + return nil, fmt.Errorf("error parsing line: %q: %w", line, err) + } + partitions = append(partitions, p) + } + + return partitions, scanner.Err() +} |
