rust icon indicating copy to clipboard operation
rust copied to clipboard

Handle win32 separator for cygwin paths

Open Berrysoft opened this issue 10 months ago • 13 comments

This PR handles a issue that cygwin actually supports Win32 path, so we need to handle the Win32 prefix and separaters.

r? @mati865

cc @jeremyd2019

~~Not sure if I should handle the prefix like the windows target... Cygwin does support win32 paths directly going through the APIs, but I think it's not the recommended way.~~

Here I just use cygwin_conv_path because it handles both cygwin and win32 paths correctly and convert them into absolute POSIX paths.

UPDATE: Windows path prefix is handled.

Berrysoft avatar Jun 01 '25 15:06 Berrysoft

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
tests/pass-dep/tokio/file-io.rs ... FAILED
tests/pass-dep/libc/mmap.rs ... ok

FAILED TEST: tests/pass-dep/tokio/file-io.rs
command: MIRI_ENV_VAR_TEST="0" MIRI_TEMP="/tmp/miri-uitest-A3m2FG" RUST_BACKTRACE="1" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/miri" "--error-format=json" "--sysroot=/checkout/obj/build/x86_64-unknown-linux-gnu/miri-sysroot" "-Dwarnings" "-Dunused" "-Ainternal_features" "-Zui-testing" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/tests/pass-dep/tokio" "tests/pass-dep/tokio/file-io.rs" "-Zmiri-disable-isolation" "--extern" "cfg_if=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libcfg_if-55a32e410325a882.rlib" "--extern" "cfg_if=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libcfg_if-55a32e410325a882.rmeta" "--extern" "getrandom_01=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libgetrandom-77190f9b44a3c009.rlib" "--extern" "getrandom_01=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libgetrandom-77190f9b44a3c009.rmeta" "--extern" "getrandom_02=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libgetrandom-56888fca95a09bf8.rlib" "--extern" "getrandom_02=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libgetrandom-56888fca95a09bf8.rmeta" "--extern" "getrandom_03=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libgetrandom-a8fc577bb44b6d80.rlib" "--extern" "getrandom_03=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libgetrandom-a8fc577bb44b6d80.rmeta" "--extern" "libc=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/liblibc-dd98cac8117d550a.rlib" "--extern" "libc=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/liblibc-dd98cac8117d550a.rmeta" "--extern" "num_cpus=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libnum_cpus-7ab8becb6da559b7.rlib" "--extern" "num_cpus=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libnum_cpus-7ab8becb6da559b7.rmeta" "--extern" "page_size=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libpage_size-c34469ad90c5eb76.rlib" "--extern" "page_size=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libpage_size-c34469ad90c5eb76.rmeta" "--extern" "tempfile=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libtempfile-d40c54a83e8abae9.rlib" "--extern" "tempfile=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libtempfile-d40c54a83e8abae9.rmeta" "--extern" "tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libtokio-539f2d149eae570a.rlib" "--extern" "tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps/libtokio-539f2d149eae570a.rmeta" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/debug/deps" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/tmp/miri_ui/0/miri/x86_64-unknown-linux-gnu/debug/deps" "--edition" "2021"

error: test got exit status: 101, but expected 0
 = note: the compiler panicked

error: no output was expected
---
   4: test_create_and_write::{closure#0}
             at tests/pass-dep/tokio/file-io.rs:24:5
   5: main::{closure#0}
             at tests/pass-dep/tokio/file-io.rs:14:29
   6: tokio::runtime::park::CachedParkThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/park.rs:284:60
   7: tokio::task::coop::with_budget::<std::task::Poll<()>, {closure@tokio::runtime::park::CachedParkThread::block_on<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/task/coop/mod.rs:167:5
   8: tokio::task::coop::budget::<std::task::Poll<()>, {closure@tokio::runtime::park::CachedParkThread::block_on<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/task/coop/mod.rs:133:5
   9: tokio::runtime::park::CachedParkThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/park.rs:284:31
  10: tokio::runtime::context::blocking::BlockingRegionGuard::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/context/blocking.rs:66:9
  11: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/scheduler/multi_thread/mod.rs:87:13
  12: tokio::runtime::context::runtime::enter_runtime::<{closure@tokio::runtime::scheduler::multi_thread::MultiThread::block_on<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}}, ()>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/context/runtime.rs:65:16
  13: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/scheduler/multi_thread/mod.rs:86:9
  14: tokio::runtime::Runtime::block_on_inner::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/runtime.rs:370:45
  15: tokio::runtime::Runtime::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/runtime.rs:342:13
  16: main
             at tests/pass-dep/tokio/file-io.rs:15:5
  17: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
             at /checkout/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---
   4: test_create_and_write::{closure#0}
             at tests/pass-dep/tokio/file-io.rs:24:5
   5: main::{closure#0}
             at tests/pass-dep/tokio/file-io.rs:14:29
   6: tokio::runtime::park::CachedParkThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/park.rs:284:60
   7: tokio::task::coop::with_budget::<std::task::Poll<()>, {closure@tokio::runtime::park::CachedParkThread::block_on<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/task/coop/mod.rs:167:5
   8: tokio::task::coop::budget::<std::task::Poll<()>, {closure@tokio::runtime::park::CachedParkThread::block_on<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/task/coop/mod.rs:133:5
   9: tokio::runtime::park::CachedParkThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/park.rs:284:31
  10: tokio::runtime::context::blocking::BlockingRegionGuard::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/context/blocking.rs:66:9
  11: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/scheduler/multi_thread/mod.rs:87:13
  12: tokio::runtime::context::runtime::enter_runtime::<{closure@tokio::runtime::scheduler::multi_thread::MultiThread::block_on<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>::{closure#0}}, ()>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/context/runtime.rs:65:16
  13: tokio::runtime::scheduler::multi_thread::MultiThread::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/scheduler/multi_thread/mod.rs:86:9
  14: tokio::runtime::Runtime::block_on_inner::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/runtime.rs:370:45
  15: tokio::runtime::Runtime::block_on::<{async block@tests/pass-dep/tokio/file-io.rs:12:1: 12:15}>
             at /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.2/src/runtime/runtime.rs:342:13
  16: main
             at tests/pass-dep/tokio/file-io.rs:15:5
  17: <fn() as std::ops::FnOnce<()>>::call_once - shim(fn())
             at /checkout/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---

Location:
   /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ui_test-0.29.2/src/lib.rs:369

Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
error: test failed, to rerun pass `--test ui`

Caused by:
  process didn't exit successfully: `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/release/deps/ui-f58affc77002becb` (exit status: 1)
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:05:02
  local time: Sun Jun  1 16:00:41 UTC 2025
  network time: Sun, 01 Jun 2025 16:00:41 GMT
##[error]Process completed with exit code 1.
Post job cleanup.

rust-log-analyzer avatar Jun 01 '25 16:06 rust-log-analyzer

Finally I reuse the prefix parser from Windows. Now the cygwin Path can handle Win32 path correctly. It should behave a little different as it allows / as verbatim separater. Here is a simple test code:

use std::path::{absolute, Path};

fn main() {
    test_path("C:\\msys64");
    test_path("/dev/sda1");
    test_path("./sda1");
    test_path("/c/Users");
    test_path("\\\\?\\UNC/localhost/share");
}

fn test_path(p: impl AsRef<Path>) {
    let p = p.as_ref();
    let abs = absolute(p).unwrap();
    if p.is_absolute() {
        println!("{} == {}", p.display(), abs.display());
    } else {
        println!("{} -> {}", p.display(), abs.display());
    }
    println!("{:?}", p.components().collect::<Vec<_>>());
}

On Windows, it should output (the current drive is D:)

C:\msys64 == C:\msys64
[Prefix(PrefixComponent { raw: "C:", parsed: Disk(67) }), RootDir, Normal("msys64")]
/dev/sda1 -> D:\dev\sda1
[RootDir, Normal("dev"), Normal("sda1")]
./sda1 -> <<<current dir>>>\sda1
[CurDir, Normal("sda1")]
/c/Users -> D:\c\Users
[RootDir, Normal("c"), Normal("Users")]
\\?\UNC/localhost/share == \\?\UNC/localhost/share
[Prefix(PrefixComponent { raw: "\\\\?\\UNC/localhost/share", parsed: VerbatimUNC("localhost/share", "") })]

While on Cygwin, it should output

C:\msys64 == /c/msys64
[Prefix(PrefixComponent { raw: "C:", parsed: Disk(67) }), RootDir, Normal("msys64")]
/dev/sda1 == /dev/sda1
[RootDir, Normal("dev"), Normal("sda1")]
./sda1 -> <<<current dir>>>/sda1
[CurDir, Normal("sda1")]
/c/Users == /c/Users
[RootDir, Normal("c"), Normal("Users")]
\\?\UNC/localhost/share == //?/UNC/localhost/share
[Prefix(PrefixComponent { raw: "\\\\?\\UNC/localhost/share", parsed: VerbatimUNC("localhost", "share") })]

Berrysoft avatar Jun 02 '25 15:06 Berrysoft

@jeremyd2019

I was going to raise the issue of encoding, but looking at the code it doesn't seem to deal with WIN_A as a different encoding than POSIX paths, so I guess that's not an issue. I guess I need to have a conversation on the Cygwin list to better understand this.

Actually rust doesn't handle very well for non-UTF-8 encoding on Unix. OsStr and Path are all UTF-8 (because they could be constructed from a UTF-8 str without copy) and they are passed to OS APIs directly without encoding conversion. The only concerns, I think, should be command line input and console input. Do you know that whether Cygwin handles the encoding conversion of argv and stdin? I hope it does:)

Berrysoft avatar Jun 02 '25 15:06 Berrysoft

OK, seems that the command line is converted from UTF-16: https://github.com/cygwin/cygwin/blob/972872c0d396dbf0ce296b8280cee08ce7727b51/winsup/cygwin/dcrt0.cc#L902

And stdin handles the encoding conversion: https://github.com/cygwin/cygwin/blob/972872c0d396dbf0ce296b8280cee08ce7727b51/winsup/cygwin/fhandler/pty.cc#L3935

So I think all inputs are UTF-8 for a Cygwin program, and the developers could not construct a non-UTF-8 Win32 path if they aren't aware of encodings. If they are, they should know that Rust codes are UTF-8:)

Berrysoft avatar Jun 02 '25 15:06 Berrysoft

Now I'm a little worried about cygwin_conv_path then. If the maintainers someday find that it should handle code page encodings, the code here will be messed up:(

Berrysoft avatar Jun 02 '25 16:06 Berrysoft

This was originally reported by @Ry0tak through Rust's security disclosure process, and since this affects a still-in-development tier 3 target (with very few users right now) we agreed to let the development of the fix happen in the open.

emilyalbini avatar Jun 02 '25 16:06 emilyalbini

This change is T-libs area, so it will require their review.

r? rust-lang/libs

I'm not familiar with Cygwin API at all, but I see what you want to achieve here, and I think it's sensible.

Now I'm a little worried about cygwin_conv_path then. If the maintainers someday find that it should handle code page encodings, the code here will be messed up:(

They wouldn't want to break that API as a normal release, right? I'd expected a documented API to remain backwards compatible.

@pietroalbini I'm out of the loop, could you shed some light on your comment?

mati865 avatar Jun 02 '25 16:06 mati865

Also, there is a typo in both the title and the first commit 😉

mati865 avatar Jun 02 '25 16:06 mati865

So I think all inputs are UTF-8 for a Cygwin program, and the developers could not construct a non-UTF-8 Win32 path if they aren't aware of encodings. If they are, they should know that Rust codes are UTF-8:)

Cygwin's encoding may not always be UTF-8 - one can set the locale environment variables like they can on Unix to set the encoding, and then the conversions of paths and terminal input will use that encoding instead of UTF-8.

jeremyd2019 avatar Jun 02 '25 17:06 jeremyd2019

In such locale, Rust doesn't even work on Linux. That's fair:)

Berrysoft avatar Jun 02 '25 17:06 Berrysoft

@pietroalbini I'm out of the loop, could you shed some light on your comment?

@mati865 this was originally reported to [email protected] as it could defeat path traversal mitigations like this:

if p.components().into_iter().any(|x| x == Component::ParentDir) {
    panic!("path traversal");
}

By only parsing unix-like paths, it would be possible to sneak in a path traversal using win32 paths. Given the current status of the target we agreed it would be ok to develop the fix in the open.

emilyalbini avatar Jun 03 '25 07:06 emilyalbini

@tgross35 ping?

Berrysoft avatar Jun 07 '25 01:06 Berrysoft

@pietroalbini I'm out of the loop, could you shed some light on your comment?

@mati865 this was originally reported to [email protected] as it could defeat path traversal mitigations like this:

if p.components().into_iter().any(|x| x == Component::ParentDir) {
    panic!("path traversal");
}

By only parsing unix-like paths, it would be possible to sneak in a path traversal using win32 paths. Given the current status of the target we agreed it would be ok to develop the fix in the open.

@Berrysoft could you add a regression test to this effect that fails without this change? Probably in library/std/tests/path.rs.

tgross35 avatar Jun 10 '25 05:06 tgross35

Should there be some testing of // prefixes, like //?/C:/foo/bar and //server/share/foo.txt?

jeremyd2019 avatar Jun 10 '25 17:06 jeremyd2019

Should there be some testing of // prefixes, like //?/C:/foo/bar and //server/share/foo.txt?

I'll add some immediately.

Berrysoft avatar Jun 10 '25 17:06 Berrysoft

@jeremyd2019 mind confirming/approving when this looks good to you? Considering you're one of the resident cygwin experts.

tgross35 avatar Jun 10 '25 17:06 tgross35

Added tests for // prefixes and mixed separater verbatim paths.

Berrysoft avatar Jun 10 '25 17:06 Berrysoft

It looks like Cygwin will take //. as well, but only //.\C: not //./C:. Go figure

jeremyd2019 avatar Jun 10 '25 17:06 jeremyd2019

Are these tests actually run in CI? I was concerned that the prefix parsing had some hard-coded backslashes that may result in the forward-slash // prefixes not working as desired. It'd be good to get confirmation that these tests all pass before merging.

jeremyd2019 avatar Jun 10 '25 17:06 jeremyd2019

No. I ran the tests on my devices...

The prefix parser converts all / to \ in the beginning so it's OK to hardcode here.

Berrysoft avatar Jun 10 '25 17:06 Berrysoft

It looks like Cygwin will take //. as well, but only //.\C: not //./C:. Go figure

Well... You're right then. So when does Cygwin doesn't take / in a path?

P.S. cygwin_conv_path converts //.\C:/msys64 to //./C:/msys64 and I think it might be a bug?

Berrysoft avatar Jun 10 '25 17:06 Berrysoft

It looks like Cygwin will take //. as well, but only //.\C: not //./C:. Go figure

Well... You're right then. So when does Cygwin doesn't take / in a path?

P.S. cygwin_conv_path converts //.\C:/msys64 to //./C:/msys64 and I think it might be a bug?

I don't know, probably have to ask Corinna when she's online

jeremyd2019 avatar Jun 10 '25 17:06 jeremyd2019

@jeremyd2019 mind confirming/approving when this looks good to you? Considering you're one of the resident cygwin experts.

I think the tests cover the cases I thought of, with the exception of //. prefix which seems kind of questionable how that should work.

jeremyd2019 avatar Jun 10 '25 17:06 jeremyd2019

Seems that Cygwin treats //./ and //../ as //. Wierd but I think I can handle that...

Berrysoft avatar Jun 10 '25 18:06 Berrysoft

I think I need more time to think how to handle the //././../././../ prefix as //... If there's no better way, I think I should remove the prefix parser for Cygwin.

Berrysoft avatar Jun 10 '25 18:06 Berrysoft

Now they are handled. Based on my experiments, only //./ (together with //../) is special and should be dealt with. \\.\, \\./, //.\ are valid device paths. I have to add a new field to Components to record the extra length of ./ and ../.

Berrysoft avatar Jun 11 '25 05:06 Berrysoft

The job mingw-check-1 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
   Compiling addr2line v0.24.2
[RUSTC-TIMING] addr2line test:false 0.867
[RUSTC-TIMING] gimli test:false 8.377
[RUSTC-TIMING] object test:false 11.905
error[E0599]: no method named `is_verbatim` found for tuple `(usize, Prefix<'_>)` in the current scope
   --> library/std/src/sys/path/windows.rs:193:25
    |
193 |     if prefix.map(|x| x.is_verbatim()).unwrap_or(false) {
    |                         ^^^^^^^^^^^ method not found in `(usize, Prefix<'_>)`

For more information about this error, try `rustc --explain E0599`.
[RUSTC-TIMING] std test:false 8.828
error: could not compile `std` (lib) due to 1 previous error
Build completed unsuccessfully in 0:12:54

rust-log-analyzer avatar Jun 11 '25 06:06 rust-log-analyzer

My only concern is will this work out well if the current handling of //./ is determined to be a bug and is fixed? It may not be, // being a distinct root from / is apparently allowed by POSIX, and perhaps they require 'ordinary' handling of . and .. elements in that case (for current and parent directory) with the presence of \ used to allow handling of the Windows device namespace.

I posted this question to https://inbox.sourceware.org/cygwin/[email protected]/T/#u

jeremyd2019 avatar Jun 11 '25 17:06 jeremyd2019

I don't think it's a bug now. It's only a little wierd. Due to the design of rust std, I choose to identify the whole //././?/C: as a prefix.

Berrysoft avatar Jun 12 '25 00:06 Berrysoft

Tested on Cygwin and I found that Cygwin even treats //./?/C:/msys64/../../../?/D:/msys64 equal to D:\msys64. So Cygwin really thinks that's a POSIX path. I think I should follow it. The path without driver letter or //, and not containing \, is a POSIX path even it contains /?/ and could be recognized finally.

Berrysoft avatar Jun 12 '25 02:06 Berrysoft