SMB shares and NFS exports may now point to any existing directory (USB disks under /mnt or /media, /srv, home folders...) instead of only ZFS dataset mountpoints. System trees (/etc, /usr, /var, /boot, /proc, /root, ...) are refused, also after resolving symlinks. The path suggestions list mounted data filesystems from /proc/self/mounts in addition to ZFS mountpoints. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package shares
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// pseudoFS are filesystem types that never hold user data.
|
||||
var pseudoFS = map[string]bool{
|
||||
"proc": true, "sysfs": true, "tmpfs": true, "devtmpfs": true, "devpts": true, "cgroup": true, "cgroup2": true,
|
||||
"securityfs": true, "pstore": true, "bpf": true, "debugfs": true, "tracefs": true, "configfs": true,
|
||||
"fusectl": true, "mqueue": true, "hugetlbfs": true, "autofs": true, "binfmt_misc": true, "nsfs": true,
|
||||
"overlay": true, "squashfs": true, "efivarfs": true, "rpc_pipefs": true, "nfsd": true, "ramfs": true,
|
||||
}
|
||||
|
||||
// ParseMounts extracts shareable mountpoints from /proc/self/mounts content:
|
||||
// real filesystems outside system directories, sorted and de-duplicated.
|
||||
func ParseMounts(data string) []string {
|
||||
seen := map[string]bool{}
|
||||
var out []string
|
||||
for _, line := range strings.Split(data, "\n") {
|
||||
f := strings.Fields(line)
|
||||
if len(f) < 3 || pseudoFS[f[2]] {
|
||||
continue
|
||||
}
|
||||
mp := unescapeMount(f[1])
|
||||
if !strings.HasPrefix(mp, "/") || ValidateNotSystem(mp) != nil || seen[mp] {
|
||||
continue
|
||||
}
|
||||
seen[mp] = true
|
||||
out = append(out, mp)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// unescapeMount decodes the octal escapes (\040 etc.) the kernel uses in mounts.
|
||||
func unescapeMount(s string) string {
|
||||
if !strings.Contains(s, `\`) {
|
||||
return s
|
||||
}
|
||||
var b strings.Builder
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == '\\' && i+4 <= len(s) {
|
||||
if n, err := strconv.ParseUint(s[i+1:i+4], 8, 8); err == nil {
|
||||
b.WriteByte(byte(n))
|
||||
i += 3
|
||||
continue
|
||||
}
|
||||
}
|
||||
b.WriteByte(s[i])
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
Reference in New Issue
Block a user