feat: format empty partitions on system disk (v0.32.6)
Detect and offer to format empty (no filesystem) partitions on the system disk. Adds IsSystemPartition() for granular per-partition safety checks instead of blocking the entire system disk. Init wizard shows formatable partitions with appropriate warnings. Add felhotest demo node to docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@ package storage
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -46,6 +47,68 @@ func IsSystemDisk(devicePath string) (bool, error) {
|
||||
return rootDiskGroup == devDiskGroup, nil
|
||||
}
|
||||
|
||||
// IsSystemPartition checks if a specific partition is a system partition
|
||||
// (/, /boot, /boot/efi, swap) or is currently mounted.
|
||||
// Unlike IsSystemDisk() which blocks the entire disk, this checks only the
|
||||
// individual partition — allowing non-system partitions on system disks to be formatted.
|
||||
func IsSystemPartition(partitionPath string) (bool, error) {
|
||||
fstabPath := "/host-fstab"
|
||||
if _, err := os.Stat(fstabPath); err != nil {
|
||||
fstabPath = "/etc/fstab"
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(fstabPath)
|
||||
if err != nil {
|
||||
// If we can't read fstab, err on the side of caution
|
||||
return true, fmt.Errorf("cannot read fstab: %w", err)
|
||||
}
|
||||
|
||||
systemMounts := map[string]bool{"/": true, "/boot": true, "/boot/efi": true}
|
||||
|
||||
for _, line := range strings.Split(string(data), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 3 {
|
||||
continue
|
||||
}
|
||||
source := fields[0]
|
||||
mountPoint := fields[1]
|
||||
fsType := fields[2]
|
||||
|
||||
if !systemMounts[mountPoint] && fsType != "swap" {
|
||||
continue
|
||||
}
|
||||
|
||||
var devPath string
|
||||
if strings.HasPrefix(source, "UUID=") {
|
||||
uuid := strings.TrimPrefix(source, "UUID=")
|
||||
if out, err := exec.Command("blkid", "-U", uuid).Output(); err == nil {
|
||||
devPath = strings.TrimSpace(string(out))
|
||||
}
|
||||
} else if strings.HasPrefix(source, "/dev/") {
|
||||
devPath = source
|
||||
}
|
||||
|
||||
if devPath == partitionPath {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Also check if the partition is currently mounted
|
||||
mounted, err := IsDeviceMounted(partitionPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if mounted {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// IsDeviceMounted checks if a device or any of its partitions is currently mounted.
|
||||
func IsDeviceMounted(devicePath string) (bool, error) {
|
||||
data, err := os.ReadFile("/proc/mounts")
|
||||
|
||||
Reference in New Issue
Block a user