-
Notifications
You must be signed in to change notification settings - Fork 17.5k
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
path/filepath: fix HasPrefix #18358
Comments
I was going to complain that the |
Does package os exports portable way to query if the
underlying file system is case sensitive or not?
(without creating a file and test?)
And what about symbolic links? If we want to fix it,
we should first work out its intended behavior, which
I think it's far from trivial. And I expect neither is the
implementation (there could be more than one mount
points along the path, and each could have different
case sensitivity rules), and not every program would
actually need such sophistications. (One prime example
is that we don't have os.CopyFile, even thought it's such
a nice thing to have.)
One other reason to not fix HasPrefix is because if
we did fix this, program will begin to use it, and rely
on the newly documented invariants, which are not
necessarily true under older Go version. But people
building the program with older Go versions won't
notice any build breakage, and thus will be silently
using the bad implementation. I think this will cause
more problem that it solves for the developer. (That
is, I believe, once something is declared deprecated,
it should never be taken out of that status again, or
change behavior, for that matter.)
If we want to fix this issue, I suggest that we add a
new function in Go 1.9.
|
I think the runtime/debug#Stack case is different from
path/filepath.HasPrefix,
1. the original implementation is not broken, both versions show the
essential
information, just in different formats, and the new version shows more.
2. it's meant to use for debugging, so stability is not that important.
for the record, here is the difference I'm talking about:
// t.go
package main
import (
"fmt"
"runtime/debug"
)
func f(i int) {
if i == 0 {
fmt.Printf("%s\n", debug.Stack())
} else {
f(i - 1)
}
}
func main() {
f(5)
}
$ go1 run t.go
/tmp/t.go:10 (0x400c29)
f: fmt.Printf("%s\n", debug.Stack())
/tmp/t.go:12 (0x400cc8)
f: f(i - 1)
/tmp/t.go:12 (0x400cc8)
f: f(i - 1)
/tmp/t.go:12 (0x400cc8)
f: f(i - 1)
/tmp/t.go:12 (0x400cc8)
f: f(i - 1)
/tmp/t.go:12 (0x400cc8)
f: f(i - 1)
/tmp/t.go:17 (0x400ced)
main: f(5)
..../go1/src/pkg/runtime/proc.c:244 (0x40cd87)
main: main·main();
..../go1/src/pkg/runtime/proc.c:271 (0x40ce2a)
goexit: runtime·goexit(void)
$ go163 run t.go
goroutine 1 [running]:
runtime/debug.Stack(0x0, 0x0, 0x0)
..../go163/src/runtime/debug/stack.go:24 +0x80
main.f(0x0)
/tmp/t.go:10 +0x36
main.f(0x1)
/tmp/t.go:12 +0x140
main.f(0x2)
/tmp/t.go:12 +0x140
main.f(0x3)
/tmp/t.go:12 +0x140
main.f(0x4)
/tmp/t.go:12 +0x140
main.f(0x5)
/tmp/t.go:12 +0x140
main.main()
/tmp/t.go:17 +0x20
Accidentally switching to the old version won't cause much trouble. Unlike
switching
from a filesystem-aware path/filepath.HasPrefix to the old
strings.HasPrefix based
implementation.
|
Whatever we decide to do here, I think filepath.HasPrefix is useful function. We can all complain that it is hard to implement it, but then people will write they own. We have written cmd/go.hasFilePathPrefix ourselves. Why didn't we use filepath.HasPrefix in cmd/go instead? Alex |
Repost from a closed bug: (Sorry for the noise, I'm a newbie still!) Just checking: this function is deprecated, and there is no alternative? Maybe a regex.Match? I assume that's why there's interest in fixing. |
It's more complicated than regex, which is why it hasn't been solved yet. |
I think checking GOOS is good enough. |
Looks like IMO |
I've unassigned myself from this. Checking Whatever solution is proposed must handle case sensitivity properly. The approach taken by dep is a hack and assumes that the file exists. |
Another approach is using
I didn't test it well, but presumably it is more efficient than the original one. EDIT: removed unused code. |
Yes, handling errors will be a problem with your approach. Real filepath.HasPrefix returns bool. Do you return true or false, if some of your syscalls return ERROR_ACCESS_DENIED on windows? Alex |
The moment we have to make syscalls heavily implies that there is a possibility that this function can fail, which further implies that the current signature is not appropriate. We either create a new function that has an error or leave this for Go2. |
I suppose creating a new function is fine, but I don't have strong opinions. |
Oh, I think above program has a bug. Perhaps, https://play.golang.org/p/u2c-PTj3HX is correct one. |
Why your program's HasPrefix returns 2 parameters? Alex |
@alexbrainman I'm not sure which option we want to choose |
I do not see how it is possible to implement this option - see my ERROR_ACCESS_DENIED comment.
Maybe this is acceptable.
Gophers that need function like that, cannot wait for Go2. They implement they own version of this function. Alex |
I agree.
I think so.
fair. So we both have the same opinion. :) |
What would new version of filepath.HasPrefix look like? Alex |
I suppose
As @dsnet pointed it out, these code assume existence of files. |
Unrelated to previous comment, I think windows implementation should use private functions - toNorm, normBase.
So, we can also handle short filenames.
|
Is anyone working on this? It seems like a useful function. I would like to help. I think we don't have too many options. Here is the summary. In order to do it 100% correct we need to know case sensitivity of the mounted file system. As far as I know it can be done only by accessing a file/folder on that file system. (User can mount FS with different case sensitivity side by side, even Windows is going to support case sensitive FS). The existing signature doesn't really allow for that. My proposal is as follows:
Please let me know whether it makes sense. |
I think the first step is to define exactly what the function should do. |
@ianlancetaylor Here are requirements I can see right now:
Does it sound useful at all? |
It's even more complicated than that: directories can have a "is case sensitive" flag too on Windows. Linux's |
The
filepath.HasPrefix
function has been in a deprecated-like status for the past 4 years (since 2012). The reasons why it was deprecated is described in CL/5712045. The issue with respecting path boundaries is probably the most significant.Given that it's had a note steering people away for 4 years, there should be nearly no users of the function. Inside Google, there are 3 uses of it and all of them would have wanted the correct implementation. We should actually fix this function and bring it out of deprecated status.
The challenge with properly implementing it is getting the case-sensitivity correct. This is a dependent on the underlying filesystem and not the GOOS.
The text was updated successfully, but these errors were encountered: