bdbe170a54
New storage watchdog monitors registered storage paths every 5s. On disconnect (3 consecutive probe failures), auto-stops affected apps, lazy-unmounts stale VFS entries, fires alerts/notifications/hub report. On reconnect (UUID detected), auto-remounts via fstab, cleans stale restic locks, offers app restart. Safe disconnect UI for USB drives: confirmation dialog, stop apps, sync, unmount. Disconnected state visible across all pages (dashboard, settings, backups, monitoring) with hatched red bars and badges. Backup guards skip disconnected drives. 22 files changed (1 new: monitor/watchdog.go), ~1500 lines added. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
110 lines
2.6 KiB
Go
110 lines
2.6 KiB
Go
//go:build !linux
|
|
|
|
package system
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// IsMountPoint always returns true on non-Linux (assume OK for dev/testing).
|
|
func IsMountPoint(_ string) bool { return true }
|
|
|
|
// IsWritable checks if the given path is writable by attempting to create+remove a temp file.
|
|
func IsWritable(path string) bool {
|
|
testFile := filepath.Join(path, ".felhom-write-test")
|
|
f, err := os.Create(testFile)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
f.Close()
|
|
os.Remove(testFile)
|
|
return true
|
|
}
|
|
|
|
// PathsOverlap returns true if one path is a parent or child of the other.
|
|
func PathsOverlap(a, b string) bool {
|
|
a = filepath.Clean(a)
|
|
b = filepath.Clean(b)
|
|
if a == b {
|
|
return true
|
|
}
|
|
aSep := a + string(os.PathSeparator)
|
|
bSep := b + string(os.PathSeparator)
|
|
return strings.HasPrefix(aSep, bSep) || strings.HasPrefix(bSep, aSep)
|
|
}
|
|
|
|
// DiskUsageInfo holds disk usage statistics for a path.
|
|
type DiskUsageInfo struct {
|
|
TotalGB float64
|
|
UsedGB float64
|
|
AvailGB float64
|
|
UsedPercent float64
|
|
TotalHuman string
|
|
UsedHuman string
|
|
}
|
|
|
|
// GetDiskUsage returns nil on non-Linux.
|
|
func GetDiskUsage(_ string) *DiskUsageInfo { return nil }
|
|
|
|
// FSInfo holds filesystem type, device, and disk model info.
|
|
type FSInfo struct {
|
|
FSType string
|
|
Device string
|
|
Model string
|
|
}
|
|
|
|
// GetFSInfo returns nil on non-Linux.
|
|
func GetFSInfo(_ string) *FSInfo { return nil }
|
|
|
|
// DestinationHealth holds the result of a tiered backup destination check.
|
|
type DestinationHealth struct {
|
|
Exists bool
|
|
Writable bool
|
|
MountPoint bool
|
|
SystemDrive bool
|
|
UsedPercent float64
|
|
FreeGB float64
|
|
Warning string
|
|
Blocked bool
|
|
Severity string
|
|
}
|
|
|
|
// CheckBackupDestination always returns ok on non-Linux (assume healthy for dev/testing).
|
|
func CheckBackupDestination(path string) DestinationHealth {
|
|
return DestinationHealth{
|
|
Exists: true,
|
|
Writable: true,
|
|
MountPoint: true,
|
|
Severity: "ok",
|
|
}
|
|
}
|
|
|
|
// ProbeStatus represents the result of a storage path probe.
|
|
type ProbeStatus int
|
|
|
|
const (
|
|
ProbeConnected ProbeStatus = iota
|
|
ProbeDisconnected
|
|
ProbeTimeout
|
|
)
|
|
|
|
// ProbeResult holds the outcome of a storage path probe.
|
|
type ProbeResult struct {
|
|
Status ProbeStatus
|
|
Err error
|
|
}
|
|
|
|
// ProbeStoragePath always returns connected on non-Linux.
|
|
func ProbeStoragePath(_ string) ProbeResult { return ProbeResult{Status: ProbeConnected} }
|
|
|
|
// IsUSBDevice always returns false on non-Linux.
|
|
func IsUSBDevice(_ string) bool { return false }
|
|
|
|
// ParseFstabUUID always returns empty on non-Linux.
|
|
func ParseFstabUUID(_, _ string) string { return "" }
|
|
|
|
// HasFelhomRawMount always returns false on non-Linux.
|
|
func HasFelhomRawMount(_, _ string) (string, bool) { return "", false }
|