From 4b6e6c1aa1ea10091284c81bc9250feabd45c58c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:21:58 +0100 Subject: [PATCH] [WIP] Add support for Windows --- .github/workflows/checks.yaml | 12 ++-- bzip2.rs | 103 +++++++++++++++++++++++----------- bzlib.rs | 34 +++++++++-- tests/quick.rs | 2 + 4 files changed, 108 insertions(+), 43 deletions(-) diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 09c111162..ca2593187 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -6,8 +6,8 @@ permissions: on: push: branches: - - main - - 'release/**' + # - main + # - 'release/**' pull_request: branches-ignore: - 'release/**' @@ -44,10 +44,10 @@ jobs: os: macos-14 features: "" target: "aarch64-apple-darwin" - # - rust: stable-x86_64-gnu - # os: windows-2022 - # features: "" - # target: "x86_64-pc-windows-gnu" + - rust: stable-x86_64-gnu + os: windows-2022 + features: "" + target: "x86_64-pc-windows-gnu" steps: - name: Checkout sources uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 diff --git a/bzip2.rs b/bzip2.rs index df0312fec..173fc1afd 100644 --- a/bzip2.rs +++ b/bzip2.rs @@ -14,12 +14,13 @@ 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, O_CREAT, O_EXCL, O_WRONLY, SIGBUS, SIGHUP, SIGINT, SIGSEGV, SIGTERM, S_IRUSR, S_IWUSR, + _exit, exit, fclose, ferror, fflush, fgetc, fileno, fopen, fread, fwrite, perror, remove, + rewind, signal, stat, strcat, strcmp, strlen, strncpy, ungetc, write, FILE, SIGINT, SIGSEGV, + SIGTERM, }; // FIXME remove this +#[cfg(not(target_os = "windows"))] extern "C" { #[cfg_attr(target_os = "macos", link_name = "__stdinp")] static mut stdin: *mut FILE; @@ -27,6 +28,35 @@ extern "C" { static mut stdout: *mut FILE; } +#[cfg(all(target_os = "windows", target_env = "gnu"))] +extern "C" { + fn __acrt_iob_func(idx: libc::c_uint) -> *mut FILE; +} + +macro_rules! STDIN { + () => { + 'block: { + #[cfg(not(target_os = "windows"))] + break 'block stdin; + + #[cfg(all(target_os = "windows", target_env = "gnu"))] + break 'block __acrt_iob_func(0); + } + }; +} + +macro_rules! STDOUT { + () => { + 'block: { + #[cfg(not(target_os = "windows"))] + break 'block stdout; + + #[cfg(all(target_os = "windows", target_env = "gnu"))] + break 'block __acrt_iob_func(1); + } + }; +} + type Bool = libc::c_uchar; type IntNative = libc::c_int; @@ -197,7 +227,7 @@ unsafe fn compressStream(stream: *mut FILE, zStream: *mut FILE) { ioError() } - if zStream != stdout { + if zStream != STDOUT!() { let fd = fileno(zStream); if fd < 0 { // diverges @@ -373,7 +403,7 @@ unsafe fn uncompressStream(zStream: *mut FILE, stream: *mut FILE) -> bool { ioError() } - if stream != stdout { + if stream != STDOUT!() { let fd: i32 = fileno(stream); if fd < 0 { // diverges @@ -399,7 +429,7 @@ unsafe fn uncompressStream(zStream: *mut FILE, stream: *mut FILE) -> bool { ioError() } - if stream != stdout { + if stream != STDOUT!() { ret = fclose(stream); outputHandleJustInCase = core::ptr::null_mut(); if ret == libc::EOF { @@ -462,10 +492,10 @@ unsafe fn uncompressStream(zStream: *mut FILE, stream: *mut FILE) -> bool { libbzip2_rs_sys::BZ_MEM_ERROR => outOfMemory(), libbzip2_rs_sys::BZ_UNEXPECTED_EOF => compressedStreamEOF(), libbzip2_rs_sys::BZ_DATA_ERROR_MAGIC => { - if zStream != stdin { + if zStream != STDIN!() { fclose(zStream); } - if stream != stdout { + if stream != STDOUT!() { fclose(stream); } if streamNo == 1 { @@ -591,7 +621,7 @@ unsafe fn testStream(zStream: *mut FILE) -> bool { false } libbzip2_rs_sys::BZ_DATA_ERROR_MAGIC => { - if zStream != stdin { + if zStream != STDIN!() { fclose(zStream); } if streamNo == 1 { @@ -906,19 +936,24 @@ unsafe fn fileExists(name: *mut c_char) -> Bool { exists } unsafe fn fopen_output_safely(name: *mut c_char, mode: *const libc::c_char) -> *mut FILE { - let fh = open( - name, - 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::(); - } - let fp = fdopen(fh, mode); - if fp.is_null() { - close(fh); + #[cfg(unix)] + { + let fh = libc::open( + name, + libc::O_WRONLY | libc::O_CREAT | libc::O_EXCL, + libc::S_IWUSR as libc::c_uint | libc::S_IRUSR as libc::c_uint, + ); + if fh == -1 as libc::c_int { + return std::ptr::null_mut::(); + } + let fp = libc::fdopen(fh, mode); + if fp.is_null() { + libc::close(fh); + } + fp } - fp + #[cfg(not(unix))] + libc::fopen(name, mode) } fn not_a_standard_file(path: &Path) -> bool { @@ -966,7 +1001,7 @@ unsafe fn countHardLinks(name: *mut c_char) -> i32 { (statBuf.st_nlink).wrapping_sub(1) as i32 } #[cfg(not(unix))] -unsafe fn countHardLinks(name: *mut c_char) -> i32 { +unsafe fn countHardLinks(_name: *mut c_char) -> i32 { 0 // FIXME } @@ -982,7 +1017,7 @@ fn count_hardlinks(path: &Path) -> u64 { } #[cfg(not(unix))] -unsafe fn count_hardlinks(path: &Path) -> u64 { +unsafe fn count_hardlinks(_path: &Path) -> u64 { 0 // FIXME } @@ -995,7 +1030,7 @@ unsafe fn saveInputFileMetaInfo(srcName: *mut c_char) { } #[cfg(unix)] unsafe fn applySavedTimeInfoToOutputFile(dstName: *mut c_char) { - let mut uTimBuf: utimbuf = utimbuf { + let mut uTimBuf = libc::utimbuf { actime: 0, modtime: 0, }; @@ -1208,8 +1243,8 @@ unsafe fn compress(name: *mut c_char) { } match srcMode { SourceMode::I2O => { - inStr = stdin; - outStr = stdout; + inStr = STDIN!(); + outStr = STDOUT!(); if std::io::stdout().is_terminal() { eprintln!( "{}: I won't write compressed data to a terminal.", @@ -1229,7 +1264,7 @@ unsafe fn compress(name: *mut c_char) { inName.as_mut_ptr(), b"rb\0" as *const u8 as *const libc::c_char, ); - outStr = stdout; + outStr = STDOUT!(); if std::io::stdout().is_terminal() { eprintln!( "{}: I won't write compressed data to a terminal.", @@ -1471,8 +1506,8 @@ unsafe fn uncompress(name: Option) { match srcMode { SourceMode::I2O => { - inStr = stdin; - outStr = stdout; + inStr = STDIN!(); + outStr = STDOUT!(); if std::io::stdin().is_terminal() { eprint!( concat!( @@ -1490,7 +1525,7 @@ unsafe fn uncompress(name: Option) { inName.as_mut_ptr(), b"rb\0" as *const u8 as *const libc::c_char, ); - outStr = stdout; + outStr = STDOUT!(); if inStr.is_null() { eprintln!( "{}: Can't open input file {}: {}.", @@ -1679,7 +1714,7 @@ unsafe fn testf(name: Option) { setExit(1); return; } - inStr = stdin; + inStr = STDIN!(); } SourceMode::F2O | SourceMode::F2F => { inStr = fopen( @@ -1814,8 +1849,9 @@ unsafe fn main_0(program_path: &Path) -> IntNative { SIGSEGV, mySIGSEGVorSIGBUScatcher as unsafe extern "C" fn(libc::c_int) as usize, ); + #[cfg(not(target_os = "windows"))] signal( - SIGBUS, + libc::SIGBUS, mySIGSEGVorSIGBUScatcher as unsafe extern "C" fn(libc::c_int) as usize, ); @@ -1991,8 +2027,9 @@ unsafe fn main_0(program_path: &Path) -> IntNative { SIGTERM, mySignalCatcher as unsafe extern "C" fn(IntNative) as usize, ); + #[cfg(not(target_os = "windows"))] signal( - SIGHUP, + libc::SIGHUP, mySignalCatcher as unsafe extern "C" fn(IntNative) as usize, ); } diff --git a/bzlib.rs b/bzlib.rs index 12be97ea8..b3dc88eb5 100644 --- a/bzlib.rs +++ b/bzlib.rs @@ -11,6 +11,7 @@ use crate::libbzip2_rs_sys_version; use crate::BZ_MAX_UNUSED; // FIXME remove this +#[cfg(not(target_os = "windows"))] extern "C" { #[cfg_attr(target_os = "macos", link_name = "__stdinp")] static mut stdin: *mut FILE; @@ -18,6 +19,31 @@ extern "C" { static mut stdout: *mut FILE; } +#[cfg(all(target_os = "windows", target_env = "gnu"))] +extern "C" { + fn __acrt_iob_func(idx: libc::c_uint) -> *mut FILE; +} + +macro_rules! STDIN { + () => {'block: { + #[cfg(not(target_os = "windows"))] + break 'block stdin; + + #[cfg(all(target_os = "windows", target_env = "gnu"))] + break 'block __acrt_iob_func(0); + }}; +} + +macro_rules! STDOUT { + () => {'block: { + #[cfg(not(target_os = "windows"))] + break 'block stdout; + + #[cfg(all(target_os = "windows", target_env = "gnu"))] + break 'block __acrt_iob_func(1); + }}; +} + pub(crate) const BZ_MAX_ALPHA_SIZE: usize = 258; pub(crate) const BZ_MAX_CODE_LEN: usize = 23; @@ -2660,8 +2686,8 @@ unsafe fn bzopen_or_bzdopen(path: Option<&CStr>, open_mode: OpenMode, mode: &CSt let mode2 = mode.as_ptr().cast_mut().cast::(); let default_file = match operation { - Operation::Reading => stdin, - Operation::Writing => stdout, + Operation::Reading => STDIN!(), + Operation::Writing => STDOUT!(), }; let fp = match open_mode { @@ -2696,7 +2722,7 @@ unsafe fn bzopen_or_bzdopen(path: Option<&CStr>, open_mode: OpenMode, mode: &CSt }; if bzfp.is_null() { - if fp != stdin && fp != stdout { + if fp != STDIN!() && fp != STDOUT!() { fclose(fp); } return ptr::null_mut(); @@ -2889,7 +2915,7 @@ pub unsafe extern "C" fn BZ2_bzclose(b: *mut BZFILE) { } } - if fp != stdin && fp != stdout { + if fp != STDIN!() && fp != STDOUT!() { fclose(fp); } } diff --git a/tests/quick.rs b/tests/quick.rs index 95bde5260..38189172b 100644 --- a/tests/quick.rs +++ b/tests/quick.rs @@ -710,6 +710,7 @@ mod decompress_command { ); } + #[cfg(unix)] #[test] fn input_file_cannot_be_read_f2o() { use std::os::unix::fs::PermissionsExt; @@ -1449,6 +1450,7 @@ mod compress_command { ); } + #[cfg(unix)] #[test] fn input_file_cannot_be_read_f2o() { use std::os::unix::fs::PermissionsExt;