Reapply the fix from #1054, but without getting into an infinite look in case of SMB fs errors. See #1164

This commit is contained in:
Deluan 2021-07-17 21:06:53 -04:00
parent 03ad6e972a
commit e61cf3217d
2 changed files with 105 additions and 15 deletions

View file

@ -2,8 +2,10 @@ package scanner
import (
"context"
"io/fs"
"os"
"path/filepath"
"testing/fstest"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -78,8 +80,85 @@ var _ = Describe("walk_dir_tree", func() {
Expect(isDirIgnored(baseDir, dirEntry)).To(BeFalse())
})
})
Describe("fullReadDir", func() {
var fsys fakeFS
var ctx context.Context
BeforeEach(func() {
ctx = context.Background()
fsys = fakeFS{MapFS: fstest.MapFS{
"root/a/f1": {},
"root/b/f2": {},
"root/c/f3": {},
}}
})
It("reads all entries", func() {
dir, _ := fsys.Open("root")
entries := fullReadDir(ctx, dir.(fs.ReadDirFile))
Expect(entries).To(HaveLen(3))
Expect(entries[0].Name()).To(Equal("a"))
Expect(entries[1].Name()).To(Equal("b"))
Expect(entries[2].Name()).To(Equal("c"))
})
It("skips entries with permission error", func() {
fsys.failOn = "b"
dir, _ := fsys.Open("root")
entries := fullReadDir(ctx, dir.(fs.ReadDirFile))
Expect(entries).To(HaveLen(2))
Expect(entries[0].Name()).To(Equal("a"))
Expect(entries[1].Name()).To(Equal("c"))
})
It("aborts if it keeps getting 'readdirent: no such file or directory'", func() {
fsys.err = fs.ErrNotExist
dir, _ := fsys.Open("root")
entries := fullReadDir(ctx, dir.(fs.ReadDirFile))
Expect(entries).To(BeEmpty())
})
})
})
type fakeFS struct {
fstest.MapFS
failOn string
err error
}
func (f *fakeFS) Open(name string) (fs.File, error) {
dir, err := f.MapFS.Open(name)
return &fakeDirFile{File: dir, fail: f.failOn, err: f.err}, err
}
type fakeDirFile struct {
fs.File
entries []fs.DirEntry
pos int
fail string
err error
}
// Only works with n == -1
func (fd *fakeDirFile) ReadDir(n int) ([]fs.DirEntry, error) {
if fd.err != nil {
return nil, fd.err
}
if fd.entries == nil {
fd.entries, _ = fd.File.(fs.ReadDirFile).ReadDir(-1)
}
var dirs []fs.DirEntry
for {
if fd.pos >= len(fd.entries) {
break
}
e := fd.entries[fd.pos]
fd.pos++
if e.Name() == fd.fail {
return dirs, &fs.PathError{Op: "lstat", Path: e.Name(), Err: fs.ErrPermission}
}
dirs = append(dirs, e)
}
return dirs, nil
}
func getDirEntry(baseDir, name string) (os.DirEntry, error) {
dirEntries, _ := os.ReadDir(baseDir)
for _, entry := range dirEntries {