96 lines
1.7 KiB
Go
96 lines
1.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"go.wit.com/log"
|
|
)
|
|
|
|
func isBlockDeviceInUse(dev string) bool {
|
|
base := filepath.Base(dev)
|
|
|
|
// 1. Check /proc/mounts
|
|
if isMounted(dev, base) {
|
|
log.Info(dev, "dev is mounted (/proc/mounts)")
|
|
return true
|
|
}
|
|
|
|
// 2. Check /proc/swaps
|
|
if isSwap(dev) {
|
|
log.Info(dev, "dev is used by swap (/proc/swaps)")
|
|
return true
|
|
}
|
|
|
|
// 3. Check /proc/mdstat for RAID
|
|
if isInRAID(base) {
|
|
log.Info(dev, "dev is in software raid (/proc/mdstat)")
|
|
return true
|
|
}
|
|
|
|
// 4. Check sysfs for device-mapper or LVM use
|
|
if hasDMHolders(base) {
|
|
log.Info(dev, "dev has lvm partitions")
|
|
return true
|
|
}
|
|
|
|
log.Info(dev, "dev appears to be unused")
|
|
return false
|
|
}
|
|
|
|
func isMounted(dev, base string) bool {
|
|
f, err := os.Open("/proc/mounts")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer f.Close()
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
if strings.HasPrefix(scanner.Text(), dev) || strings.Contains(scanner.Text(), base) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isSwap(dev string) bool {
|
|
f, err := os.Open("/proc/swaps")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer f.Close()
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
if strings.HasPrefix(scanner.Text(), dev) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isInRAID(base string) bool {
|
|
f, err := os.Open("/proc/mdstat")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer f.Close()
|
|
|
|
scanner := bufio.NewScanner(f)
|
|
for scanner.Scan() {
|
|
if strings.Contains(scanner.Text(), base) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func hasDMHolders(base string) bool {
|
|
path := filepath.Join("/sys/block", base, "holders")
|
|
entries, err := os.ReadDir(path)
|
|
return err == nil && len(entries) > 0
|
|
}
|