io/fs, path/filepath: honor SkipDir on second WalkDirFunc error call

Fixes #51617

Change-Id: I03e9e575d9bad1481e7e4f051b50a077ba5f2fe0
Reviewed-on: https://go-review.googlesource.com/c/go/+/392154
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
This commit is contained in:
Ian Lance Taylor 2022-03-12 16:18:23 -08:00
parent 3c7f9b8022
commit 460fd63ccc
4 changed files with 74 additions and 0 deletions

View File

@ -76,6 +76,9 @@ func walkDir(fsys FS, name string, d DirEntry, walkDirFn WalkDirFunc) error {
// Second call, to report ReadDir error.
err = walkDirFn(name, d, err)
if err != nil {
if err == SkipDir && d.IsDir() {
err = nil
}
return err
}
}

View File

@ -8,6 +8,8 @@ import (
. "io/fs"
"os"
pathpkg "path"
"path/filepath"
"reflect"
"testing"
"testing/fstest"
)
@ -122,3 +124,34 @@ func TestWalkDir(t *testing.T) {
}
checkMarks(t, true)
}
func TestIssue51617(t *testing.T) {
dir := t.TempDir()
for _, sub := range []string{"a", filepath.Join("a", "bad"), filepath.Join("a", "next")} {
if err := os.Mkdir(filepath.Join(dir, sub), 0755); err != nil {
t.Fatal(err)
}
}
bad := filepath.Join(dir, "a", "bad")
if err := os.Chmod(bad, 0); err != nil {
t.Fatal(err)
}
defer os.Chmod(bad, 0700) // avoid errors on cleanup
var saw []string
err := WalkDir(os.DirFS(dir), ".", func(path string, d DirEntry, err error) error {
if err != nil {
return filepath.SkipDir
}
if d.IsDir() {
saw = append(saw, path)
}
return nil
})
if err != nil {
t.Fatal(err)
}
want := []string{".", "a", "a/bad", "a/next"}
if !reflect.DeepEqual(saw, want) {
t.Errorf("got directories %v, want %v", saw, want)
}
}

View File

@ -396,6 +396,9 @@ func walkDir(path string, d fs.DirEntry, walkDirFn fs.WalkDirFunc) error {
// Second call, to report ReadDir error.
err = walkDirFn(path, d, err)
if err != nil {
if err == SkipDir && d.IsDir() {
err = nil
}
return err
}
}

View File

@ -1526,3 +1526,38 @@ func TestEvalSymlinksAboveRootChdir(t *testing.T) {
t.Logf("EvalSymlinks(%q) = %q", check, resolved)
}
}
func TestIssue51617(t *testing.T) {
dir := t.TempDir()
for _, sub := range []string{"a", filepath.Join("a", "bad"), filepath.Join("a", "next")} {
if err := os.Mkdir(filepath.Join(dir, sub), 0755); err != nil {
t.Fatal(err)
}
}
bad := filepath.Join(dir, "a", "bad")
if err := os.Chmod(bad, 0); err != nil {
t.Fatal(err)
}
defer os.Chmod(bad, 0700) // avoid errors on cleanup
var saw []string
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return filepath.SkipDir
}
if d.IsDir() {
rel, err := filepath.Rel(dir, path)
if err != nil {
t.Fatal(err)
}
saw = append(saw, rel)
}
return nil
})
if err != nil {
t.Fatal(err)
}
want := []string{".", "a", filepath.Join("a", "bad"), filepath.Join("a", "next")}
if !reflect.DeepEqual(saw, want) {
t.Errorf("got directories %v, want %v", saw, want)
}
}