-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: RemoveAll fails for long file paths #27029
Comments
Reproducible on 1.11 too, leaving this for the 1.12 cycle since it's not a recent regression. |
Nice bug, thanks! (When I saw the title I feared this was our Windows long paths bug creeping up again and I was afraid we hadn't fixed it correctly the first time. Glad to see it's a new bug and amused that it's on Linux.) /cc @ianlancetaylor |
This is pretty hard to fix in a portable way, but I agree that we should probably start using |
Some more thoughts on this:
The following fails with the same error. Also if you
File systems usually have a maximum filename length of 255 chars and linux has a max filepath limit of 4096. The same limit seems to apply to Darwin. I would argue that regardless of the filepath limit, This leaves a few options: 1. Patch os
|
I don't think we need to support the general case of very long file names for |
Sounds fine. We can always do more later if needed. |
We've been looking at a fitting implementation here. For this to be solved, a
The /cc @gcapizzi |
@ostenbom Thanks for looking into this. Our preference where the standard library requires system call support that is not presently in the syscall package is to add that support to the internal/syscall/unix package. That way we can let the standard library do what it needs without adding new API to the syscall package. |
Ok @ianlancetaylor @bradfitz, we're working on a version according to your comments. There is a The questions we have are:
Other resources on understanding how the Thanks cc @gcapizzi |
Thanks. Seems like the right basic idea. removeall_unix.go is an OK name but perhaps the other file should be removeall_nonunix.go. Or perhaps there is a better implementation possible for Windows, I don't really know, in which case we would have removeall_unix.go, removeall_windows.go, removeall_plan9.go. Since For the test, yes, skip it for systems that don't support it. Build constraints are documented at https://golang.org/pkg/go/build . |
Ok, great. We have a working implementation now that passes all tests, in the same branch. The only problem we have now is knowing the trap numbers for the We started making |
I'm sorry for jumping in, but just wanted to mention that some time ago we had a similar problem where files could "hide" in directories way past We solved the problem generally by writing a walker that iteratively navigated deep directories by changing CWD. File operations on any files found that deep were done locally, no attempts to pass a very large filename through a syscall. This worked on all operating systems supported by Go. Code is here: github.com/mirtchovski/walk |
@mirtchovski Right doing the recursive chdir would rid us of long path names, but would probably have concurrency issues if, say, several goroutines were calling |
It definitely doesn't work well with concurrent walks. We usually do normal walking for most things and only trigger the deep path if we encounter nested directories beyond a certain depth. Usually in a separate process. |
On unix systems, long enough path names will fail on doing syscall like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <julianedialkova@hotmail.com> Change-Id: I9d8a634bb7a479e5ef80fc346aeff478bde1f607
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <julianedialkova@hotmail.com> Change-Id: Ibfa8fd2b60f49c34ad5468a13f9d459d32fe8af5
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <julianedialkova@hotmail.com> Change-Id: Ibfa8fd2b60f49c34ad5468a13f9d459d32fe8af5
@ostenbom The simplest approach is to write the code so that it falls back to normal behavior if the Also note that on many systems the number is already available as |
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com> Change-Id: I21730a61c70a38b2fcef8dbab6cae4eca3f95f05
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com> Change-Id: I21730a61c70a38b2fcef8dbab6cae4eca3f95f05
Change https://golang.org/cl/137442 mentions this issue: |
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com> Change-Id: I6a965569beb113c10a52967d5ea0294fcd8dd9d6
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux and darwin. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com> Change-Id: I80ed34170fd826c008d596f36a1534ea40a17ea6
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com> Change-Id: I77dfe62a28d86e7cbcfb5aa0b19a7651572c416b
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
Change https://golang.org/cl/145839 mentions this issue: |
This was reverted by https://go-review.googlesource.com/c/go/+/145897 (which didn't reference this issue). |
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
Change https://golang.org/cl/146020 mentions this issue: |
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin, freebsd and openbsd. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin and openbsd. Not yet implemented on freebsd due to fstatat 64-bit inode compatibility issues. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
On unix systems, long enough path names will fail when performing syscalls like `Lstat`. The current RemoveAll uses several of these syscalls, and so will fail for long paths. This can be risky, as it can let users "hide" files from the system or otherwise make long enough paths for programs to fail. By using `Unlinkat` and `Openat` syscalls instead, RemoveAll is safer on unix systems. Initially implemented for linux, darwin and openbsd. Not yet implemented on freebsd due to fstatat 64-bit inode compatibility issues. Fixes golang#27029 Co-authored-by: Giuseppe Capizzi <gcapizzi@pivotal.io> Co-authored-by: Julia Nedialkova <yulia.nedyalkova@sap.com>
Follow CL 146020 and enable RemoveAll based on Unlinkat and Openat on solaris. Updates #27029 Change-Id: I0b0e92f4422fa960a13dcd3e9adb57cd23f09ed4 Reviewed-on: https://go-review.googlesource.com/c/145839 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Change https://golang.org/cl/146597 mentions this issue: |
Follow CL 146020 and enable RemoveAll based on Unlinkat and Openat on freebsd. Since the layout of syscall.Stat_t changes in FreeBSD 12, Fstatat needs a compatibility wrapper akin to Fstatat in x/sys/unix. See CL 138595 and CL 136816 for details. Updates #27029 Change-Id: I8851a5b7fa658eaa6e69a1693150b16d9a68f36a Reviewed-on: https://go-review.googlesource.com/c/146597 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Yuval Pavel Zholkover <paulzhol@gmail.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Change https://golang.org/cl/146937 mentions this issue: |
Follow CL 146020 and enable RemoveAll based on Unlinkat and Openat on aix. Updates #27029 Change-Id: I78b34ed671166ee6fa651d5f2025b88548ee6c68 Reviewed-on: https://go-review.googlesource.com/c/146937 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Clément Chigot <clement.chigot@atos.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
What version of Go are you using (
go version
)?go version go1.10.3 linux/amd64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?Linux, amd64
What did you do?
Make a long file path (> 4096 chars).
os.RemoveAll(path)
.What did you expect to see?
Success.
What did you see instead?
it fails with
file name too long
.Suggested solutions
We have worked around this using
unix.Openat
andunix.Unlinkat
in our code base, but this solution would only work on unix.The problem really is with os.Remove, whose unix syscalls don't accept long file paths. An alternate solution would be to alter os.Remove to split long path names on unix systems.
We'd be happy to submit pull requests for either approach.
cc @Callisto13
The text was updated successfully, but these errors were encountered: