fix(samba): separate storage-ROOT validation from share-TARGET validation

Live validation caught it: the 'new folder' flow passed the storage root through
sharingResolvePath, which (correctly) refuses the drive root as a share target —
so share creation silently failed. sharingResolveStorageRoot accepts EXACTLY a
registered live root (strictly tighter) and is used only as the new-folder parent.
Regression test asserts both halves.
This commit is contained in:
2026-07-18 11:54:35 +02:00
parent 2eef9b2e4a
commit b409f5eee2
2 changed files with 71 additions and 1 deletions
@@ -115,6 +115,43 @@ func TestSharingResolvePath_UniformRefusal(t *testing.T) {
}
}
// The "new folder" flow validates the storage ROOT, which the share-target guard rightly refuses.
// Regression guard for the live-validation bug: reusing sharingResolvePath there broke share
// creation entirely (the root is never a valid share TARGET, but is the valid PARENT).
func TestSharingResolveStorageRoot(t *testing.T) {
s, drive := newSharingServer(t)
// The registered root is accepted here...
if got, err := s.sharingResolveStorageRoot(drive); err != nil || got == "" {
t.Errorf("a registered storage root must be accepted as a new-folder parent, got %q err=%v", got, err)
}
// ...even though it is (correctly) refused as a share TARGET.
if _, err := s.sharingResolvePath(drive); err == nil {
t.Error("the drive root must still be refused as a share target")
}
// Anything that is not EXACTLY a registered live root is refused.
for _, bad := range []string{
filepath.Join(drive, "media"), // a subdir is not a root
filepath.Join(drive, "appdata"),
t.TempDir(), // unregistered
"relative",
"",
} {
if _, err := s.sharingResolveStorageRoot(bad); err == nil {
t.Errorf("%q must not be accepted as a storage root", bad)
}
}
// A decommissioned root stops being a valid parent.
if err := s.settings.SetDecommissioned(drive, ""); err != nil {
t.Fatal(err)
}
if _, err := s.sharingResolveStorageRoot(drive); err == nil {
t.Error("a decommissioned root must not accept new folders")
}
}
// pathWithin must be segment-wise: a sibling directory sharing a name PREFIX is not containment.
func TestPathWithin_SiblingPrefixIsNotContainment(t *testing.T) {
if pathWithin("/mnt/drive-evil/x", "/mnt/drive") {