From 6e1b203b756fbc658f2addfe4c1be2ddb3f02897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikul=C3=A1=C5=A1=20D=C3=ADt=C4=9B?= Date: Wed, 21 Mar 2018 13:58:25 +0100 Subject: [PATCH] add symlink depth limit to symwalk Closes #3700 Rough performance implications of given depth: limit=5 completes in 1s 10 in 4s 20 in 8.4 s 30 did not complete in 73s --- pkg/sympath/walk.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pkg/sympath/walk.go b/pkg/sympath/walk.go index 77fa04153..5cb6c409a 100644 --- a/pkg/sympath/walk.go +++ b/pkg/sympath/walk.go @@ -33,11 +33,12 @@ import ( // output deterministic but means that for very large directories Walk can be // inefficient. Walk follows symbolic links. func Walk(root string, walkFn filepath.WalkFunc) error { + const nestedSymlinkLimit = 5 info, err := os.Lstat(root) if err != nil { err = walkFn(root, nil, err) } else { - err = symwalk(root, info, walkFn) + err = symwalk(root, info, walkFn, nestedSymlinkLimit) } if err == filepath.SkipDir { return nil @@ -62,7 +63,10 @@ func readDirNames(dirname string) ([]string, error) { } // symwalk recursively descends path, calling walkFn. -func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { +func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc, nestedSymlinkLimit int) error { + if nestedSymlinkLimit <= 0 { + return nil + } // Recursively walk symlinked directories. if IsSymlink(info) { resolved, err := filepath.EvalSymlinks(path) @@ -72,7 +76,7 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { if info, err = os.Lstat(resolved); err != nil { return err } - if err := symwalk(resolved, info, walkFn); err != nil && err != filepath.SkipDir { + if err := symwalk(resolved, info, walkFn, nestedSymlinkLimit-1); err != nil && err != filepath.SkipDir { return err } } @@ -98,7 +102,11 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { return err } } else { - err = symwalk(filename, fileInfo, walkFn) + if IsSymlink(fileInfo) { + err = symwalk(filename, fileInfo, walkFn, nestedSymlinkLimit-1) + } else { + err = symwalk(filename, fileInfo, walkFn, nestedSymlinkLimit) + } if err != nil { if (!fileInfo.IsDir() && !IsSymlink(fileInfo)) || err != filepath.SkipDir { return err