Skip to content
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

Add try_canonicalize to rustc_fs_util and use it over fs::canonicalize #109231

Merged
merged 1 commit into from
Mar 23, 2023

Conversation

Zoxc
Copy link
Contributor

@Zoxc Zoxc commented Mar 16, 2023

This adds try_canonicalize which tries to call fs::canonicalize, but falls back to std::path::absolute if it fails. Existing canonicalize calls are replaced with it. fs::canonicalize is not guaranteed to work on Windows.

@rustbot
Copy link
Collaborator

rustbot commented Mar 16, 2023

r? @WaffleLapkin

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 16, 2023
@rustbot
Copy link
Collaborator

rustbot commented Mar 16, 2023

These commits modify the Cargo.lock file. Random changes to Cargo.lock can be introduced when switching branches and rebasing PRs.
This was probably unintentional and should be reverted before this PR is merged.

If this was intentional then you can ignore this comment.

These commits modify compiler targets.
(See the Target Tier Policy.)

@WaffleLapkin
Copy link
Member

r? compiler

@rustbot rustbot assigned eholk and unassigned WaffleLapkin Mar 17, 2023
Copy link
Member

@ChrisDenton ChrisDenton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some Windows background info:

  • The canonicalize function will fail on filesystem drivers that don't fully implement the kernel interface (most notably ImDisk RAM drives).
  • Paths starting with \\?\ (which canonicalize returns) are sometimes necessary to avoid path length limitations. However, std will now take care of this automatically.
  • std::path::absolute gets an absolute path without touching the filesystem, thus it should never fail on a valid path. However, it does not resolve symlinks.

So trying fs::canonicalize and falling back to path::absolute will suite most cases. The only issue I see would be if it's vital for symlinks to be resolved. (I did have a patch that would make canonicalize work even in the presence of ImDisk but people were understandably nervous of the weird paths it produces in that case).

@eholk
Copy link
Contributor

eholk commented Mar 23, 2023

fs::canonicalize is not guaranteed to work on Windows.

Is this something that's fixable? Or would the fix just be to move try_canonicalize to the standard library?

@eholk
Copy link
Contributor

eholk commented Mar 23, 2023

@bors r+

@bors
Copy link
Contributor

bors commented Mar 23, 2023

📌 Commit 4f7cd3d has been approved by eholk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 23, 2023
@ChrisDenton
Copy link
Member

fs::canonicalize is not guaranteed to work on Windows.

Is this something that's fixable?

It's fixable if either a) we fix all the faulty drivers in the world or b) are ok with returning some weird paths. The first would be fairly difficult to do and the second is seen as being far from ideal.

Or would the fix just be to move try_canonicalize to the standard library?

We could have a function that attempts to clean up the . and .. parts from paths in whatever way works (which I think is what people usually want) but that doesn't promise to resolve symlinks.

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 23, 2023
…iaskrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#106964 (Clarify `Error::last_os_error` can be weird)
 - rust-lang#107718 (Add `-Z time-passes-format` to allow specifying a JSON output for `-Z time-passes`)
 - rust-lang#107880 (Lint ambiguous glob re-exports)
 - rust-lang#108549 (Remove issue number for `link_cfg`)
 - rust-lang#108588 (Fix the ffi_unwind_calls lint documentation)
 - rust-lang#109231 (Add `try_canonicalize` to `rustc_fs_util` and use it over `fs::canonicalize`)
 - rust-lang#109472 (Add parentheses properly for method calls)
 - rust-lang#109487 (Move useless_anynous_reexport lint into unused_imports)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@Zoxc
Copy link
Contributor Author

Zoxc commented Mar 23, 2023

I'm starting to think that std::fs::canonicalize should be changed to be best effort. I'm not sure what use cases there are where you need it to fail. It can't be used to resolve aliasing in general.

@ChrisDenton
Copy link
Member

That would be a breaking change so isn't on the table. More over there are cases (e.g. in security contexts) where you do actually want to resolve symlinks. So it is a useful function. A new function would be a better way forward.

@bors bors merged commit 2a39cf5 into rust-lang:master Mar 23, 2023
@rustbot rustbot added this to the 1.70.0 milestone Mar 23, 2023
@Zoxc
Copy link
Contributor Author

Zoxc commented Mar 24, 2023

GetFinalPathNameByHandle is documented to have a fallback path for SMB, do you know if this can silently fail to resolve symlinks / reparse points?

I guess we kind of need a function which returns absolute paths which can resolve .. to make paths more user presentable. std::path::absolute would be a faster alternative for internal use, but it wouldn't be suitable if you want to remove .. so it's less of a std::fs::canonicalize drop-in.

@ChrisDenton
Copy link
Member

If an SMB server can't resolve a component it will return an error (although of course this is ultimately up to the remote server, which can just straight up lie if it wants to).

std::path::absolute works on paths that don't exist. This is a big benefit over alternatives and sometimes is the only option (e.g. before you create the file/directories). Properly resolving .. on Unix systems requires accessing the filesystem so, indeed, absolute cannot be used for that case. I'd agree that a different function would be required for that.

bors added a commit to rust-lang/cargo that referenced this pull request Apr 8, 2023
Add `try_canonicalize` and use it over `std::fs::canonicalize`

This adds a `try_canonicalize` function that calls `std::fs::canonicalize` and on Windows falls back to getting an absolute path. Uses of `canonicalize` have been replaced with `std::fs::canonicalize`. On Windows `std::fs::canonicalize` may fail due to incomplete drivers. In particular `ImDisk` does not support it.

Combined with rust-lang/rust#109231 this allows compiling crates on an `ImDisk` RAM disk and I've tested that it works with various configuration using [rcb](https://github.com/Zoxc/rcb).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants