Cross platform Rust library for checking whether two file paths are the same file.
by BurntSushiRust
Last 12 weeks · 0 commits
2 of 6 standards met
Fixes #55. takes the underlying out of and hands the 's ownership back to the caller instead of dropping it. When that value is later dropped by the caller, 's impl unconditionally unwrapped for std streams (), assuming it was still . But had already emptied it, so the panicked: The fix makes tolerate an already-empty instead of assuming it's always , using in place of the unconditional . Verification** Reproduced the panic on current with , matching the exact panic site/message from the issue. Added a regression test ( in ) that fails with the same panic against the old impl and passes with the fix. (10 unit tests + 8 doc-tests) and both pass. Manually exercised all three std streams: called on , , and in a standalone binary — no panic — and additionally wrote through the fd recovered from to confirm it's still a live, usable descriptor and not just a non-panicking value. Left the pre-existing / clippy no-ops in // untouched since #67 already covers those.
On (and the other targets) compiles into the module, so and always return The effect that reaches users is through . With , calls for its symlink loop check, so on WASI every directory symlink errors and the whole subtree behind it is dropped. We hit this in rolldown, whose wasm build walks a project tree for : the native binding matches the files behind a directory symlink, the wasm binding matches none (rolldown/rolldown#10609). WASI's file API has the same shape as the unix one, and is stable on WASI, so can serve both. The one piece std does not provide is /: is still unstable (, rust-lang/rust#71213) as of Rust 1.97.1. Proposal Read the two numbers through on WASI, and let WASI share the existing module. The rest is only: becomes for the selection, the declarations and the / accessors, loses WASI, and the two imports in gain WASI counterparts. calls instead of reading the metadata inline. About 30 lines in total, and nothing changes for unix or windows. is a new dependency, which is why I am opening an issue first. Windows already pulls , so a target-gated dependency has precedent here, and this one only covers . Alternative without a new dependency preview1 exposes , and and are the first two s of , so the same values can be read through a small block and no dependency at all. That version only covers , so would keep falling back to . I have it working as well and can send it instead if you would rather not take . What I verified Builds: , , , and the host target. and are unchanged on the host. Runtime: a probe built for and run under Node 24's , over a tree containing a directory symlink and a symlink loop. Two paths to the same directory compare equal, different directories compare unequal, and a directory symlink compares equal to its target. with then yields exactly the entries and the error that the same tree yields natively. Without the change the same probe drops both symlinked subtrees. Same probe under , the WASI shim npm packages use in the browser, with the same result. MSRV: on WASI this needs a newer Rust than the declared 1.60, because of . Other targets are unaffected. I have not pinned the exact floor yet, and can do that or use a different import if you want to keep a single MSRV. Unrelated but adjacent no longer compiles on unsupported platforms at all: uses , which edition 2021 rejects with "format argument must be a string literal". 1.0.6 is edition 2018 so it still builds; a release cut from today would turn and friends from a runtime error into a build failure. fixes it. I can fold that into the same PR or keep it separate. Happy to send a PR — just say which of the two implementations you would rather take.
First off, thanks for taking the time to make this crate in the first place! It's made things easier on my personal projects! I would prefer to do this as a discussion, and not a bug, but I didn't see that available on the page. While working with this crate, I had a few ideas on features that I would find useful, and have made an attempt to implement some of them in my own fork: Have a separate, non-owning type that represents a file identity value. This would be the cross-platform representation of the file identity. While the type itself would be completely safe, I understand that for it to actually represent a file identity, the associated file descriptor/handle has to be open. Still, if you need to store values with keys of the file identity, but you don't want to clone a file handle/descriptor in order to put the key in there, and you're willing to handle the precondition that the file handle has to be open for the FileIdentity to mean anything, that seems reasonable. Given a Handle that was created with Handle::from_file(), have a function Handle::into_inner() that converts the handle back to a File. Seeing the current implementation, I know that this is a bit tricky, as the special casing used for Stdin/out/err files does not make that a smooth round-trip, but its hard to work with if you have libraries that expect to convert to/from std::fs::File for owned file descriptors/handles. To implement the above handle conversion safely, and open up the file identity features to more types, would it make sense to make a new FileLikeHandle which will work as long as T implements something like AsRawFd (or AsFd)? All of the metadata queries used to get the file identity do not modify the underlying file, which means you could wrap any type that returns a valid file descriptor/handle. In this way, the Stdin/out/err handles just become instances of FileLikeHandle, with the correct behavior for dropping. Of course, all of the above names are bikesheddable. If you are interested in this, I'm happy to show you what code I have already. Thanks again!
Repository: BurntSushi/same-file. Description: Cross platform Rust library for checking whether two file paths are the same file. Stars: 122, Forks: 27. Primary language: Rust. Languages: Rust (100%). License: Unlicense. Open PRs: 5, open issues: 7. Last activity: 11mo ago. Community health: 42%. Top contributors: BurntSushi, yandexx, gurgalex, AndyGauge, GuillaumeGomez, alexcrichton, KodrAus, cjubb39, igor-raits, jackpot51 and others.