fixup/doDrives.go

143 lines
2.9 KiB
Go

package main
import (
"bufio"
"io/fs"
"os"
"path/filepath"
"strings"
"go.wit.com/log"
)
func doDrives() {
parts, err := parseProcPartitions()
if err != nil {
panic(err)
}
for _, p := range parts {
log.Printf("RAW Device: /dev/%s\tSize: %d KiB\n", p.Name, p.Blocks)
devname := "/dev/" + p.Name
if blkpb := me.pb.FindByName(devname); blkpb != nil {
blkpb.SizeBytes = uint64(p.Blocks) * 1024
}
}
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
log.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)
partDev := "/dev/" + partName
if partName == dev {
log.Printf(" SKIP MAIN Partition: %s\n", partDev)
continue // skip the main device
}
hasPartition = true
isMounted := mounts[partDev]
log.Printf(" Partition: %s [%v]\n", partDev, isMounted)
if isMounted {
used = true
}
}
if !hasPartition {
log.Println(" No partitions found.")
}
if !used {
log.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 := log.Sscanf(line, "%d %d %d %s", &p.Major, &p.Minor, &p.Blocks, &p.Name)
if err != nil {
return nil, log.Errorf("error parsing line: %q: %w", line, err)
}
partitions = append(partitions, p)
}
return partitions, scanner.Err()
}