/* Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ package helm import ( "log" "os" "path/filepath" "sort" "github.com/pkg/errors" ) // copied from 3.12.1 "helm.sh/helm/v3/internal/sympath" // Walk walks the file tree rooted at root, calling walkFn for each file or directory // in the tree, including root. All errors that arise visiting files and directories // are filtered by walkFn. The files are walked in lexical order, which makes the // 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 { info, err := os.Lstat(root) if err != nil { err = walkFn(root, nil, err) } else { err = symwalk(root, info, walkFn) } if err == filepath.SkipDir { return nil } return err } // readDirNames reads the directory named by dirname and returns // a sorted list of directory entries. func readDirNames(dirname string) ([]string, error) { f, err := os.Open(dirname) if err != nil { return nil, err } names, err := f.Readdirnames(-1) f.Close() if err != nil { return nil, err } sort.Strings(names) return names, nil } // symwalk recursively descends path, calling walkFn. func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { // Recursively walk symlinked directories. if isSymlink(info) { resolved, err := filepath.EvalSymlinks(path) if err != nil { return errors.Wrapf(err, "error evaluating symlink %s", path) } log.Printf("found symbolic link in path: %s resolves to %s. Contents of linked file included and used", path, resolved) if info, err = os.Lstat(resolved); err != nil { return err } if err := symwalk(path, info, walkFn); err != nil && err != filepath.SkipDir { return err } return nil } if err := walkFn(path, info, nil); err != nil { return err } if !info.IsDir() { return nil } names, err := readDirNames(path) if err != nil { return walkFn(path, info, err) } for _, name := range names { filename := filepath.Join(path, name) fileInfo, err := os.Lstat(filename) if err != nil { if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir { return err } } else { err = symwalk(filename, fileInfo, walkFn) if err != nil { if (!fileInfo.IsDir() && !isSymlink(fileInfo)) || err != filepath.SkipDir { return err } } } } return nil } // isSymlink is used to determine if the fileinfo is a symbolic link. func isSymlink(fi os.FileInfo) bool { return fi.Mode()&os.ModeSymlink != 0 }