Skip to content

os: Seek suceeds for directories where it should error #45046

@tmthrgd

Description

@tmthrgd

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

$ go version
go version go1.16.2 linux/amd64

Does this issue reproduce with the latest release?

Yes with tip.

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

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/tom/.cache/go-build"
GOENV="/home/tom/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/tom/go/pkg/mod"
GONOPROXY=...
GONOSUMDB=...
GOOS="linux"
GOPATH="/home/tom/go"
GOPRIVATE=...
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/tom/sdk/go1.16.2"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/tom/sdk/go1.16.2/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.2"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build14584737=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I was looking through the os directory reading source code and I noticed that Seeks EISDIR error condition is broken.

Seek checks if the os-specific seek method succeeded for a file that has a dirinfo:

go/src/os/file.go

Lines 239 to 241 in f02a26b

if e == nil && f.dirinfo != nil && r != 0 {
e = syscall.EISDIR
}

Unfortunately the seek method always clears dirinfo (#35767 and #37161):

go/src/os/file_unix.go

Lines 269 to 274 in 78f9015

if f.dirinfo != nil {
// Free cached dirinfo, so we allocate a new one if we
// access this file as a directory again. See #35767 and #37161.
f.dirinfo.close()
f.dirinfo = nil
}

This script should reproduce the error when run locally:

https://play.golang.org/p/brgpk5je9tP

As an aside: I'm not sure this is the best way handle Seek-ing a directory, it will only trigger if readdir was previously called and, on Linux at least, only after the seek has actually succeeded.

What did you expect to see?

Seek returned a syscall.EISDIR error.

What did you see instead?

Seek returned without error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions