Skip to content

Commit 5b82b99

Browse files
Do not ignore symlinks when listing store contents (#2344)
* Do not ignore symlinks when listing store contents Fixes #2173 RELEASE_NOTES=[BUGFIX] Do not ignore symlinks when listing Signed-off-by: Dominik Schulz <[email protected]> * Do not init map with magic constant. Signed-off-by: Dominik Schulz <[email protected]> Signed-off-by: Dominik Schulz <[email protected]>
1 parent 00d04c4 commit 5b82b99

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

internal/backend/storage/fs/store.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,13 @@ func (s *Store) Exists(ctx context.Context, name string) bool {
151151
func (s *Store) List(ctx context.Context, prefix string) ([]string, error) {
152152
prefix = strings.TrimPrefix(prefix, "/")
153153
debug.Log("Listing %s/%s", s.path, prefix)
154+
154155
files := make([]string, 0, 100)
155-
if err := filepath.Walk(s.path, func(path string, info os.FileInfo, err error) error {
156+
if err := walkSymlinks(s.path, func(path string, info os.FileInfo, err error) error {
156157
if err != nil {
157158
return err
158159
}
160+
159161
relPath := strings.TrimPrefix(path, s.path+string(filepath.Separator)) + string(filepath.Separator)
160162
if info.IsDir() && strings.HasPrefix(info.Name(), ".") && path != s.path && !strings.HasPrefix(prefix, relPath) && filepath.Base(path) != filepath.Base(prefix) {
161163
debug.Log("skipping dot dir (relPath: %s, prefix: %s)", relPath, prefix)
@@ -175,6 +177,7 @@ func (s *Store) List(ctx context.Context, prefix string) ([]string, error) {
175177
if !strings.HasPrefix(name, prefix) {
176178
return nil
177179
}
180+
178181
files = append(files, name)
179182

180183
return nil

internal/backend/storage/fs/walk.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package fs
2+
3+
import (
4+
"io/fs"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/gopasspw/gopass/pkg/debug"
9+
)
10+
11+
func walkSymlinks(path string, walkFn filepath.WalkFunc) error {
12+
w := &walker{
13+
seen: map[string]bool{},
14+
}
15+
16+
return w.walk(path, path, walkFn)
17+
}
18+
19+
type walker struct {
20+
seen map[string]bool
21+
}
22+
23+
func (w *walker) walk(filename, linkDir string, walkFn filepath.WalkFunc) error {
24+
sWalkFn := func(path string, info fs.FileInfo, err error) error {
25+
fname, err := filepath.Rel(filename, path)
26+
if err != nil {
27+
return err
28+
}
29+
path = filepath.Join(linkDir, fname)
30+
31+
if info.Mode()&fs.ModeSymlink == fs.ModeSymlink {
32+
destPath, err := filepath.EvalSymlinks(path)
33+
if err != nil {
34+
return err
35+
}
36+
37+
// avoid loops
38+
if w.seen[destPath] {
39+
debug.Log("Symlink loop detected at %s!", destPath)
40+
41+
return nil
42+
}
43+
w.seen[destPath] = true
44+
45+
destInfo, err := os.Lstat(destPath)
46+
if err != nil {
47+
return walkFn(path, destInfo, err)
48+
}
49+
50+
if destInfo.IsDir() {
51+
return w.walk(destPath, path, walkFn)
52+
}
53+
}
54+
55+
return walkFn(path, info, err)
56+
}
57+
58+
return filepath.Walk(filename, sWalkFn)
59+
}

0 commit comments

Comments
 (0)