Description
On AIX, unlinkat or rmdir syscall doesn't work on the CWD. Therefore, a program like the following one doesn't remove GOPATH.
$ cat removeall.go
package main
import (
"io/ioutil"
"log"
"os"
)
func main() {
GOPATH, err := ioutil.TempDir("", "TestRemoveAll")
if err != nil {
log.Panic(err)
}
if err := os.Chdir(GOPATH); err != nil {
log.Panic(err)
}
if err := os.Remove(GOPATH); err != nil {
log.Panic(err)
}
}
$ ./removeall.go
2019/05/22 09:29:19 remove /tmp/TestRemoveAll186232865: device busy
panic: remove /tmp/TestRemoveAll186232865: device busy
goroutine 1 [running]:
log.Panic(0xa00010000088f58, 0x1, 0x1)
/opt/freeware/src/packages/BUILD/go-root/src/log/log.go:338 +0x9c
main.main()
/opt/freeware/src/packages/BUILD/go-root/own_test/goprogs/removeall.go:19 +0x138
exit status 2
There is no real documentation on that. However, rmdir seems to return EBUSY and unlinkat EPERM. So, we should be able to detect if os.Remove is failing because of that. However, what's the correct behavior if we want to fix that ?
Do we chdir to the parentdir ? "/tmp" ? the executable folder ? anything else ?
Or do we want to keep this behavior ?
Note that, when calling os.Removeall, everything except the directory itself is still being removed. Therefore, only a empty directory remains. But, as most of the tests are doing a defer os.Removeall
, /tmp is filled with empty directories...
Do some other OSes have the same problem ?
Edit: POSIX rmdir doesn't specify which behavior must be done (cf https://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html)
If the directory is the root directory or the current working directory of any process, it is unspecified whether the function succeeds, or whether it shall fail and set errno to [EBUSY].