more sanity checks
This commit is contained in:
parent
25c604aeee
commit
145244f63d
40
doGui.go
40
doGui.go
|
@ -6,7 +6,6 @@ package main
|
|||
// An app to submit patches for the 30 GO GUI repos
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -21,7 +20,7 @@ import (
|
|||
func debug() {
|
||||
for {
|
||||
time.Sleep(10 * time.Second)
|
||||
log.Info("TODO: use this debug loop for something?")
|
||||
// log.Info("TODO: use this debug loop for something?")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,17 +39,48 @@ func addDrive(devname string, displayDesc string) *Block {
|
|||
}
|
||||
|
||||
func switchDrive(blk *Block) {
|
||||
var inUse bool = false
|
||||
me.currentDev = blk
|
||||
me.parted.SetText("Partition " + blk.Name)
|
||||
|
||||
if isBlockDeviceInUse(blk.Name) {
|
||||
log.Info("Is in use?", blk.Name)
|
||||
me.parted.SetText("Partition " + blk.Name + " (in use)")
|
||||
me.parted.Disable()
|
||||
inUse = true
|
||||
} else {
|
||||
log.Info("Is probably not in use?", blk.Name)
|
||||
me.parted.SetText("Partition " + blk.Name + " as gpt boot disk")
|
||||
me.parted.Enable()
|
||||
}
|
||||
|
||||
log.Info("check if", me.currentDev.Name, "is in use")
|
||||
result, err := shell.RunVerbose([]string{"parted", me.currentDev.Name, "print"})
|
||||
log.Info("result =", result.Stdout, "err =", err)
|
||||
out := strings.Join(result.Stdout, "\n")
|
||||
if err != nil {
|
||||
out += fmt.Sprintf("err = %v", err)
|
||||
out += log.Sprintf("err = %v", err)
|
||||
}
|
||||
me.driveInfoBox.SetText(out)
|
||||
|
||||
if inUse {
|
||||
// if the drive is in use already, you can just stop here
|
||||
return
|
||||
}
|
||||
|
||||
if ok, err := hasPartitionTable(blk.Name); err != nil {
|
||||
out := log.Sprintf("Error checking partition table: %s\n", err)
|
||||
log.Warn(out)
|
||||
me.parted.Disable()
|
||||
me.driveInfoBox.SetText(out)
|
||||
} else {
|
||||
if !ok {
|
||||
log.Printf("%s has no partition table safe for gdisk\n", blk.Name)
|
||||
} else {
|
||||
log.Printf("%s already has a partition table\n", blk.Name)
|
||||
me.parted.SetText("Partition " + blk.Name + " (has partitions)")
|
||||
me.parted.Disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func doGui() {
|
||||
|
@ -95,7 +125,7 @@ func drawWindow(win *gadgets.GenericWindow) {
|
|||
log.Info("You must select a drive first")
|
||||
return
|
||||
}
|
||||
log.Info("TODO: figure out if the drive is in use")
|
||||
log.Info("If you got here, gdisk should be safe to run on", me.currentDev.Name)
|
||||
})
|
||||
|
||||
grid.NextRow()
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HasPartitionTable runs `parted <device> print` and returns:
|
||||
// - true if the disk has a recognized partition table
|
||||
// - false if it's unrecognized or empty
|
||||
func hasPartitionTable(dev string) (bool, error) {
|
||||
cmd := exec.Command("parted", "-s", dev, "print")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &out
|
||||
|
||||
err := cmd.Run()
|
||||
output := out.String()
|
||||
|
||||
// Check for known "no label" pattern
|
||||
if strings.Contains(output, "unrecognised disk label") ||
|
||||
strings.Contains(output, "unrecognized disk label") ||
|
||||
strings.Contains(output, "Error") {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("parted failed: %w: %s", err, output)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
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
|
||||
}
|
Loading…
Reference in New Issue