From fe0091db1fcdcc7e938b61505068c707ca7c82b3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 09:54:35 -0800 Subject: [PATCH 1/8] Backport build.rs fixes to 1.x. * Backport build.rs fixes to 1.x. * Fix warnings on recent Rust compilers. * Fix the build of timezone.rs on recent Rust versions. * Use docsrs instead of doc_cfg. * Update CI for 1.x. * Implement `change_time` for windows' `MetadataExt`. --- .cirrus.yml | 23 +++++-- .github/actions/install-rust/action.yml | 2 +- .github/workflows/main.yml | 32 +++++----- build.rs | 16 +++-- cap-fs-ext/Cargo.toml | 6 ++ cap-fs-ext/build.rs | 55 ++++++++++++++--- cap-primitives/build.rs | 61 ++++++++++++++++--- cap-primitives/src/fs/metadata.rs | 5 ++ cap-primitives/src/lib.rs | 1 + cap-primitives/src/windows/fs/metadata_ext.rs | 42 +++++++++++-- cap-std/Cargo.toml | 2 +- cap-std/build.rs | 59 +++++++++++++++--- cap-std/src/lib.rs | 2 +- tests/cap-basics.rs | 7 ++- 14 files changed, 254 insertions(+), 59 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index abe8fce4..d6fa71b4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -2,11 +2,10 @@ # at revision 7f4774e76bd5cb9ccb7140d71ef9be9c16009cdf. task: - name: stable x86_64-unknown-freebsd-13 + name: stable x86_64-unknown-freebsd-15-snap freebsd_instance: - image_family: freebsd-13-0-snap + image_family: freebsd-15-0-snap setup_script: - - pkg install -y curl - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh --default-toolchain stable -y --profile=minimal - . $HOME/.cargo/env @@ -16,11 +15,23 @@ task: - cargo test --features=fs_utf8 --workspace task: - name: stable x86_64-unknown-freebsd-12 + name: stable x86_64-unknown-freebsd-14 + freebsd_instance: + image_family: freebsd-14-0 + setup_script: + - curl https://sh.rustup.rs -sSf --output rustup.sh + - sh rustup.sh --default-toolchain stable -y --profile=minimal + - . $HOME/.cargo/env + - rustup default stable + test_script: + - . $HOME/.cargo/env + - cargo test --features=fs_utf8 --workspace + +task: + name: stable x86_64-unknown-freebsd-13 freebsd_instance: - image_family: freebsd-12-1 + image_family: freebsd-13-3 setup_script: - - pkg install -y curl - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh --default-toolchain stable -y --profile=minimal - . $HOME/.cargo/env diff --git a/.github/actions/install-rust/action.yml b/.github/actions/install-rust/action.yml index 6afc01d6..11c05760 100644 --- a/.github/actions/install-rust/action.yml +++ b/.github/actions/install-rust/action.yml @@ -8,5 +8,5 @@ inputs: default: 'stable' runs: - using: node16 + using: node20 main: 'main.js' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 56e593bf..6a255228 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: name: Rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -34,7 +34,7 @@ jobs: rust: beta steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -88,7 +88,7 @@ jobs: rust: beta steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -116,7 +116,7 @@ jobs: rust: nightly steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -150,7 +150,7 @@ jobs: riscv64gc-unknown-linux-gnu arm-unknown-linux-gnueabihf aarch64-linux-android - wasm32-wasi + wasm32-wasip1 - run: cargo check --workspace --all-targets --all-features --release -vv - run: cargo check --workspace --all-targets --all-features --release -vv --target=x86_64-unknown-linux-musl - run: cargo check --workspace --all-targets --all-features --release -vv --target=x86_64-unknown-linux-gnux32 @@ -164,7 +164,7 @@ jobs: - run: cargo check --workspace --all-targets --all-features --release -vv --target=riscv64gc-unknown-linux-gnu - run: cargo check --workspace --all-targets --all-features --release -vv --target=arm-unknown-linux-gnueabihf - run: cargo check --workspace --all-targets --all-features --release -vv --target=aarch64-linux-android - - run: cd cap-std && cargo check --features=fs_utf8 --release -vv --target=wasm32-wasi + - run: cd cap-std && cargo check --features=fs_utf8 --release -vv --target=wasm32-wasip1 check_cross_nightly_windows: name: Check Cross-Compilation on Rust nightly on Windows @@ -178,7 +178,7 @@ jobs: rust: nightly steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -201,7 +201,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - build: [stable, windows-latest, windows-2019, macos-latest, macos-10.15, beta, ubuntu-20.04, aarch64-ubuntu] + build: [stable, windows-latest, windows-2019, macos-latest, macos-12, beta, ubuntu-20.04, aarch64-ubuntu] include: - build: stable os: ubuntu-latest @@ -215,8 +215,8 @@ jobs: - build: macos-latest os: macos-latest rust: stable - - build: macos-10.15 - os: macos-10.15 + - build: macos-12 + os: macos-12 rust: stable - build: beta os: ubuntu-latest @@ -234,7 +234,7 @@ jobs: qemu_target: aarch64-linux-user steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -291,7 +291,7 @@ jobs: rust: nightly steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -311,7 +311,7 @@ jobs: rust: stable steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -345,7 +345,7 @@ jobs: RUSTFLAGS: --cfg linux_raw RUSTDOCFLAGS: --cfg linux_raw steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -365,7 +365,7 @@ jobs: rust: 1.58 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust @@ -381,7 +381,7 @@ jobs: name: Fuzz Targets runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - uses: ./.github/actions/install-rust diff --git a/build.rs b/build.rs index 1a2cead4..c991825c 100644 --- a/build.rs +++ b/build.rs @@ -19,6 +19,9 @@ fn main() { // https://doc.rust-lang.org/unstable-book/library-features/windows-file-type-ext.html use_feature_or_nothing("windows_file_type_ext"); + // Cfgs that users may set. + println!("cargo:rustc-check-cfg=cfg(racy_asserts)"); + // Don't rerun this on changes other than build.rs, as we only depend on // the rustc version. println!("cargo:rerun-if-changed=build.rs"); @@ -28,6 +31,7 @@ fn use_feature_or_nothing(feature: &str) { if has_feature(feature) { use_feature(feature); } + println!("cargo:rustc-check-cfg=cfg({})", feature); } fn use_feature(feature: &str) { @@ -36,7 +40,7 @@ fn use_feature(feature: &str) { /// Test whether the rustc at `var("RUSTC")` supports the given feature. fn has_feature(feature: &str) -> bool { - can_compile(&format!( + can_compile(format!( "#![allow(stable_features)]\n#![feature({})]", feature )) @@ -46,12 +50,11 @@ fn has_feature(feature: &str) -> bool { fn can_compile>(test: T) -> bool { use std::process::Stdio; - let out_dir = var("OUT_DIR").unwrap(); let rustc = var("RUSTC").unwrap(); let target = var("TARGET").unwrap(); - // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, - // as documented [here]. + // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, as + // documented [here]. // [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads let wrapper = var("RUSTC_WRAPPER") .ok() @@ -70,8 +73,9 @@ fn can_compile>(test: T) -> bool { .arg("--emit=metadata") // Do as little as possible but still parse. .arg("--target") .arg(target) - .arg("--out-dir") - .arg(out_dir); // Put the output somewhere inconsequential. + .arg("-o") + .arg("-") + .stdout(Stdio::null()); // We don't care about the output (only whether it builds or not) // If Cargo wants to set RUSTFLAGS, use that. if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { diff --git a/cap-fs-ext/Cargo.toml b/cap-fs-ext/Cargo.toml index b42fa771..2a4f62a3 100644 --- a/cap-fs-ext/Cargo.toml +++ b/cap-fs-ext/Cargo.toml @@ -40,3 +40,9 @@ features = [ [dev-dependencies] cap-tempfile = { path = "../cap-tempfile" } + +[lints.rust.unexpected_cfgs] +level = "warn" +check-cfg = [ + 'cfg(feature, values("async_std"))' +] diff --git a/cap-fs-ext/build.rs b/cap-fs-ext/build.rs index 6e8f4d3f..1716d753 100644 --- a/cap-fs-ext/build.rs +++ b/cap-fs-ext/build.rs @@ -13,6 +13,7 @@ fn use_feature_or_nothing(feature: &str) { if has_feature(feature) { use_feature(feature); } + println!("cargo:rustc-check-cfg=cfg({})", feature); } fn use_feature(feature: &str) { @@ -21,20 +22,60 @@ fn use_feature(feature: &str) { /// Test whether the rustc at `var("RUSTC")` supports the given feature. fn has_feature(feature: &str) -> bool { - let out_dir = var("OUT_DIR").unwrap(); + can_compile(&format!( + "#![allow(stable_features)]\n#![feature({})]", + feature + )) +} + +/// Test whether the rustc at `var("RUSTC")` can compile the given code. +fn can_compile>(test: T) -> bool { + use std::process::Stdio; + let rustc = var("RUSTC").unwrap(); + let target = var("TARGET").unwrap(); + + // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, + // as documented [here]. + // [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads + let wrapper = var("RUSTC_WRAPPER") + .ok() + .and_then(|w| if w.is_empty() { None } else { Some(w) }); - let mut child = std::process::Command::new(rustc) - .arg("--crate-type=rlib") // Don't require `main`. + let mut cmd = if let Some(wrapper) = wrapper { + let mut cmd = std::process::Command::new(wrapper); + // The wrapper's first argument is supposed to be the path to rustc. + cmd.arg(rustc); + cmd + } else { + std::process::Command::new(rustc) + }; + + cmd.arg("--crate-type=rlib") // Don't require `main`. .arg("--emit=metadata") // Do as little as possible but still parse. - .arg("--out-dir") - .arg(out_dir) // Put the output somewhere inconsequential. + .arg("--target") + .arg(target) + .arg("-o") + .arg("-") + .stdout(Stdio::null()); // We don't care about the output (only whether it builds or not) + + // If Cargo wants to set RUSTFLAGS, use that. + if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { + if !rustflags.is_empty() { + for arg in rustflags.split('\x1f') { + cmd.arg(arg); + } + } + } + + let mut child = cmd .arg("-") // Read from stdin. - .stdin(std::process::Stdio::piped()) // Stdin is a pipe. + .stdin(Stdio::piped()) // Stdin is a pipe. + .stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing. .spawn() .unwrap(); - writeln!(child.stdin.take().unwrap(), "#![feature({})]", feature).unwrap(); + writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap(); child.wait().unwrap().success() } diff --git a/cap-primitives/build.rs b/cap-primitives/build.rs index 966799b5..0515658a 100644 --- a/cap-primitives/build.rs +++ b/cap-primitives/build.rs @@ -5,9 +5,15 @@ fn main() { use_feature_or_nothing("windows_by_handle"); // https://github.com/rust-lang/rust/issues/63010 // https://doc.rust-lang.org/unstable-book/library-features/windows-file-type-ext.html use_feature_or_nothing("windows_file_type_ext"); + use_feature_or_nothing("windows_change_time"); use_feature_or_nothing("io_error_more"); // https://github.com/rust-lang/rust/issues/86442 use_feature_or_nothing("io_error_uncategorized"); + // Cfgs that users may set. + println!("cargo:rustc-check-cfg=cfg(racy_asserts)"); + println!("cargo:rustc-check-cfg=cfg(emulate_second_only_system)"); + println!("cargo:rustc-check-cfg=cfg(io_lifetimes_use_std)"); + // Don't rerun this on changes other than build.rs, as we only depend on // the rustc version. println!("cargo:rerun-if-changed=build.rs"); @@ -17,6 +23,7 @@ fn use_feature_or_nothing(feature: &str) { if has_feature(feature) { use_feature(feature); } + println!("cargo:rustc-check-cfg=cfg({})", feature); } fn use_feature(feature: &str) { @@ -25,20 +32,60 @@ fn use_feature(feature: &str) { /// Test whether the rustc at `var("RUSTC")` supports the given feature. fn has_feature(feature: &str) -> bool { - let out_dir = var("OUT_DIR").unwrap(); + can_compile(&format!( + "#![allow(stable_features)]\n#![feature({})]", + feature + )) +} + +/// Test whether the rustc at `var("RUSTC")` can compile the given code. +fn can_compile>(test: T) -> bool { + use std::process::Stdio; + let rustc = var("RUSTC").unwrap(); + let target = var("TARGET").unwrap(); + + // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, + // as documented [here]. + // [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads + let wrapper = var("RUSTC_WRAPPER") + .ok() + .and_then(|w| if w.is_empty() { None } else { Some(w) }); - let mut child = std::process::Command::new(rustc) - .arg("--crate-type=rlib") // Don't require `main`. + let mut cmd = if let Some(wrapper) = wrapper { + let mut cmd = std::process::Command::new(wrapper); + // The wrapper's first argument is supposed to be the path to rustc. + cmd.arg(rustc); + cmd + } else { + std::process::Command::new(rustc) + }; + + cmd.arg("--crate-type=rlib") // Don't require `main`. .arg("--emit=metadata") // Do as little as possible but still parse. - .arg("--out-dir") - .arg(out_dir) // Put the output somewhere inconsequential. + .arg("--target") + .arg(target) + .arg("-o") + .arg("-") + .stdout(Stdio::null()); // We don't care about the output (only whether it builds or not) + + // If Cargo wants to set RUSTFLAGS, use that. + if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { + if !rustflags.is_empty() { + for arg in rustflags.split('\x1f') { + cmd.arg(arg); + } + } + } + + let mut child = cmd .arg("-") // Read from stdin. - .stdin(std::process::Stdio::piped()) // Stdin is a pipe. + .stdin(Stdio::piped()) // Stdin is a pipe. + .stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing. .spawn() .unwrap(); - writeln!(child.stdin.take().unwrap(), "#![feature({})]", feature).unwrap(); + writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap(); child.wait().unwrap().success() } diff --git a/cap-primitives/src/fs/metadata.rs b/cap-primitives/src/fs/metadata.rs index afcda83d..fd63d5c4 100644 --- a/cap-primitives/src/fs/metadata.rs +++ b/cap-primitives/src/fs/metadata.rs @@ -443,6 +443,11 @@ impl std::os::windows::fs::MetadataExt for Metadata { fn file_index(&self) -> Option { self.ext.file_index() } + + #[inline] + fn change_time(&self) -> Option { + self.ext.change_time() + } } /// Extension trait to allow `volume_serial_number` etc. to be exposed by diff --git a/cap-primitives/src/lib.rs b/cap-primitives/src/lib.rs index e9943917..03245996 100644 --- a/cap-primitives/src/lib.rs +++ b/cap-primitives/src/lib.rs @@ -5,6 +5,7 @@ #![allow(stable_features)] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] #![cfg_attr(all(windows, windows_by_handle), feature(windows_by_handle))] +#![cfg_attr(all(windows, windows_change_time), feature(windows_change_time))] #![cfg_attr(all(windows, windows_file_type_ext), feature(windows_file_type_ext))] #![doc( html_logo_url = "https://raw.githubusercontent.com/bytecodealliance/cap-std/main/media/cap-std.svg" diff --git a/cap-primitives/src/windows/fs/metadata_ext.rs b/cap-primitives/src/windows/fs/metadata_ext.rs index 0b1becf8..44a1940f 100644 --- a/cap-primitives/src/windows/fs/metadata_ext.rs +++ b/cap-primitives/src/windows/fs/metadata_ext.rs @@ -18,6 +18,8 @@ pub(crate) struct MetadataExt { volume_serial_number: Option, number_of_links: Option, file_index: Option, + #[cfg(windows_change_time)] + change_time: Option, } impl MetadataExt { @@ -26,7 +28,8 @@ impl MetadataExt { #[inline] #[allow(unused_variables)] pub(crate) fn from(file: &fs::File, std: &fs::Metadata) -> io::Result { - let (mut volume_serial_number, mut number_of_links, mut file_index) = (None, None, None); + let (mut volume_serial_number, mut number_of_links, mut file_index, mut change_time) = + (None, None, None, None); #[cfg(windows_by_handle)] { @@ -40,10 +43,17 @@ impl MetadataExt { if let Some(some) = std.file_index() { file_index = Some(some); } + if let Some(some) = std.change_time() { + change_time = Some(some); + } } #[cfg(not(windows_by_handle))] - if volume_serial_number.is_none() || number_of_links.is_none() || file_index.is_none() { + if volume_serial_number.is_none() + || number_of_links.is_none() + || file_index.is_none() + || change_time.is_none() + { let fileinfo = winx::winapi_util::file::information(file)?; if volume_serial_number.is_none() { let t64: u64 = fileinfo.volume_serial_number(); @@ -58,6 +68,7 @@ impl MetadataExt { if file_index.is_none() { file_index = Some(fileinfo.file_index()); } + change_time = None; } Ok(Self::from_parts( @@ -65,6 +76,7 @@ impl MetadataExt { volume_serial_number, number_of_links, file_index, + change_time, )) } @@ -78,7 +90,8 @@ impl MetadataExt { #[inline] #[allow(unused_mut)] pub(crate) fn from_just_metadata(std: &fs::Metadata) -> Self { - let (mut volume_serial_number, mut number_of_links, mut file_index) = (None, None, None); + let (mut volume_serial_number, mut number_of_links, mut file_index, mut change_time) = + (None, None, None, None); #[cfg(windows_by_handle)] { @@ -92,9 +105,18 @@ impl MetadataExt { if let Some(some) = std.file_index() { file_index = Some(some); } + if let Some(some) = std.change_time() { + change_time = Some(some); + } } - Self::from_parts(std, volume_serial_number, number_of_links, file_index) + Self::from_parts( + std, + volume_serial_number, + number_of_links, + file_index, + change_time, + ) } #[inline] @@ -103,8 +125,13 @@ impl MetadataExt { volume_serial_number: Option, number_of_links: Option, file_index: Option, + change_time: Option, ) -> Self { use std::os::windows::fs::MetadataExt; + + #[cfg(not(windows_change_time))] + let _ = change_time; + Self { file_attributes: std.file_attributes(), #[cfg(windows_by_handle)] @@ -118,6 +145,8 @@ impl MetadataExt { volume_serial_number, number_of_links, file_index, + #[cfg(windows_change_time)] + change_time, } } @@ -190,6 +219,11 @@ impl std::os::windows::fs::MetadataExt for MetadataExt { fn file_index(&self) -> Option { self.file_index } + + #[inline] + fn change_time(&self) -> Option { + self.change_time + } } #[doc(hidden)] diff --git a/cap-std/Cargo.toml b/cap-std/Cargo.toml index 1260ea1f..ee3e45bc 100644 --- a/cap-std/Cargo.toml +++ b/cap-std/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" [package.metadata.docs.rs] all-features = true -rustdoc-args = ["--cfg=doc_cfg"] +rustdoc-args = ["--cfg=docsrs"] [dependencies] arf-strings = { version = "0.7.0", optional = true } diff --git a/cap-std/build.rs b/cap-std/build.rs index db85de0e..384b38a8 100644 --- a/cap-std/build.rs +++ b/cap-std/build.rs @@ -6,6 +6,10 @@ fn main() { use_feature_or_nothing("seek_convenience"); // https://github.com/rust-lang/rust/issues/59359 use_feature_or_nothing("with_options"); // https://github.com/rust-lang/rust/issues/65439 use_feature_or_nothing("write_all_vectored"); // https://github.com/rust-lang/rust/issues/70436 + use_feature_or_nothing("windows_file_type_ext"); + + // Cfgs that users may set. + println!("cargo:rustc-check-cfg=cfg(io_lifetimes_use_std)"); // Don't rerun this on changes other than build.rs, as we only depend on // the rustc version. @@ -16,6 +20,7 @@ fn use_feature_or_nothing(feature: &str) { if has_feature(feature) { use_feature(feature); } + println!("cargo:rustc-check-cfg=cfg({})", feature); } fn use_feature(feature: &str) { @@ -24,20 +29,60 @@ fn use_feature(feature: &str) { /// Test whether the rustc at `var("RUSTC")` supports the given feature. fn has_feature(feature: &str) -> bool { - let out_dir = var("OUT_DIR").unwrap(); + can_compile(&format!( + "#![allow(stable_features)]\n#![feature({})]", + feature + )) +} + +/// Test whether the rustc at `var("RUSTC")` can compile the given code. +fn can_compile>(test: T) -> bool { + use std::process::Stdio; + let rustc = var("RUSTC").unwrap(); + let target = var("TARGET").unwrap(); + + // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, + // as documented [here]. + // [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads + let wrapper = var("RUSTC_WRAPPER") + .ok() + .and_then(|w| if w.is_empty() { None } else { Some(w) }); - let mut child = std::process::Command::new(rustc) - .arg("--crate-type=rlib") // Don't require `main`. + let mut cmd = if let Some(wrapper) = wrapper { + let mut cmd = std::process::Command::new(wrapper); + // The wrapper's first argument is supposed to be the path to rustc. + cmd.arg(rustc); + cmd + } else { + std::process::Command::new(rustc) + }; + + cmd.arg("--crate-type=rlib") // Don't require `main`. .arg("--emit=metadata") // Do as little as possible but still parse. - .arg("--out-dir") - .arg(out_dir) // Put the output somewhere inconsequential. + .arg("--target") + .arg(target) + .arg("-o") + .arg("-") + .stdout(Stdio::null()); // We don't care about the output (only whether it builds or not) + + // If Cargo wants to set RUSTFLAGS, use that. + if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { + if !rustflags.is_empty() { + for arg in rustflags.split('\x1f') { + cmd.arg(arg); + } + } + } + + let mut child = cmd .arg("-") // Read from stdin. - .stdin(std::process::Stdio::piped()) // Stdin is a pipe. + .stdin(Stdio::piped()) // Stdin is a pipe. + .stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing. .spawn() .unwrap(); - writeln!(child.stdin.take().unwrap(), "#![feature({})]", feature).unwrap(); + writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap(); child.wait().unwrap().success() } diff --git a/cap-std/src/lib.rs b/cap-std/src/lib.rs index 5ddf9f49..e425778f 100644 --- a/cap-std/src/lib.rs +++ b/cap-std/src/lib.rs @@ -23,7 +23,7 @@ //! [`Pool`]: net::Pool #![deny(missing_docs)] -#![cfg_attr(doc_cfg, feature(doc_cfg, doc_auto_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] #![cfg_attr(can_vector, feature(can_vector))] #![cfg_attr(seek_convenience, feature(seek_convenience))] diff --git a/tests/cap-basics.rs b/tests/cap-basics.rs index eae9925d..b1f37f0a 100644 --- a/tests/cap-basics.rs +++ b/tests/cap-basics.rs @@ -217,10 +217,11 @@ fn symlink_loop_from_rename() { check!(tmpdir.open("link")); } -#[cfg(linux)] +#[cfg(target_os = "linux")] #[test] fn proc_self_fd() { - let fd = check!(File::open("/proc/self/fd")); + let fd = check!(std::fs::File::open("/proc/self/fd")); let dir = cap_std::fs::Dir::from_std_file(fd); - error!(dir.open("0"), "No such file"); + // This should fail with "too many levels of symbolic links". + dir.open("0").unwrap_err(); } From 4fcaa0906cad7b0912765913adeb07defc89cc1d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 13:26:41 -0800 Subject: [PATCH 2/8] Backport warning fixes. --- tests/sys_common/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/sys_common/mod.rs b/tests/sys_common/mod.rs index fa803baf..d13e417d 100644 --- a/tests/sys_common/mod.rs +++ b/tests/sys_common/mod.rs @@ -1,3 +1,5 @@ +#![allow(unused_imports)] + mod symlink_junction; pub mod io; From b3795e160ef133f2a940bf3eeda45482d114096b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 13:30:54 -0800 Subject: [PATCH 3/8] Backport more test warning fixes. --- tests/dir-ext.rs | 10 ++++++---- tests/fs.rs | 3 +-- tests/sys/mod.rs | 2 ++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/dir-ext.rs b/tests/dir-ext.rs index d5bf4996..0b0f5d91 100644 --- a/tests/dir-ext.rs +++ b/tests/dir-ext.rs @@ -39,8 +39,9 @@ fn remove_symlink_to_dir() { } let tempdir = TempDir::new(ambient_authority()).expect("create tempdir"); - let target = tempdir.create_dir("target").expect("create target dir"); - drop(target); + { + let _target = tempdir.create_dir("target").expect("create target dir"); + } tempdir.symlink("target", "link").expect("create symlink"); assert!(tempdir.exists("link"), "link exists"); tempdir @@ -53,8 +54,9 @@ fn remove_symlink_to_dir() { #[test] fn do_not_remove_dir() { let tempdir = TempDir::new(ambient_authority()).expect("create tempdir"); - let subdir = tempdir.create_dir("subdir").expect("create dir"); - drop(subdir); + { + let _subdir = tempdir.create_dir("subdir").expect("create dir"); + } assert!(tempdir.exists("subdir"), "subdir created"); tempdir .remove_file_or_symlink("subdir") diff --git a/tests/fs.rs b/tests/fs.rs index b51d5183..df8e332e 100644 --- a/tests/fs.rs +++ b/tests/fs.rs @@ -673,7 +673,6 @@ fn recursive_rmdir_toctou() { // `attack_dest/attack_file` is deleted. let tmpdir = tmpdir(); let victim_del_path = "victim_del"; - let victim_del_path_clone = victim_del_path.clone(); // setup dest let attack_dest_dir = "attack_dest"; @@ -691,7 +690,7 @@ fn recursive_rmdir_toctou() { let tmpdir_clone = tmpdir.try_clone().unwrap(); let _t = thread::spawn(move || { while drop_canary_weak.upgrade().is_some() { - let _ = tmpdir_clone.remove_dir_all(victim_del_path_clone); + let _ = tmpdir_clone.remove_dir_all(victim_del_path); } }); diff --git a/tests/sys/mod.rs b/tests/sys/mod.rs index e1163bab..cc2c50f9 100644 --- a/tests/sys/mod.rs +++ b/tests/sys/mod.rs @@ -1,3 +1,5 @@ +#![allow(unused_imports)] + #[cfg(unix)] mod unix; From ad2c483dde9eb5969a89446cdbaf86e52f7495ec Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 13:46:26 -0800 Subject: [PATCH 4/8] Fix warning. --- tests/fs_utf8.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/fs_utf8.rs b/tests/fs_utf8.rs index 06cfda28..882d726f 100644 --- a/tests/fs_utf8.rs +++ b/tests/fs_utf8.rs @@ -676,7 +676,6 @@ fn recursive_rmdir_toctou() { // `attack_dest/attack_file` is deleted. let tmpdir = tmpdir(); let victim_del_path = "victim_del"; - let victim_del_path_clone = victim_del_path.clone(); // setup dest let attack_dest_dir = "attack_dest"; @@ -694,7 +693,7 @@ fn recursive_rmdir_toctou() { let tmpdir_clone = tmpdir.try_clone().unwrap(); let _t = thread::spawn(move || { while drop_canary_weak.upgrade().is_some() { - let _ = tmpdir_clone.remove_dir_all(victim_del_path_clone); + let _ = tmpdir_clone.remove_dir_all(victim_del_path); } }); From a6f796372f334702bd45e4b754f08c32e2a90c1f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 14:10:34 -0800 Subject: [PATCH 5/8] Update to rustix 0.38. --- Cargo.toml | 2 +- cap-async-std/Cargo.toml | 2 +- cap-directories/Cargo.toml | 2 +- cap-primitives/Cargo.toml | 2 +- cap-primitives/src/rustix/fs/metadata_ext.rs | 13 ++++++++----- cap-primitives/src/rustix/fs/open_unchecked.rs | 4 ++-- cap-primitives/src/rustix/fs/reopen_impl.rs | 4 ++-- cap-primitives/src/rustix/fs/stat_unchecked.rs | 2 +- cap-primitives/src/rustix/linux/fs/procfs.rs | 11 ++++++++--- cap-std/Cargo.toml | 2 +- cap-tempfile/Cargo.toml | 2 +- cap-tempfile/src/tempfile.rs | 2 +- cap-time-ext/Cargo.toml | 2 +- 13 files changed, 29 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1916f0bd..5336131d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ libc = "0.2.100" io-lifetimes = "1.0.0" [target.'cfg(not(windows))'.dev-dependencies] -rustix = { version = "0.37.0", features = ["fs"] } +rustix = { version = "0.38.0", features = ["fs"] } [target.'cfg(windows)'.dev-dependencies] # nt_version uses internal Windows APIs, however we're only using it diff --git a/cap-async-std/Cargo.toml b/cap-async-std/Cargo.toml index 90048a67..92948372 100644 --- a/cap-async-std/Cargo.toml +++ b/cap-async-std/Cargo.toml @@ -23,7 +23,7 @@ io-extras = { version = "0.17.0", features = ["use_async_std"] } camino = { version = "1.0.5", optional = true } [target.'cfg(not(windows))'.dependencies] -rustix = { version = "0.37.0", features = ["fs"] } +rustix = { version = "0.38.0", features = ["fs"] } [features] default = [] diff --git a/cap-directories/Cargo.toml b/cap-directories/Cargo.toml index e3a3804a..583958aa 100644 --- a/cap-directories/Cargo.toml +++ b/cap-directories/Cargo.toml @@ -17,7 +17,7 @@ cap-std = { path = "../cap-std", version = "^1.0.9" } directories-next = "2.0.0" [target.'cfg(not(windows))'.dependencies] -rustix = { version = "0.37.0" } +rustix = { version = "0.38.0" } [target.'cfg(windows)'.dependencies.windows-sys] version = "0.45.0" diff --git a/cap-primitives/Cargo.toml b/cap-primitives/Cargo.toml index 80f11559..69f00e02 100644 --- a/cap-primitives/Cargo.toml +++ b/cap-primitives/Cargo.toml @@ -25,7 +25,7 @@ io-lifetimes = { version = "1.0.0", default-features = false } cap-tempfile = { path = "../cap-tempfile" } [target.'cfg(not(windows))'.dependencies] -rustix = { version = "0.37.0", features = ["fs", "process", "procfs", "termios", "time"] } +rustix = { version = "0.38.31", features = ["fs", "process", "procfs", "termios", "time"] } [target.'cfg(windows)'.dependencies] winx = "0.35.0" diff --git a/cap-primitives/src/rustix/fs/metadata_ext.rs b/cap-primitives/src/rustix/fs/metadata_ext.rs index 9143a65d..61bd006b 100644 --- a/cap-primitives/src/rustix/fs/metadata_ext.rs +++ b/cap-primitives/src/rustix/fs/metadata_ext.rs @@ -102,6 +102,9 @@ impl MetadataExt { /// Constructs a new instance of `Metadata` from the given `Stat`. #[inline] pub(crate) fn from_rustix(stat: Stat) -> Metadata { + #[cfg(not(target_os = "wasi"))] + use rustix::fs::StatExt; + Metadata { file_type: ImplFileTypeExt::from_raw_mode(stat.st_mode as RawMode), len: u64::try_from(stat.st_size).unwrap(), @@ -112,12 +115,12 @@ impl MetadataExt { #[cfg(not(any(target_os = "netbsd", target_os = "wasi")))] modified: system_time_from_rustix( - stat.st_mtime.try_into().unwrap(), + stat.mtime().try_into().unwrap(), stat.st_mtime_nsec as _, ), #[cfg(not(any(target_os = "netbsd", target_os = "wasi")))] accessed: system_time_from_rustix( - stat.st_atime.try_into().unwrap(), + stat.atime().try_into().unwrap(), stat.st_atime_nsec as _, ), @@ -178,19 +181,19 @@ impl MetadataExt { rdev: u64::try_from(stat.st_rdev).unwrap(), size: u64::try_from(stat.st_size).unwrap(), #[cfg(not(target_os = "wasi"))] - atime: i64::try_from(stat.st_atime).unwrap(), + atime: i64::try_from(stat.atime()).unwrap(), #[cfg(not(any(target_os = "netbsd", target_os = "wasi")))] atime_nsec: stat.st_atime_nsec as _, #[cfg(target_os = "netbsd")] atime_nsec: stat.st_atimensec as _, #[cfg(not(target_os = "wasi"))] - mtime: i64::try_from(stat.st_mtime).unwrap(), + mtime: i64::try_from(stat.mtime()).unwrap(), #[cfg(not(any(target_os = "netbsd", target_os = "wasi")))] mtime_nsec: stat.st_mtime_nsec as _, #[cfg(target_os = "netbsd")] mtime_nsec: stat.st_mtimensec as _, #[cfg(not(target_os = "wasi"))] - ctime: i64::try_from(stat.st_ctime).unwrap(), + ctime: i64::try_from(stat.ctime()).unwrap(), #[cfg(not(any(target_os = "netbsd", target_os = "wasi")))] ctime_nsec: stat.st_ctime_nsec as _, #[cfg(target_os = "netbsd")] diff --git a/cap-primitives/src/rustix/fs/open_unchecked.rs b/cap-primitives/src/rustix/fs/open_unchecked.rs index 4112a5a3..8ff6b351 100644 --- a/cap-primitives/src/rustix/fs/open_unchecked.rs +++ b/cap-primitives/src/rustix/fs/open_unchecked.rs @@ -2,7 +2,7 @@ use super::compute_oflags; use crate::fs::{stat_unchecked, OpenOptions, OpenUncheckedError}; use crate::AmbientAuthority; use io_lifetimes::AsFilelike; -use rustix::fs::{cwd, openat, Mode}; +use rustix::fs::{openat, Mode, CWD}; use rustix::io; use std::fs; use std::path::Path; @@ -67,5 +67,5 @@ pub(crate) fn open_ambient_impl( ambient_authority: AmbientAuthority, ) -> Result { let _ = ambient_authority; - open_unchecked(&cwd().as_filelike_view::(), path, options) + open_unchecked(&CWD.as_filelike_view::(), path, options) } diff --git a/cap-primitives/src/rustix/fs/reopen_impl.rs b/cap-primitives/src/rustix/fs/reopen_impl.rs index 40490a6b..e010a4d3 100644 --- a/cap-primitives/src/rustix/fs/reopen_impl.rs +++ b/cap-primitives/src/rustix/fs/reopen_impl.rs @@ -1,14 +1,14 @@ use crate::fs::{open_unchecked, OpenOptions}; use crate::rustix::fs::file_path; use io_lifetimes::AsFilelike; -use rustix::fs::cwd; +use rustix::fs::CWD; use std::{fs, io}; /// Implementation of `reopen`. pub(crate) fn reopen_impl(file: &fs::File, options: &OpenOptions) -> io::Result { if let Some(path) = file_path(file) { Ok(open_unchecked( - &cwd().as_filelike_view::(), + &CWD.as_filelike_view::(), &path, options, )?) diff --git a/cap-primitives/src/rustix/fs/stat_unchecked.rs b/cap-primitives/src/rustix/fs/stat_unchecked.rs index 70b40d18..9cee69a8 100644 --- a/cap-primitives/src/rustix/fs/stat_unchecked.rs +++ b/cap-primitives/src/rustix/fs/stat_unchecked.rs @@ -54,7 +54,7 @@ pub(crate) fn stat_unchecked( // the current working directory returns a similar error, // then stop using `statx`. if let Err(rustix::io::Errno::PERM) = statx( - rustix::fs::cwd(), + rustix::fs::CWD, "", AtFlags::EMPTY_PATH, StatxFlags::empty(), diff --git a/cap-primitives/src/rustix/linux/fs/procfs.rs b/cap-primitives/src/rustix/linux/fs/procfs.rs index b596fc4d..42544c12 100644 --- a/cap-primitives/src/rustix/linux/fs/procfs.rs +++ b/cap-primitives/src/rustix/linux/fs/procfs.rs @@ -10,9 +10,9 @@ use crate::fs::{ errors, open, read_link_unchecked, set_times_follow_unchecked, OpenOptions, SystemTimeSpec, }; use io_lifetimes::{AsFd, AsFilelike}; -use rustix::fs::{chmodat, Mode, OFlags, RawMode}; -use rustix::io::proc_self_fd; +use rustix::fs::{chmodat, AtFlags, Mode, OFlags, RawMode}; use rustix::path::DecInt; +use rustix::procfs::proc_self_fd; use std::os::unix::fs::{OpenOptionsExt, PermissionsExt}; use std::path::{Path, PathBuf}; use std::{fs, io}; @@ -46,7 +46,12 @@ pub(crate) fn set_permissions_through_proc_self_fd( let dirfd = proc_self_fd()?; let mode = Mode::from_bits(perm.mode() as RawMode).ok_or_else(errors::invalid_flags)?; - Ok(chmodat(&dirfd, DecInt::from_fd(&opath), mode)?) + Ok(chmodat( + &dirfd, + DecInt::from_fd(&opath), + mode, + AtFlags::empty(), + )?) } pub(crate) fn set_times_through_proc_self_fd( diff --git a/cap-std/Cargo.toml b/cap-std/Cargo.toml index ee3e45bc..5601ca5c 100644 --- a/cap-std/Cargo.toml +++ b/cap-std/Cargo.toml @@ -24,7 +24,7 @@ io-lifetimes = { version = "1.0.0", default-features = false } camino = { version = "1.0.5", optional = true } [target.'cfg(not(windows))'.dependencies] -rustix = { version = "0.37.0", features = ["fs"] } +rustix = { version = "0.38.0", features = ["fs"] } [features] default = [] diff --git a/cap-tempfile/Cargo.toml b/cap-tempfile/Cargo.toml index 106a2cb0..8c565689 100644 --- a/cap-tempfile/Cargo.toml +++ b/cap-tempfile/Cargo.toml @@ -21,7 +21,7 @@ camino = { version = "1.0.5", optional = true } rand = "0.8.1" [target.'cfg(not(windows))'.dependencies] -rustix = { version = "0.37.0", features = ["procfs"] } +rustix = { version = "0.38.0", features = ["procfs"] } [target.'cfg(windows)'.dev-dependencies.windows-sys] version = "0.45.0" diff --git a/cap-tempfile/src/tempfile.rs b/cap-tempfile/src/tempfile.rs index 4a00f4f3..a8535347 100644 --- a/cap-tempfile/src/tempfile.rs +++ b/cap-tempfile/src/tempfile.rs @@ -84,7 +84,7 @@ fn new_tempfile_linux(d: &Dir, anonymous: bool) -> io::Result> { fn generate_name_in(subdir: &Dir, f: &File) -> io::Result { use rustix::fd::AsFd; use rustix::fs::AtFlags; - let procself_fd = rustix::io::proc_self_fd()?; + let procself_fd = rustix::procfs::proc_self_fd()?; let fdnum = rustix::path::DecInt::from_fd(&f.as_fd()); let fdnum = fdnum.as_c_str(); super::retry_with_name_ignoring(io::ErrorKind::AlreadyExists, |name| { diff --git a/cap-time-ext/Cargo.toml b/cap-time-ext/Cargo.toml index 864893a9..2e75c85e 100644 --- a/cap-time-ext/Cargo.toml +++ b/cap-time-ext/Cargo.toml @@ -17,7 +17,7 @@ cap-primitives = { path = "../cap-primitives", version = "^1.0.9" } cap-std = { path = "../cap-std", optional = true, version = "^1.0.9" } [target.'cfg(not(windows))'.dependencies] -rustix = { version = "0.37.0", features = ["time"] } +rustix = { version = "0.38.0", features = ["time"] } [target.'cfg(windows)'.dependencies] once_cell = "1.5.2" From c425bedca0d2ca9bad156251d2c7ab9ad61c614f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 14:16:22 -0800 Subject: [PATCH 6/8] Update for rustix 0.38. --- cap-primitives/src/rustix/linux/fs/open_impl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cap-primitives/src/rustix/linux/fs/open_impl.rs b/cap-primitives/src/rustix/linux/fs/open_impl.rs index 793b77b0..cfe76b86 100644 --- a/cap-primitives/src/rustix/linux/fs/open_impl.rs +++ b/cap-primitives/src/rustix/linux/fs/open_impl.rs @@ -140,7 +140,7 @@ pub(crate) fn open_beneath( fn openat2_supported() -> bool { // `openat2` is supported in Linux 5.6 and later. Parse the current // Linux version from the `release` field from `uname` to detect this. - let uname = rustix::process::uname(); + let uname = rustix::system::uname(); let release = uname.release().to_bytes(); if let Some((major, minor)) = linux_major_minor(release) { if major >= 6 || (major == 5 && minor >= 6) { From 2edfd6fdfb369beaa13ced48cdf4d7a3351f70ae Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 14:20:40 -0800 Subject: [PATCH 7/8] Fixes. --- Cargo.toml | 2 +- cap-tempfile/src/tempfile.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5336131d..e48542a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ rustix = { version = "0.38.0", features = ["fs"] } nt_version = "0.1.3" [target.'cfg(windows)'.dependencies.windows-sys] -version = "0.45.0" +version = "0.48.0" features = [ "Win32_Storage_FileSystem", "Win32_Foundation", diff --git a/cap-tempfile/src/tempfile.rs b/cap-tempfile/src/tempfile.rs index a8535347..ade0ee98 100644 --- a/cap-tempfile/src/tempfile.rs +++ b/cap-tempfile/src/tempfile.rs @@ -265,7 +265,7 @@ mod test { let metadata = tf.as_file().metadata().unwrap(); let mode = metadata.mode(); let mode = Mode::from_bits_truncate(mode); - assert_eq!(0o666 & !umask, mode.bits()); + assert_eq!(0o666 & !umask, mode.bits() & 0o777); } // And that we can write tf.write_all(b"hello world")?; From 2db2cd00002eddf442d09922bce60beff9a02689 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 22 Nov 2024 14:24:13 -0800 Subject: [PATCH 8/8] Update to windows-sys 0.52. --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e48542a2..f805529d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,10 +40,12 @@ rustix = { version = "0.38.0", features = ["fs"] } nt_version = "0.1.3" [target.'cfg(windows)'.dependencies.windows-sys] -version = "0.48.0" +version = "0.52.0" features = [ "Win32_Storage_FileSystem", "Win32_Foundation", + "Win32_System_IO", + "Win32_System_Ioctl", "Win32_System_SystemServices", ]