-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: Symlink returns Cannot create a file when that file already exists #53582
Comments
Per the Go release policy, For that matter, how are you running an What was the exact command line that you ran to run the test? Some versions of Windows require that the program be run with Administrator privileges to create symlinks; Windows 10 and after also allows other users to create symlinks if the device is in Developer Mode. If symlinks are not enabled, that should cause |
yes, this issue can reproduce with the latest release go1.18.3。I have run the test with Administrator privileges to create symlinks,and it can create symlinks but it returns errror。I just show the existence of this problem through this test。You can call symlink after calling zone and the problem will arise |
Please tell us exactly what you are doing, and exactly what happens. If you are modifying the code that comes with Go, please show us the complete file that you are running. Thanks. |
I don't modify the code that comes with Go.You can run this test: func TestSymlink(t *testing.T) {
now := time.Now()
now.Zone()
from, to := "symlinktestfrom", "symlinktestto"
file, err := os.Create(to)
if err != nil {
t.Fatalf("Create(%q) failed: %v", to, err)
}
if err = file.Close(); err != nil {
t.Errorf("Close(%q) failed: %v", to, err)
}
err = os.Symlink(to, from)
if err != nil {
t.Fatalf("Symlink(%q, %q) failed: %v", to, from, err)
}
} === RUN TestSymlink
util_test.go:71: Symlink("symlinktestto", "symlinktestfrom") failed: symlink symlinktestto symlinktestfrom: Cannot create a file when that file already exists.
--- FAIL: TestSymlink (0.02s)
FAIL |
Hmm, I don't reproduce this. Could you please test with adding small sleep? func TestSymlink(t *testing.T) {
now := time.Now()
now.Zone()
from, to := "symlinktestfrom", "symlinktestto"
file, err := os.Create(to)
if err != nil {
t.Fatalf("Create(%q) failed: %v", to, err)
}
if err = file.Close(); err != nil {
t.Errorf("Close(%q) failed: %v", to, err)
}
time.Sleep(1 * time.Second)
err = os.Symlink(to, from)
if err != nil {
t.Fatalf("Symlink(%q, %q) failed: %v", to, from, err)
}
} |
|
Do you always check that symlinktestfrom does not exist before testing? |
yes |
I debug the code. The code src\os\file_windows.go:369 returns ERROR_ACCESS_DENIED (5), but the symbolic link has been created, then CreateSymbolicLink in src\os\file_windows.go:374 creates it again go 1.18.3 code from src\os\file_windows.go:364 var flags uint32 = windows.SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
if isdir {
flags |= syscall.SYMBOLIC_LINK_FLAG_DIRECTORY
}
err = syscall.CreateSymbolicLink(n, o, flags) // returns ERROR_ACCESS_DENIED (5) but the symbolic link has been created
if err != nil {
// the unprivileged create flag is unsupported
// below Windows 10 (1703, v10.0.14972). retry without it.
flags &^= windows.SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
err = syscall.CreateSymbolicLink(n, o, flags) // then it creates again
if err != nil {
return &LinkError{"symlink", oldname, newname, err}
}
}
return nil |
I don't understand what happen on this case, but at least os.Symlink for Window should not do second try if err is not ERROR_PRIVILEGE_NOT_HELD, I think. diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index db5c27dd30..c0cb501450 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -368,6 +368,9 @@ func Symlink(oldname, newname string) error {
}
err = syscall.CreateSymbolicLink(n, o, flags)
if err != nil {
+ if err.(syscall.Errno) != syscall.ERROR_PRIVILEGE_NOT_HELD {
+ return &LinkError{"symlink", oldname, newname, err}
+ }
// the unprivileged create flag is unsupported
// below Windows 10 (1703, v10.0.14972). retry without it.
flags &^= windows.SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE |
Change https://go.dev/cl/415094 mentions this issue: |
@zdszxp It sounds like you are saying that even though |
yes, i don't know.If I remove the code about time, os.Symlink executes correctly |
This is a question, but another question is, why it will return ERROR_ACCESS_DENIED) in windows10, when I call now.Zone before calling os.Symlink, but the link is still created successfully, if I remove the code about time, os.Symlink executes correctly |
@zdszxp why do you use I cannot reproduce your issue here. I run this test https://go.dev/play/p/TMpFxBKkafD as simple user on my local
As simple user on
And locally as an Administrator:
Perhaps you can try and put some println in Go library code and figure out what is happening on your PC. Please note that your system environment will affect your result. See #53582 (comment) for example. I also noticed that CreateSymbolicLink API uses Not sure what to do here. Alex |
Timed out in state WaitingForInfo. Closing. (I am just a bot, though. Please speak up if this is a mistake or you have the requested information.) |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I ran this test (go\src\os\os_test.go's TestSymlink):
What did you expect to see?
I expected the test to pass.
What did you see instead?
If I don't add the relevant code about the time, the test passes, but if I add it, the link can't be created
The text was updated successfully, but these errors were encountered: