v0.12.3 — Security & correctness bug fixes (33 bugs)
CRITICAL: 10 data race and security fixes — backup.go mutex coverage (C1-C4), IsSystemDisk 12-bit major/minor (C5), /dev/ path validation (C6), extractName traversal (C7), TargetPath/DestinationPath against registered paths (C8-C9), ParseComposeHDDMounts Clean-before-prefix (C10). HIGH: 17 logic/resource fixes — ValidateDump bufio.Scanner (H1), single appDirSize() with 30s timeout (H2/H3), snapshot ID regex (H4), cross-drive restic prune (H5), temp file order (H6), dirSizeBytes errors (H7), atomic fstab (H8), IsDeviceMounted suffix check (H9), eMMC partition mapping (H10), bytesCopied mutex (H11), separator-aware migrate prefix (H13), DeleteStack error on compose-down (H14), docker 60s timeout (H16), NotificationPrefs deep-copy (H17), wipefs warning (H18), fstab rollback on mount fail (H19). MEDIUM: 7 code quality fixes — formatBytes dedup (M1), .tmp filter order (M2), sizeBytes string type (M3), elapsed in message (M6), LoadLocation fallback (M7), pathCovers separator (M10), cancelEditLabel textContent (M11). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
package backup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -76,8 +78,7 @@ func DiscoverAppData(provider StackDataProvider, backupPrefs map[string]bool, di
|
||||
path := AppDataPath{HostPath: mount}
|
||||
if fi, err := os.Stat(mount); err == nil && fi.IsDir() {
|
||||
path.Exists = true
|
||||
path.SizeBytes = appDirSizeBytes(mount)
|
||||
path.SizeHuman = appDirSizeHuman(mount)
|
||||
path.SizeBytes, path.SizeHuman = appDirSize(mount)
|
||||
}
|
||||
info.HDDPaths = append(info.HDDPaths, path)
|
||||
info.HDDTotalSize += path.SizeBytes
|
||||
@@ -131,34 +132,23 @@ func parseComposeNamedVolumes(composePath string) []AppDockerVolume {
|
||||
return volumes
|
||||
}
|
||||
|
||||
// appDirSizeHuman returns a human-readable size string for a directory using du.
|
||||
func appDirSizeHuman(path string) string {
|
||||
cmd := exec.Command("du", "-sh", path)
|
||||
// appDirSize returns the total byte count and a human-readable string for a directory.
|
||||
// H2/H3: Single du invocation with 30s timeout replaces two separate calls.
|
||||
func appDirSize(path string) (int64, string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, "du", "-sb", path)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "?"
|
||||
return 0, "?"
|
||||
}
|
||||
fields := strings.Fields(string(output))
|
||||
if len(fields) > 0 {
|
||||
return fields[0]
|
||||
if len(fields) == 0 {
|
||||
return 0, "?"
|
||||
}
|
||||
return "?"
|
||||
}
|
||||
|
||||
// appDirSizeBytes returns the total size in bytes for a directory.
|
||||
func appDirSizeBytes(path string) int64 {
|
||||
cmd := exec.Command("du", "-sb", path)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
fields := strings.Fields(string(output))
|
||||
if len(fields) > 0 {
|
||||
var size int64
|
||||
fmt.Sscanf(fields[0], "%d", &size)
|
||||
return size
|
||||
}
|
||||
return 0
|
||||
var size int64
|
||||
fmt.Sscanf(fields[0], "%d", &size)
|
||||
return size, humanizeBytes(size)
|
||||
}
|
||||
|
||||
// humanizeBytes converts bytes to a human-readable string.
|
||||
|
||||
Reference in New Issue
Block a user