rustup: rustup fails with symlink RUSTUP_HOME/toolchains
Problem
% rustup update
error: I/O Error: Too many levels of symbolic links (os error 40)
BTW: This message isn’t very helpful.
I’m having a symlink at ~/.rustup/toolchains pointing to ~/.cache/rustup/toolchains
Steps
mkdir ~/rustup-test && cd ~/.rustup && cp -r downloads tmp update-hashes settings.toml ~/rustup-testln -s ~/.rustup/toolchains ~/rustup-test/RUSTUP_HOME=$HOME/rustup-test rustup update
Possible Solution(s)
No response
Notes
This happens since the update from
nightly-x86_64-unknown-linux-gnu updated - rustc 1.78.0-nightly (3b1717c05 2024-03-10) (from rustc 1.78.0-nightly (2d24fe591 2024-03-09))
stable-x86_64-unknown-linux-gnu unchanged - rustc 1.76.0 (07dca489a 2024-02-04)
to
nightly-x86_64-unknown-linux-gnu updated - rustc 1.78.0-nightly (3cbb93223 2024-03-13) (from rustc 1.78.0-nig
htly (3b1717c05 2024-03-10))
stable-x86_64-unknown-linux-gnu unchanged - rustc 1.76.0 (07dca489a 2024-02-04)
% RUSTUP_HOME=$HOME/rustup-test strace -Zk -e t=openat rustup update
10:27:49.009219 openat(AT_FDCWD</home/joerg/git/rustup>, "/home/joerg/kein_Backup/rustup-test/toolchains", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = -1 ELOOP (Too many levels of symbolic links) <0.000013>
> /usr/lib/x86_64-linux-gnu/libc.so.6(__open64+0x51) [0xf7861]
> /home/joerg/.cache/cargo/bin/rustup(std::sys::unix::fs::File::open_c+0xe8) [0x511148]
> /home/joerg/.cache/cargo/bin/rustup(std::fs::OpenOptions::_open+0x12a) [0x5391fa]
> /home/joerg/.cache/cargo/bin/rustup(rustup::toolchain::toolchain::Toolchain::exists+0x172) [0x3fb192]
> /home/joerg/.cache/cargo/bin/rustup(rustup::toolchain::toolchain::Toolchain::new+0x34) [0x3fac74]
> /home/joerg/.cache/cargo/bin/rustup(rustup::toolchain::distributable::DistributableToolchain::new+0x3f) [0x3d92af]
> /home/joerg/.cache/cargo/bin/rustup(<core::iter::adapters::GenericShunt<I,R> as core::iter::traits::iterator::Iterator>::next+0xf80) [0x4e8550]
> /home/joerg/.cache/cargo/bin/rustup(rustup::config::Cfg::list_channels+0x9a) [0x4e692a]
> /home/joerg/.cache/cargo/bin/rustup(rustup::cli::rustup_mode::update+0x3b6) [0x4a38c6]
> /home/joerg/.cache/cargo/bin/rustup(rustup::cli::rustup_mode::main+0x1b2d) [0x47e09d]
> /home/joerg/.cache/cargo/bin/rustup(rustup_init::main+0x1262) [0xeea32]
> /home/joerg/.cache/cargo/bin/rustup(std::sys_common::backtrace::__rust_begin_short_backtrace+0x3) [0xec8c3]
> /home/joerg/.cache/cargo/bin/rustup(main+0x414) [0xef3c4]
> /usr/lib/x86_64-linux-gnu/libc.so.6(__libc_init_first+0x8a) [0x276ca]
> /usr/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x85) [0x27785]
> /home/joerg/.cache/cargo/bin/rustup(_start+0x29) [0xec7f7]
error: I/O Error: Too many levels of symbolic links (os error 40)
Rustup version
rustup 1.27.0 (bbb9276d2 2024-03-08)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.79.0-nightly (2f090c30d 2024-03-23)`
Installed toolchains
Default host: x86_64-unknown-linux-gnu
rustup home: /home/joerg/.rustup
installed toolchains
--------------------
stable-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu (default)
active toolchain
----------------
nightly-x86_64-unknown-linux-gnu (default)
rustc 1.79.0-nightly (2f090c30d 2024-03-23)
About this issue
- Original URL
- State: closed
- Created 3 months ago
- Comments: 16 (11 by maintainers)
Commits related to this issue
- fix(utils): don't use `O_NOFOLLOW` in `open_dir()` Fixes #3737. ## Concerns - [ ] Testing: can we bake a smoke test to prevent regression? — committed to rust-lang/rustup by rami3l 3 months ago
- test(cli): ensure the resolution of #3737 — committed to rust-lang/rustup by rami3l 3 months ago
- test(cli): ensure the resolution of #3737 — committed to rust-lang/rustup by rami3l 3 months ago
- test(cli): ensure the resolution of #3737 — committed to rust-lang/rustup by rami3l 3 months ago
- test(cli): ensure the resolution of #3737 — committed to rust-lang/rustup by rami3l 3 months ago
- test(cli): ensure the resolution of #3737 — committed to rust-lang/rustup by rami3l 3 months ago
- test(cli): ensure the resolution of #3737 — committed to rust-lang/rustup by rami3l 3 months ago
It works:
Yes. To downgrade, download an older version of rustup-init from the dist server https://static.rust-lang.org/rustup and run it to install it.
the env variable RUSTUP_UPDATE_ROOT will override that, so if you set it to an empty web host in your environment, rustup will no longer be able to self-update.
Or, you can pass --no-self-update to rustup when you invoke an update / install. If you’re using an IDE that invokes rustup, consult its documentation.
Indeed thanks for the bug.
@rami3l I think what we need here for .rustup/toolchains and .rustup/downloads, but not for directories in general, are the following semantics:
I think remove_dir_all + the fs_at crates should permit solving this quite nicely.
re remove_dir_all behaviour, see https://docs.rs/remove_dir_all/0.8.2/remove_dir_all/ the last two paragraphs before ‘features’. tl;dr symlinks are not directories, and if you’re dealing with a symlink, just unlink, don’t expect remove_dir_all to delete it.
re: the semantics on windows, the implementation details are different, but roughly identical semantics are achievable - the open with FILE_FLAG_BACKUP_SEMANTICS is required to read the link out of a link, compared to linux where a different syscall is used to read links.
Happy to review a patch.
It’s not about self-referential symlinks. As you can see in the
stracethe flagO_NOFOLLOWgets passed to theopenat, which causes not even one symlink is crossed.With a self compiled version you get
Which points to https://github.com/rust-lang/rustup/blob/0c501d55c54031a992395078d535b6d2574dc693/src/utils/raw.rs#L45-L54 that adds the NOFOLLOW flag
contrary to
Toolchain::exists()https://github.com/rust-lang/rustup/blob/0c501d55c54031a992395078d535b6d2574dc693/src/toolchain/toolchain.rs#L70-L74Here’s a git-bisect run. A good version was 1.25.0, and the culprit is 2c9297d51a077d9a364e98ad8ebaee2301cd0c0d.