diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 905b1a16f..09c111162 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -36,14 +36,14 @@ jobs: os: ubuntu-latest features: "" target: "x86_64-unknown-linux-gnu" - # - rust: "stable" - # os: macos-latest - # features: "" - # target: "x86_64-apple-darwin" - # - rust: "stable" - # os: macos-14 - # features: "" - # target: "aarch64-apple-darwin" + - rust: "stable" + os: macos-latest + features: "" + target: "x86_64-apple-darwin" + - rust: "stable" + os: macos-14 + features: "" + target: "aarch64-apple-darwin" # - rust: stable-x86_64-gnu # os: windows-2022 # features: "" diff --git a/bzip2.rs b/bzip2.rs index 23ecc1e7c..86566f153 100644 --- a/bzip2.rs +++ b/bzip2.rs @@ -16,12 +16,24 @@ use libbzip2_rs_sys::{ use libc::{ _exit, close, exit, fclose, fdopen, ferror, fflush, fgetc, fileno, fopen, fread, fwrite, open, perror, remove, rewind, signal, stat, strcat, strcmp, strlen, strncpy, ungetc, utimbuf, write, - FILE, + FILE, O_CREAT, O_EXCL, O_WRONLY, S_IRUSR, S_IWUSR, }; + +// FIXME remove this extern "C" { + #[cfg(all(target_os = "linux", target_env = "gnu"))] static mut stdin: *mut FILE; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + static mut stdout: *mut FILE; + + #[cfg(target_os = "macos")] + #[link_name = "__stdinp"] + static mut stdin: *mut FILE; + #[cfg(target_os = "macos")] + #[link_name = "__stdoutp"] static mut stdout: *mut FILE; } + type Bool = libc::c_uchar; type IntNative = libc::c_int; @@ -907,8 +919,8 @@ unsafe fn fileExists(name: *mut c_char) -> Bool { unsafe fn fopen_output_safely(name: *mut c_char, mode: *const libc::c_char) -> *mut FILE { let fh = open( name, - 0o1 as libc::c_int | 0o100 as libc::c_int | 0o200 as libc::c_int, - 0o200 as libc::c_int | 0o400 as libc::c_int, + O_WRONLY | O_CREAT | O_EXCL, + S_IWUSR as libc::c_uint | S_IRUSR as libc::c_uint, ); if fh == -1 as libc::c_int { return std::ptr::null_mut::(); @@ -971,13 +983,13 @@ unsafe fn countHardLinks(name: *mut c_char) -> i32 { #[cfg(unix)] fn count_hardlinks(path: &Path) -> u64 { - use std::os::linux::fs::MetadataExt; + use std::os::unix::fs::MetadataExt; let Ok(metadata) = path.metadata() else { return 0; }; - metadata.st_nlink().saturating_sub(1) + metadata.nlink().saturating_sub(1) } #[cfg(not(unix))] diff --git a/bzip2recover.rs b/bzip2recover.rs index 36b6a8e50..528ab8e96 100644 --- a/bzip2recover.rs +++ b/bzip2recover.rs @@ -343,7 +343,8 @@ fn main_help(program_name: &Path, in_filename: &Path) -> Result<(), Error> { options.write(true).create(true); #[cfg(unix)] - options.mode(libc::S_IWUSR | libc::S_IRUSR); + #[allow(clippy::unnecessary_cast)] + options.mode(libc::S_IWUSR as u32 | libc::S_IRUSR as u32); #[cfg(unix)] options.custom_flags(libc::O_EXCL); diff --git a/bzlib.rs b/bzlib.rs index 1b0887415..7c71945c0 100644 --- a/bzlib.rs +++ b/bzlib.rs @@ -10,9 +10,19 @@ use crate::decompress::{self, decompress}; use crate::libbzip2_rs_sys_version; use crate::BZ_MAX_UNUSED; +// FIXME remove this extern "C" { - static stdin: *mut FILE; - static stdout: *mut FILE; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + static mut stdin: *mut FILE; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + static mut stdout: *mut FILE; + + #[cfg(target_os = "macos")] + #[link_name = "__stdinp"] + static mut stdin: *mut FILE; + #[cfg(target_os = "macos")] + #[link_name = "__stdoutp"] + static mut stdout: *mut FILE; } pub(crate) const BZ_MAX_ALPHA_SIZE: usize = 258; diff --git a/tests/quick.rs b/tests/quick.rs index 683076478..2d2205de1 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -1594,6 +1594,8 @@ mod compress_command { #[test] #[cfg(unix)] fn io_error() { + use std::os::fd::FromRawFd; + let mut cmd = command(); let tmpdir = tempfile::tempdir().unwrap(); @@ -1601,22 +1603,24 @@ mod compress_command { let sample1_ref = tmpdir.path().join("sample1.ref"); std::fs::copy("tests/input/quick/sample1.ref", &sample1_ref).unwrap(); - let (master, tty) = unsafe { setup_custom_tty() }; - - // dropping here triggers an IO error down the line - drop(master); + let mut pair = [0; 2]; + unsafe { + assert_eq!(libc::pipe(&mut pair as *mut [i32; 2] as *mut i32), 0); + // closing the read side here triggers an IO error down the line + assert_eq!(libc::close(pair[0]), 0); + } expect_failure!( cmd.arg("-z") .arg("-c") .arg("-k") .arg(&sample1_ref) - .stdout(tty), + .stdout(unsafe { Stdio::from_raw_fd(pair[1]) }), format!( concat!( "\n", "bzip2: I/O or other error, bailing out. Possible reason follows.\n", - "bzip2: Input/output error\n", + "bzip2: Broken pipe\n", "\tInput file = {in_file}, output file = (stdout)\n", "" ),