diff --git a/Cargo.toml b/Cargo.toml index 7e923c2..c1622be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ license = "MIT" publish = false [dependencies] -libc = "0.2.178" ron = ">=0.8, <0.13" #rust-i18n = "3.1.3" @@ -23,3 +22,9 @@ features = ["derive"] [dependencies.serde] version = "1.0" features = ["derive"] + +[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies] +# Yes. For one constant, this library is required. +# And yes, I spent time tracking down the first release with that constant. +# v0.2.25 is almost 9 years old as of writing this comment. +libc = "~0.2.25" diff --git a/src/cli.rs b/src/cli.rs index 3302322..6728c9c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -35,6 +35,12 @@ pub struct Args { // ArgAction::SetFalse by default evaluates to true, // ArgAction::SetTrue by default evaluates to false. /// Upon encountering a read error, reopen the source file before continuing. - #[arg(short, long, action=ArgAction::SetTrue)] + #[arg(short, long, action = ArgAction::SetTrue)] pub reopen_on_error: bool, + + /// Use O_DIRECT to bypass kernel buffer when reading. + // BSD seems to support O_DIRECT, but MacOS for certain does not. + #[cfg(all(unix, not(target_os = "macos")))] + #[arg(short, long = "direct", action = ArgAction::SetFalse)] + pub direct_io: bool, } diff --git a/src/io.rs b/src/io.rs index 793de77..0e103a2 100644 --- a/src/io.rs +++ b/src/io.rs @@ -1,6 +1,5 @@ use std::fs::{File, OpenOptions}; use std::io::{self, Seek, SeekFrom}; -use std::os::unix::fs::OpenOptionsExt; use crate::cli::CONFIG; @@ -20,10 +19,26 @@ pub fn get_stream_length(stream: &mut S) -> io::Result { len } +#[cfg(all(unix, not(target_os = "macos")))] +pub fn load_input() -> anyhow::Result { + use std::os::unix::fs::OpenOptionsExt; + + let mut options = OpenOptions::new(); + options.read(true); + + if CONFIG.direct_io { + options.custom_flags(libc::O_DIRECT); + } + + options + .open(&CONFIG.input) + .with_context(|| format!("Failed to open input file: {}", &CONFIG.input.display())) +} + +#[cfg(any(not(unix), target_os = "macos"))] pub fn load_input() -> anyhow::Result { OpenOptions::new() .read(true) - .custom_flags(libc::O_DIRECT) .open(&CONFIG.input) .with_context(|| format!("Failed to open input file: {}", &CONFIG.input.display())) }