Skip to content

path/filepath: Walk reports unreadable directories twice #21758

@LMMilewski

Description

@LMMilewski

What version of Go are you using (go version)?

$ go version
go version go1.9 darwin/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/pol/lm/"
GORACE=""
GOROOT="/Users/pol/go1.9"
GOTOOLDIR="/Users/pol/go1.9/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-p
refix-map=/var/folders/gg/1phmfkb169g24y_s7w7v0q_r0000gp/T/go-build230951228=/tmp/go-build -gno-record
-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

The following test fails:

package filepath_test

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"testing"
)

func Test(t *testing.T) {
	dir, err := ioutil.TempDir("/tmp/", "fptest")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}

	crdir := filepath.Join(dir, "cant-read")
	if err := os.Mkdir(crdir, 0300); err != nil {
		t.Fatalf("Mkdir(%s) failed: %v", err)
	}

	var got []string
	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		got = append(got, path)
		return nil
	})
	if err != nil {
		t.Errorf("Walk(%s) failed: %v", dir, dir)
	}

	want := []string{dir, crdir}
	if !reflect.DeepEqual(got, want) {
		t.Errorf("Walk was called with paths %s; want %s", got, want)
	}
}

with this output:

--- FAIL: Test (0.00s)
filepath_test.go:33: Walk was called with paths [/tmp/fptest478009460 /tmp/fptest478009460/cant-read /tmp/fptest478009460/cant-read]; want [/tmp/fptest478009460 /tmp/fptest478009460/cant-read]

That is "/tmp/fptest478009460/cant-read" (which has permissions 0300) is reported twice (once with err==nil and once with err!=nil).

This isn't reproducible on the playground: https://play.golang.org/p/ofa6fpGuVq

What did you expect to see?

Two calls to my WalkFunc:

  1. path==/tmp/fptest478009460 err==nil
  2. path==/tmp/fptest478009460/cant-read err !=nil

What did you see instead?

Three calls to my WalkFunc:

  1. path==/tmp/fptest478009460 err==nil
  2. path==/tmp/fptest478009460/cant-read err ==nil
  3. path==/tmp/fptest478009460/cant-read err !=nil

The result surprised me at first, but it's not entirely unreasonable. If this is intended behavior then I'd argue that at least the documentation should be updated.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions