Skip to content

Commit

Permalink
[WIP] Add support for Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Nov 12, 2024
1 parent 82443b8 commit c846363
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 43 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ permissions:
on:
push:
branches:
- main
- 'release/**'
# - main
# - 'release/**'
pull_request:
branches-ignore:
- 'release/**'
Expand Down Expand Up @@ -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
Expand Down
103 changes: 70 additions & 33 deletions bzip2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,49 @@ 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;
#[cfg_attr(target_os = "macos", link_name = "__stdoutp")]
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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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::<FILE>();
}
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::<FILE>();
}
let fp = libc::fdopen(fh, mode);
if fp.is_null() {
libc::close(fh);

Check warning on line 951 in bzip2.rs

View check run for this annotation

Codecov / codecov/patch

bzip2.rs#L951

Added line #L951 was not covered by tests
}
fp
}
fp
#[cfg(not(unix))]
libc::fopen(name, mode)
}

fn not_a_standard_file(path: &Path) -> bool {
Expand Down Expand Up @@ -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
}

Expand All @@ -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
}

Expand All @@ -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,
};
Expand Down Expand Up @@ -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.",
Expand All @@ -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.",
Expand Down Expand Up @@ -1471,8 +1506,8 @@ unsafe fn uncompress(name: Option<String>) {

match srcMode {
SourceMode::I2O => {
inStr = stdin;
outStr = stdout;
inStr = STDIN!();
outStr = STDOUT!();
if std::io::stdin().is_terminal() {
eprint!(
concat!(
Expand All @@ -1490,7 +1525,7 @@ unsafe fn uncompress(name: Option<String>) {
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 {}: {}.",
Expand Down Expand Up @@ -1679,7 +1714,7 @@ unsafe fn testf(name: Option<String>) {
setExit(1);
return;
}
inStr = stdin;
inStr = STDIN!();
}
SourceMode::F2O | SourceMode::F2F => {
inStr = fopen(
Expand Down Expand Up @@ -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,
);

Expand Down Expand Up @@ -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,
);
}
Expand Down
34 changes: 30 additions & 4 deletions bzlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,39 @@ 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;
#[cfg_attr(target_os = "macos", link_name = "__stdoutp")]
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;

Expand Down Expand Up @@ -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::<c_char>();

let default_file = match operation {
Operation::Reading => stdin,
Operation::Writing => stdout,
Operation::Reading => STDIN!(),
Operation::Writing => STDOUT!(),
};

let fp = match open_mode {
Expand Down Expand Up @@ -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!() {

Check warning on line 2725 in bzlib.rs

View check run for this annotation

Codecov / codecov/patch

bzlib.rs#L2725

Added line #L2725 was not covered by tests
fclose(fp);
}
return ptr::null_mut();
Expand Down Expand Up @@ -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);
}
}
Expand Down
3 changes: 3 additions & 0 deletions tests/quick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,7 @@ mod decompress_command {
);
}

#[cfg(unix)]
#[test]
fn input_file_cannot_be_read_f2o() {
use std::os::unix::fs::PermissionsExt;
Expand Down Expand Up @@ -1449,6 +1450,7 @@ mod compress_command {
);
}

#[cfg(unix)]
#[test]
fn input_file_cannot_be_read_f2o() {
use std::os::unix::fs::PermissionsExt;
Expand Down Expand Up @@ -1549,6 +1551,7 @@ mod compress_command {
}

#[test]
#[cfg(unix)]
fn stdout_is_terminal_i2o() {
let mut cmd = command();

Expand Down

0 comments on commit c846363

Please sign in to comment.