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

syscall.Unlinkat does not pass AT_REMOVEDIR #35935

Closed
cedws opened this issue Dec 2, 2019 · 2 comments
Closed

syscall.Unlinkat does not pass AT_REMOVEDIR #35935

cedws opened this issue Dec 2, 2019 · 2 comments

Comments

@cedws
Copy link

cedws commented Dec 2, 2019

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

$ go version
go version go1.13.4 linux/amd64

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="amd64"
GOBIN=""
GOCACHE="/home/cedwards/.cache/go-build"
GOENV="/home/cedwards/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/cedwards/go:/home/cedwards/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
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-build489396315=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Ran this code, which calls Unlinkat.

package main

import (
    "syscall"
    "os"
    "log"
)

func main() {
    os.MkdirAll("dir/subdir", 0777)
    fd, _ := syscall.Open("dir", os.O_RDONLY, 0777)
    err := syscall.Unlinkat(fd, "subdir")
    log.Fatal(err)
}

What did you expect to see?

The program should print nothing (err should be nil). Internally, the standard library is expected to pass the AT_REMOVEDIR flag to libc, as per #9923.

What did you see instead?

The program prints is not a directory - the Unlinkat returns EISDIR because it requires the AT_REMOVEDIR flag. By running an strace on the above program, we can see that the AT_REMOVEDIR flag (0x200/512) is not being passed as the last parameter to Unlinkat:

readlinkat(AT_FDCWD, "/proc/self/exe", "/tmp/x/x", 128) = 8
fcntl(0, F_GETFL)                       = 0x2 (flags O_RDWR)
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7aa5733000
fcntl(1, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(2, F_GETFL)                       = 0x2 (flags O_RDWR)
newfstatat(AT_FDCWD, "dir/subdir", {st_mode=S_IFDIR|0755, st_size=40, ...}, 0) = 0
openat(AT_FDCWD, "dir", O_RDONLY)       = 3
+ unlinkat(3, "subdir", 0)                = -1 EISDIR (Is a directory)
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7aa56f3000
openat(AT_FDCWD, "/etc//localtime", O_RDONLY) = 4
read(4, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\7\0\0\0\7\0\0\0\0"..., 4096) = 3648
read(4, "", 4096)                       = 0
close(4)                                = 0
write(2, "2019/12/02 18:04:12 is a directo"..., 352019/12/02 18:04:12 is a directory
) = 35
exit_group(1)                           = ?
@cuonglm
Copy link
Member

cuonglm commented Dec 2, 2019

Duplicated #9923

@ianlancetaylor
Copy link
Contributor

The syscall package is more or less frozen. Use the golang.org/x/sys/unix package instead. There the Unlinkat function takes a flags parameter.

@golang golang locked and limited conversation to collaborators Dec 1, 2020
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