Release 2026.09.27.r001: support array disk rsync backups to mounted USB disks

This commit is contained in:
Mikei386 committed 2026-09-27 16:07:00 +02:00
1 parent 5009dc202b
commit 106f9c9387
13 files changed
+252 -15

No files matched your search

+30 -8
View File
@@ -16,7 +16,12 @@ type DirectoryEntry struct {
var browseRoots = []string{"/mnt/user", "/mnt/disks", "/mnt/remotes", "/boot"}
func BrowseDirectories(path string) ([]DirectoryEntry, error) {
clean, err := validateBrowsePath(path)
mounts, _ := mountedPaths()
return browseDirectories(path, storageBrowseRoots(mounts))
}
func browseDirectories(path string, roots []string) ([]DirectoryEntry, error) {
clean, err := validateBrowsePathWithRoots(path, roots)
if err != nil {
return nil, err
}
@@ -26,17 +31,29 @@ func BrowseDirectories(path string) ([]DirectoryEntry, error) {
}
result := make([]DirectoryEntry, 0, len(entries))
for _, entry := range entries {
if entry.IsDir() && entry.Type()&os.ModeSymlink == 0 {
result = append(result, DirectoryEntry{Name: entry.Name(), Path: filepath.Join(clean, entry.Name())})
child := filepath.Join(clean, entry.Name())
if entry.Type()&os.ModeSymlink != 0 {
if _, err := validateBrowsePathWithRoots(child, roots); err != nil {
continue
}
info, err := os.Stat(child)
if err != nil || !info.IsDir() {
continue
}
} else if !entry.IsDir() {
continue
}
result = append(result, DirectoryEntry{Name: entry.Name(), Path: child})
}
sort.Slice(result, func(i, j int) bool { return strings.ToLower(result[i].Name) < strings.ToLower(result[j].Name) })
return result, nil
}
func BrowseRoots() []DirectoryEntry {
result := make([]DirectoryEntry, 0, len(browseRoots))
for _, root := range browseRoots {
mounts, _ := mountedPaths()
roots := storageBrowseRoots(mounts)
result := make([]DirectoryEntry, 0, len(roots))
for _, root := range roots {
if info, err := os.Stat(root); err == nil && info.IsDir() {
result = append(result, DirectoryEntry{Name: root, Path: root})
}
@@ -45,6 +62,11 @@ func BrowseRoots() []DirectoryEntry {
}
func validateBrowsePath(path string) (string, error) {
mounts, _ := mountedPaths()
return validateBrowsePathWithRoots(path, storageBrowseRoots(mounts))
}
func validateBrowsePathWithRoots(path string, roots []string) (string, error) {
if path == "" || path == "/" {
return "", errors.New("validation: select an allowed browse root")
}
@@ -53,7 +75,7 @@ func validateBrowsePath(path string) (string, error) {
return "", errors.New("validation: browse path must be absolute")
}
allowed := false
for _, root := range browseRoots {
for _, root := range roots {
if clean == root || strings.HasPrefix(clean, root+string(os.PathSeparator)) {
allowed = true
break
@@ -66,9 +88,9 @@ func validateBrowsePath(path string) (string, error) {
if err != nil {
return "", err
}
for _, root := range browseRoots {
for _, root := range roots {
if resolved == root || strings.HasPrefix(resolved, root+string(os.PathSeparator)) {
return resolved, nil
return clean, nil
}
}
return "", errors.New("validation: browse path resolves outside allowed Unraid storage roots")