build / build (push) Successful in 1m7s
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>
56 lines
1.5 KiB
Go
56 lines
1.5 KiB
Go
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()
|
|
}
|