fs/torrentfs.go | 24 ++++++++++++------------ fs/torrentfs_test.go | 19 +++++++++++++++++++ diff --git a/fs/torrentfs.go b/fs/torrentfs.go index ea2ae4e9c61ab34aab58ef600e035c15882e790c..9b3f3958768532a1497d9befbd450a4ba2d64928 100644 --- a/fs/torrentfs.go +++ b/fs/torrentfs.go @@ -4,6 +4,7 @@ import ( "expvar" "fmt" "os" + "path" "strings" "sync" @@ -46,7 +47,7 @@ fs *TorrentFS } type node struct { - path []string + path string metadata *metainfo.Info FS *TorrentFS t torrent.Torrent @@ -65,7 +66,7 @@ return nil } func (n *node) fsPath() string { - return "/" + strings.Join(append([]string{n.metadata.Name}, n.path...), "/") + return "/" + n.metadata.Name + "/" + n.path } func blockingRead(ctx context.Context, fs *TorrentFS, t torrent.Torrent, off int64, p []byte) (n int, err error) { @@ -151,22 +152,21 @@ _ fusefs.HandleReadDirAller = dirNode{} _ fusefs.HandleReader = fileNode{} ) -func isSubPath(parent, child []string) bool { - if len(child) <= len(parent) { +func isSubPath(parent, child string) bool { + if !strings.HasPrefix(child, parent) { return false } - for i := range parent { - if parent[i] != child[i] { - return false - } + s := child[len(parent):] + if len(s) == 0 { + return false } - return true + return s[0] == '/' } func (dn dirNode) ReadDirAll(ctx context.Context) (des []fuse.Dirent, err error) { names := map[string]bool{} for _, fi := range dn.metadata.Files { - if !isSubPath(dn.path, fi.Path) { + if !isSubPath(dn.path, strings.Join(fi.Path, "/")) { continue } name := fi.Path[len(dn.path)] @@ -190,7 +190,7 @@ func (dn dirNode) Lookup(ctx context.Context, name string) (_node fusefs.Node, err error) { var torrentOffset int64 for _, fi := range dn.metadata.Files { - if !isSubPath(dn.path, fi.Path) { + if !isSubPath(dn.path, strings.Join(fi.Path, "/")) { torrentOffset += fi.Length continue } @@ -199,7 +199,7 @@ torrentOffset += fi.Length continue } __node := dn.node - __node.path = append(__node.path, name) + __node.path = path.Join(__node.path, name) if len(fi.Path) == len(dn.path)+1 { _node = fileNode{ node: __node, diff --git a/fs/torrentfs_test.go b/fs/torrentfs_test.go index a83a0cd536f09a761e303ad9446d4869b3980956..8ae89e1c30bd33237942751f0b8767f91315fc08 100644 --- a/fs/torrentfs_test.go +++ b/fs/torrentfs_test.go @@ -15,9 +15,12 @@ "strings" "testing" "time" + _ "github.com/anacrolix/envpprof" + "bazil.org/fuse" fusefs "bazil.org/fuse/fs" "github.com/anacrolix/missinggo" + "github.com/stretchr/testify/assert" netContext "golang.org/x/net/context" "github.com/anacrolix/torrent" @@ -253,3 +256,19 @@ if string(content) != testutil.GreetingFileContents { t.Fatalf("%q != %q", string(content), testutil.GreetingFileContents) } } + +func TestIsSubPath(t *testing.T) { + for _, case_ := range []struct { + parent, child string + is bool + }{ + {"", "", false}, + {"", "/", true}, + {"a/b", "a/bc", false}, + {"a/b", "a/b", false}, + {"a/b", "a/b/c", true}, + {"a/b", "a//b", false}, + } { + assert.Equal(t, case_.is, isSubPath(case_.parent, case_.child)) + } +}