Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os: os.Stat says broken symlinks do not exist as checked by os.IsNotExist() #53437

Closed
quackduck opened this issue Jun 18, 2022 · 4 comments
Closed

Comments

@quackduck
Copy link

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

$ go version
go version go1.18.3 darwin/arm64

Does this issue reproduce with the latest release?

Yes

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

go env Output
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/ishan/Library/Caches/go-build"
GOENV="/Users/ishan/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/ishan/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/ishan/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/opt/go/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/opt/go/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.18.3"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/_d/8s653yvs3rjcnwqy_dc45wh40000gn/T/go-build2011038208=/tmp/go-build -gno-record-gcc-switches -fno-common"

To reproduce:

  1. Make a file and a symlink pointing to that file
  2. Delete the file
  3. Check if the symlink exists according to os

I made a program that does this: https://go.dev/play/p/pCoJBeM6-rC

Code
package main

import (
	"fmt"
	"os"
)

func main() {
	_, err := os.Create("file")
	check(err)
	err = os.Symlink("file", "symlink")
	check(err)
	err = os.Remove("file")
	check(err)

	_, err = os.Stat("symlink")
	if os.IsNotExist(err) {
		fmt.Println(err) // shouldn't run, because we never deleted the symlink
	}
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

What did you expect to see?

That os says the symlink exists (even if the file it points to doesn't).

What did you see instead?

An error that the symlink does not exist.

@ZekeLu
Copy link
Contributor

ZekeLu commented Jun 18, 2022

I think you want to use https://pkg.go.dev/os#Lstat in this case.

@quackduck
Copy link
Author

That fixes it, but I don't see why os.Stat should say the symlink does not exist when it does exist.

@ianlancetaylor
Copy link
Contributor

That's how os.Stat works: it reports information about the target of the symlink. If the target does not exist, that is what it reports. If you want information about the symlink itself, you have to use os.Lstat, as @ZekeLu suggests.

This is consistent with the C functions stat and `lstat.

Closing because there is anything to do here.

@ianlancetaylor ianlancetaylor closed this as not planned Won't fix, can't repro, duplicate, stale Jun 18, 2022
@quackduck
Copy link
Author

Ah, thanks

@golang golang locked and limited conversation to collaborators Jun 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants