2015-10-07 23:22:09 -05:00
|
|
|
package util
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
)
|
|
|
|
|
2019-01-28 15:37:44 -06:00
|
|
|
//ErrWalkSkipDir is the Error returned when we want to skip descending into a directory
|
|
|
|
var ErrWalkSkipDir = errors.New("skip this directory")
|
2015-10-07 23:22:09 -05:00
|
|
|
|
|
|
|
//WalkFunc is a callback function called for each path as a directory is walked
|
|
|
|
//If resolvedPath != "", then we are following symbolic links.
|
|
|
|
type WalkFunc func(resolvedPath string, info os.FileInfo, err error) error
|
|
|
|
|
|
|
|
//Walk walks a path, optionally following symbolic links, and for each path,
|
|
|
|
//it calls the walkFn passed.
|
|
|
|
//
|
|
|
|
//It is similar to filepath.Walk, except that it supports symbolic links and
|
|
|
|
//can detect infinite loops while following sym links.
|
|
|
|
//It solves the issue where your WalkFunc needs a path relative to the symbolic link
|
|
|
|
//(resolving links within walkfunc loses the path to the symbolic link for each traversal).
|
|
|
|
func Walk(path string, followSymlinks bool, detectSymlinkInfiniteLoop bool, walkFn WalkFunc) error {
|
|
|
|
info, err := os.Lstat(path)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
var symlinkPathsFollowed map[string]bool
|
|
|
|
var resolvedPath string
|
|
|
|
if followSymlinks {
|
|
|
|
resolvedPath = path
|
|
|
|
if detectSymlinkInfiniteLoop {
|
|
|
|
symlinkPathsFollowed = make(map[string]bool, 8)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return walk(path, info, resolvedPath, symlinkPathsFollowed, walkFn)
|
|
|
|
}
|
|
|
|
|
|
|
|
//walk walks the path. It is a helper/sibling function to Walk.
|
|
|
|
//It takes a resolvedPath into consideration. This way, paths being walked are
|
|
|
|
//always relative to the path argument, even if symbolic links were resolved).
|
|
|
|
//
|
|
|
|
//If resolvedPath is "", then we are not following symbolic links.
|
|
|
|
//If symlinkPathsFollowed is not nil, then we need to detect infinite loop.
|
2016-03-02 08:11:24 -06:00
|
|
|
func walk(path string, info os.FileInfo, resolvedPath string, symlinkPathsFollowed map[string]bool, walkFn WalkFunc) error {
|
2015-10-07 23:22:09 -05:00
|
|
|
if info == nil {
|
|
|
|
return errors.New("Walk: Nil FileInfo passed")
|
|
|
|
}
|
|
|
|
err := walkFn(resolvedPath, info, nil)
|
|
|
|
if err != nil {
|
2019-01-28 15:37:44 -06:00
|
|
|
if info.IsDir() && err == ErrWalkSkipDir {
|
2015-10-07 23:22:09 -05:00
|
|
|
err = nil
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if resolvedPath != "" && info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
|
|
|
path2, err := os.Readlink(resolvedPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
//vout("SymLink Path: %v, links to: %v", resolvedPath, path2)
|
|
|
|
if symlinkPathsFollowed != nil {
|
|
|
|
if _, ok := symlinkPathsFollowed[path2]; ok {
|
|
|
|
errMsg := "Potential SymLink Infinite Loop. Path: %v, Link To: %v"
|
|
|
|
return fmt.Errorf(errMsg, resolvedPath, path2)
|
|
|
|
}
|
Outdent code after if block that ends with return (golint)
This commit fixes the following golint warnings:
pkg/bus/bus.go:64:9: if block ends with a return statement, so drop this else and outdent its block
pkg/bus/bus.go:84:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:137:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:177:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:183:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:199:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:208:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/components/dynmap/dynmap.go:236:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:242:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:257:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:263:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:278:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:284:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:299:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:331:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:350:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:356:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:366:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:390:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:396:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:405:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:427:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:433:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:442:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:459:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:465:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:474:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:491:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:497:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:506:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:523:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:529:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:538:12: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:555:9: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:561:10: if block ends with a return statement, so drop this else and outdent its block
pkg/components/dynmap/dynmap.go:570:12: if block ends with a return statement, so drop this else and outdent its block
pkg/login/ldap.go:55:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/login/ldap_test.go:372:10: if block ends with a return statement, so drop this else and outdent its block
pkg/middleware/middleware_test.go:213:12: if block ends with a return statement, so drop this else and outdent its block
pkg/plugins/dashboard_importer.go:153:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/dashboards_updater.go:39:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/dashboards_updater.go:121:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/plugins.go:210:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/plugins/plugins.go:235:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/eval_context.go:111:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:92:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:98:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifier.go:122:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:108:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:118:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/rule.go:121:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/alerting/notifiers/telegram.go:94:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/annotation.go:34:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/annotation.go:99:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/dashboard_test.go:107:13: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/plugin_setting.go:78:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/preferences.go:91:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/user.go:50:10: if block ends with a return statement, so drop this else and outdent its block
pkg/services/sqlstore/migrator/migrator.go:106:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/services/sqlstore/migrator/postgres_dialect.go:48:10: if block ends with a return statement, so drop this else and outdent its block
pkg/tsdb/time_range.go:59:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/tsdb/time_range.go:67:9: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
pkg/tsdb/cloudwatch/metric_find_query.go:225:9: if block ends with a return statement, so drop this else and outdent its block
pkg/util/filepath.go:68:11: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary)
2018-04-27 15:42:49 -05:00
|
|
|
symlinkPathsFollowed[path2] = true
|
2015-10-07 23:22:09 -05:00
|
|
|
}
|
|
|
|
info2, err := os.Lstat(path2)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return walk(path, info2, path2, symlinkPathsFollowed, walkFn)
|
|
|
|
}
|
|
|
|
if info.IsDir() {
|
|
|
|
list, err := ioutil.ReadDir(path)
|
|
|
|
if err != nil {
|
|
|
|
return walkFn(resolvedPath, info, err)
|
|
|
|
}
|
2016-03-03 04:02:18 -06:00
|
|
|
var subFiles = make([]subFile, 0)
|
2015-10-07 23:22:09 -05:00
|
|
|
for _, fileInfo := range list {
|
|
|
|
path2 := filepath.Join(path, fileInfo.Name())
|
|
|
|
var resolvedPath2 string
|
|
|
|
if resolvedPath != "" {
|
|
|
|
resolvedPath2 = filepath.Join(resolvedPath, fileInfo.Name())
|
|
|
|
}
|
2016-03-03 04:02:18 -06:00
|
|
|
subFiles = append(subFiles, subFile{path: path2, resolvedPath: resolvedPath2, fileInfo: fileInfo})
|
|
|
|
}
|
|
|
|
|
|
|
|
if containsDistFolder(subFiles) {
|
|
|
|
err := walk(
|
|
|
|
filepath.Join(path, "dist"),
|
|
|
|
info,
|
|
|
|
filepath.Join(resolvedPath, "dist"),
|
|
|
|
symlinkPathsFollowed,
|
|
|
|
walkFn)
|
|
|
|
|
2015-10-07 23:22:09 -05:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-03-03 04:02:18 -06:00
|
|
|
} else {
|
|
|
|
for _, p := range subFiles {
|
|
|
|
err = walk(p.path, p.fileInfo, p.resolvedPath, symlinkPathsFollowed, walkFn)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2015-10-07 23:22:09 -05:00
|
|
|
}
|
2016-03-03 04:02:18 -06:00
|
|
|
|
2015-10-07 23:22:09 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2016-03-02 08:11:24 -06:00
|
|
|
|
2016-03-03 04:02:18 -06:00
|
|
|
type subFile struct {
|
|
|
|
path, resolvedPath string
|
|
|
|
fileInfo os.FileInfo
|
|
|
|
}
|
2016-03-02 08:11:24 -06:00
|
|
|
|
2016-03-03 04:02:18 -06:00
|
|
|
func containsDistFolder(subFiles []subFile) bool {
|
|
|
|
for _, p := range subFiles {
|
|
|
|
if p.fileInfo.IsDir() && p.fileInfo.Name() == "dist" {
|
2016-03-02 08:11:24 -06:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|