package storage import ( "bufio" "fmt" "log" "strings" ) // FormatRequest holds parameters for formatting and mounting a disk. type FormatRequest struct { DevicePath string // "/dev/sdb" or "/dev/sdb1" MountName string // "hdd_1" → mounts at /mnt/hdd_1 Label string // Display label for the UI CreatePartition bool // If true, create a single partition first (wipes disk) SetDefault bool // Register as default storage path Logger *log.Logger // Optional logger for debug output Debug bool // Enable debug logging } // FormatProgress tracks the formatting/mounting progress. type FormatProgress struct { Step string // "validating","partitioning","formatting","mounting","permissions","done","error" Message string // Human-readable status Error string // Non-empty if Step == "error" Percent int // 0–100 } // parseRsyncProgress parses a single line of rsync --info=progress2 output. // Returns (bytesCopied, percent, ok). func parseRsyncProgress(line string) (int64, int, bool) { // Format: " 45,678,901 49% 12.34MB/s 0:00:30" scanner := bufio.NewScanner(strings.NewReader(line)) scanner.Split(bufio.ScanWords) var tokens []string for scanner.Scan() { tokens = append(tokens, scanner.Text()) } if len(tokens) < 2 { return 0, 0, false } bytesStr := strings.ReplaceAll(tokens[0], ",", "") var bytesCopied int64 if _, err := fmt.Sscanf(bytesStr, "%d", &bytesCopied); err != nil { return 0, 0, false } pctStr := strings.TrimSuffix(tokens[1], "%") var pct int if _, err := fmt.Sscanf(pctStr, "%d", &pct); err != nil { return 0, 0, false } return bytesCopied, pct, true }