From 47e540e06bc17c72e7b470bc146f181953525bb5 Mon Sep 17 00:00:00 2001 From: Scott Hutton Date: Wed, 24 Jan 2024 09:50:17 -0800 Subject: [PATCH 1/4] Move clamav-sys/build_internal.rs for duplication --- libclamav_rust/build.rs => clamav-sys/build_internal.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename libclamav_rust/build.rs => clamav-sys/build_internal.rs (100%) diff --git a/libclamav_rust/build.rs b/clamav-sys/build_internal.rs similarity index 100% rename from libclamav_rust/build.rs rename to clamav-sys/build_internal.rs From 40a3b0a0e1d5208a25e0d072743ce6f56b18f1ff Mon Sep 17 00:00:00 2001 From: Scott Hutton Date: Wed, 24 Jan 2024 09:52:21 -0800 Subject: [PATCH 2/4] Restore libclamav_rust/build.rs for duplication --- libclamav_rust/build.rs | 341 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 341 insertions(+) create mode 100644 libclamav_rust/build.rs diff --git a/libclamav_rust/build.rs b/libclamav_rust/build.rs new file mode 100644 index 0000000000..36dd19dd77 --- /dev/null +++ b/libclamav_rust/build.rs @@ -0,0 +1,341 @@ +use std::env; +use std::path::{Path, PathBuf}; + +use bindgen::builder; + +// Note to maintainers: this is currently a hybrid of examination of the +// CMake environment, and leaning on Rust `cfg` elements. Ideally, it +// should be possible to work in this space (e.g., execute tests from an +// IDE) without having to rely on CMake elements to properly link the +// unit tests). Hence the bizarre mix of CMake inspection and Cargo-based +// elements. +// +// It's handy to know that all the `cfg` goodies are defined here: +// +// https://doc.rust-lang.org/reference/conditional-compilation.html + +// A list of environment variables to query to determine additional libraries +// that need to be linked to resolve dependencies. +const LIB_ENV_LINK: &[&str] = &[ + "LIBSSL", + "LIBCRYPTO", + "LIBZ", + "LIBBZ2", + "LIBPCRE2", + "LIBXML2", + "LIBCURL", + "LIBJSONC", + "LIBCLAMMSPACK", + "LIBCLAMUNRARIFACE", + "LIBCLAMUNRAR", + "LIBICONV", +]; + +// The same, but additional values to check on Windows platforms +const LIB_ENV_LINK_WINDOWS: &[&str] = &["LIBPTHREADW32", "LIBWIN32COMPAT"]; + +// Additional [verbatim] libraries to link on Windows platforms +const LIB_LINK_WINDOWS: &[&str] = &["wsock32", "ws2_32", "Shell32", "User32"]; + +// Windows library names that must have the leading `lib` trimmed (if encountered) +const WINDOWS_TRIM_LOCAL_LIB: &[&str] = &["libclamav", "libclammspack"]; + +// Generate bindings for these functions: +const BINDGEN_FUNCTIONS: &[&str] = &[ + "cli_ctx", + "cli_warnmsg", + "cli_dbgmsg_no_inline", + "cli_infomsg_simple", + "cli_errmsg", + "cli_append_virus", + "lsig_increment_subsig_match", + "cli_versig2", + "cli_getdsig", + "cli_get_debug_flag", + "cli_magic_scan_buff", +]; + +// Generate bindings for these types (structs, enums): +const BINDGEN_TYPES: &[&str] = &[ + "cli_matcher", + "cli_ac_data", + "cli_ac_result", + "css_image_extractor_t", + "css_image_handle_t", + "onedump_t", +]; + +// Find the required functions and types in these headers: +const BINDGEN_HEADERS: &[&str] = &[ + "../libclamav/matcher.h", + "../libclamav/matcher-ac.h", + "../libclamav/others.h", + "../libclamav/dsig.h", + "../libclamav/htmlnorm.h", + "../libclamav/fmap.h", + "../libclamav/scanners.h", +]; + +// Find the required headers in these directories: +const BINDGEN_INCLUDE_PATHS: &[&str] = &[ + "-I../libclamav", + "-I../libclamunrar_iface", + "-I../libclammspack", +]; + +// Write the bindings to this file: +const BINDGEN_OUTPUT_FILE: &str = "src/sys.rs"; + +const C_HEADER_OUTPUT: &str = "clamav_rust.h"; + +// Environment variable name prefixes worth including for diags +const ENV_PATTERNS: &[&str] = &["CARGO_", "RUST", "LIB"]; + +fn main() -> Result<(), &'static str> { + // Dump the command line and interesting environment variables for diagnostic + // purposes. These will end up in a 'stderr' file under the target directory, + // in a ".../clamav_rust-" subdirectory + + eprintln!("build.rs command line: {:?}", std::env::args()); + eprintln!("Environment:"); + std::env::vars() + .filter(|(k, _)| ENV_PATTERNS.iter().any(|prefix| k.starts_with(prefix))) + .for_each(|(k, v)| eprintln!(" {}={:?}", k, v)); + + detect_clamav_build()?; + + // We only want to generate bindings for `cargo build`, not `cargo test`. + // FindRust.cmake defines $CARGO_CMD so we can differentiate. + let cargo_cmd = env::var("CARGO_CMD").unwrap_or_else(|_| "".into()); + if cargo_cmd == "build" { + // Always generate the C-headers when CMake kicks off a build. + execute_cbindgen()?; + + // Only generate the `.rs` bindings when maintainer-mode is enabled. + // + // Bindgen requires libclang, which may not readily available, so we + // will commit the bindings to version control and use maintainer-mode + // to update them, as needed. + // On the plus-side, this means that our `.rs` file is present before our + // first build, so at least rust-analyzer will be happy. + let maintainer_mode = env::var("MAINTAINER_MODE").unwrap_or_else(|_| "".into()); + if maintainer_mode == "ON" { + execute_bindgen()?; + } + } else { + eprintln!("NOTE: Not generating bindings because CARGO_CMD != build"); + } + + Ok(()) +} + +/// Use bindgen to generate Rust bindings to call into C libraries. +fn execute_bindgen() -> Result<(), &'static str> { + let build_dir = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".into())); + let build_include_path = format!("-I{}", build_dir.join(".").to_str().unwrap()); + let has_include_directories = env::var("CARGO_INCLUDE_DIRECTORIES").ok(); + + // Configure and generate bindings. + let mut builder = builder() + // Silence code-style warnings for generated bindings. + .raw_line("#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]") + // Make the bindings pretty. + .formatter(bindgen::Formatter::Rustfmt) + // Disable the layout tests. + // We're committing to source control. Pointer width, integer size, etc + // are probably not the same when generated as when compiled. + .layout_tests(false) + // Enable bindgen to find generated headers in the build directory, too. + .clang_arg(build_include_path); + + // If include directories were specified, add them to the builder. + if let Some(include_directories) = has_include_directories { + for include_directory in include_directories.split(';') { + // Enable bindgen to find dependencies headers. + builder = builder.clang_arg(format!("-I{include_directory}")); + } + } + + for &include_path in BINDGEN_INCLUDE_PATHS { + builder = builder.clang_arg(include_path); + } + for &header in BINDGEN_HEADERS { + builder = builder.header(header); + } + for &c_function in BINDGEN_FUNCTIONS { + builder = builder.allowlist_function(c_function); + } + for &c_type in BINDGEN_TYPES { + builder = builder.allowlist_type(c_type); + } + + // Generate! + builder + .generate() + .expect("Generating Rust bindings for C code") + .write_to_file(BINDGEN_OUTPUT_FILE) + .expect("Writing Rust bindings to output file"); + + eprintln!("bindgen outputting \"{}\"", BINDGEN_OUTPUT_FILE); + + Ok(()) +} + +/// Use cbindgen to generate C-header's for Rust static libraries. +fn execute_cbindgen() -> Result<(), &'static str> { + let crate_dir = env::var("CARGO_MANIFEST_DIR").or(Err("CARGO_MANIFEST_DIR not specified"))?; + let build_dir = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".into())); + let outfile_path = build_dir.join(C_HEADER_OUTPUT); + + // Useful for build diagnostics + eprintln!("cbindgen outputting {:?}", &outfile_path); + cbindgen::generate(crate_dir) + .expect("Unable to generate bindings") + .write_to_file(&outfile_path); + + Ok(()) +} + +fn detect_clamav_build() -> Result<(), &'static str> { + println!("cargo:rerun-if-env-changed=LIBCLAMAV"); + + if search_and_link_lib("LIBCLAMAV")? { + eprintln!("NOTE: LIBCLAMAV defined. Examining LIB* environment variables"); + // Need to link with libclamav dependencies + + // LLVM is optional, and don't have a path to each library like we do with the other libs. + let llvm_libs = env::var("LLVM_LIBS").unwrap_or("".into()); + if !llvm_libs.is_empty() { + match env::var("LLVM_DIRS") { + Err(env::VarError::NotPresent) => eprintln!("LLVM_DIRS not set"), + Err(env::VarError::NotUnicode(_)) => return Err("environment value not unicode"), + Ok(s) => { + if s.is_empty() { + eprintln!("LLVM_DIRS not set"); + } else { + s.split(',').for_each(|dirpath| { + println!("cargo:rustc-link-search={}", dirpath); + }); + } + } + }; + + llvm_libs + .split(',') + .for_each(|filepath_str| match parse_lib_path(filepath_str) { + Ok(parsed_path) => { + println!("cargo:rustc-link-search={}", parsed_path.dir); + eprintln!(" - requesting that rustc link {:?}", &parsed_path.libname); + println!("cargo:rustc-link-lib={}", parsed_path.libname); + } + Err(_) => { + eprintln!(" - requesting that rustc link {:?}", filepath_str); + println!("cargo:rustc-link-lib={}", filepath_str); + } + }); + } + + for var in LIB_ENV_LINK { + let _ = search_and_link_lib(var); + } + + if cfg!(windows) { + for var in LIB_ENV_LINK_WINDOWS { + let _ = search_and_link_lib(var); + } + for lib in LIB_LINK_WINDOWS { + println!("cargo:rustc-link-lib={}", lib); + } + } else { + // Link the test executable with libstdc++ on unix systems, + // This is needed for fully-static build where clamav & 3rd party + // dependencies excluding the std libs are static. + if cfg!(target_os = "linux") { + eprintln!("NOTE: linking libstdc++ (linux target)"); + println!("cargo:rustc-link-lib=stdc++"); + } else { + eprintln!("NOTE: NOT linking libstdc++ (non-linux target)"); + } + } + } else { + println!("NOTE: LIBCLAMAV not defined"); + } + + Ok(()) +} + +// +// Return whether the specified environment variable has been set, and output +// linking directives as a side-effect +// +fn search_and_link_lib(environment_variable: &str) -> Result { + eprintln!(" - checking for {:?} in environment", environment_variable); + let filepath_str = match env::var(environment_variable) { + Err(env::VarError::NotPresent) => return Ok(false), + Err(env::VarError::NotUnicode(_)) => return Err("environment value not unicode"), + Ok(s) => { + if s.is_empty() { + return Ok(false); + } else { + s + } + } + }; + + let parsed_path = parse_lib_path(&filepath_str)?; + eprintln!( + " - adding {:?} to rustc library search path", + &parsed_path.dir + ); + println!("cargo:rustc-link-search={}", parsed_path.dir); + eprintln!(" - requesting that rustc link {:?}", &parsed_path.libname); + println!("cargo:rustc-link-lib={}", parsed_path.libname); + + Ok(true) +} + +struct ParsedLibraryPath { + dir: String, + libname: String, +} + +// Parse a library path, returning the portion expected after the `-l`, and the +// directory containing the library +fn parse_lib_path(path: &str) -> Result { + let path = PathBuf::from(path); + let file_name = path + .file_name() + .ok_or("file name not found")? + .to_str() + .ok_or("file name not unicode")?; + + // This can't fail because it came from a &str + let dir = path + .parent() + .unwrap_or_else(|| Path::new(".")) + .to_str() + .unwrap() + .to_owned(); + + // Grab the portion up to the first '.' + let full_libname = file_name + .split('.') + .next() + .ok_or("no '.' found in file name")?; + + // Windows typically requires the full filename when linking system libraries, + // but not when it's one of the locally-generated libraries. + let should_trim_leading_lib = + !cfg!(windows) || WINDOWS_TRIM_LOCAL_LIB.iter().any(|s| *s == full_libname); + + let libname = if should_trim_leading_lib { + full_libname + .strip_prefix("lib") + .ok_or(r#"file name doesn't begin with "lib""#)? + } else { + full_libname + } + .to_owned(); + + Ok(ParsedLibraryPath { dir, libname }) +} From b988623acf912b6e676290388d2c6d00e1613b84 Mon Sep 17 00:00:00 2001 From: Scott Hutton Date: Wed, 24 Jan 2024 10:08:49 -0800 Subject: [PATCH 3/4] Refactor bindgen/cbindgen --- clamav-sys/Cargo.toml | 3 +- clamav-sys/build.rs | 125 ++- clamav-sys/build_internal.rs | 78 +- clamav-sys/no-libclang/bindings.rs | 1061 ++++++++++++++++++++++++ clamav-sys/no-libclang/sys.rs | 1220 ++++++++++++++++++++++++++++ clamav-sys/src/lib.rs | 5 + libclamav_rust/Cargo.toml | 7 +- libclamav_rust/build.rs | 293 +------ libclamav_rust/src/lib.rs | 2 +- 9 files changed, 2430 insertions(+), 364 deletions(-) create mode 100644 clamav-sys/no-libclang/bindings.rs create mode 100644 clamav-sys/no-libclang/sys.rs diff --git a/clamav-sys/Cargo.toml b/clamav-sys/Cargo.toml index 6beff91f14..27e7f69d4a 100644 --- a/clamav-sys/Cargo.toml +++ b/clamav-sys/Cargo.toml @@ -13,7 +13,8 @@ repository = "https://github.com/Cisco-Talos/clamav-sys/" version = "1.0.0" [build-dependencies] -bindgen = "0.64.0" +anyhow = "1.0" +bindgen = "0.69" [target.'cfg(unix)'.build-dependencies] pkg-config = "0.3" diff --git a/clamav-sys/build.rs b/clamav-sys/build.rs index 98479cfe57..3560260371 100644 --- a/clamav-sys/build.rs +++ b/clamav-sys/build.rs @@ -16,8 +16,14 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, // MA 02110-1301, USA. +mod build_internal; + use std::env; -use std::path::PathBuf; +use std::io::Write as _; +use std::path::{Path, PathBuf}; + +// Write the public bindings to this file in maintainer mode +const BINDGEN_OUTPUT_FILE: &str = "no-libclang/bindings.rs"; // Generate bindings for these functions: const BINDGEN_FUNCTIONS: &[&str] = &[ @@ -112,7 +118,10 @@ const BINDGEN_CONSTANTS: &[&str] = &[ const CLAMAV_LIBRARY_NAME: &str = "clamav"; -fn generate_bindings(customize_bindings: &dyn Fn(bindgen::Builder) -> bindgen::Builder) { +fn generate_bindings( + output_path: &Path, + customize_bindings: &dyn Fn(bindgen::Builder) -> bindgen::Builder, +) { let mut bindings = bindgen::Builder::default(); for function in BINDGEN_FUNCTIONS { bindings = bindings.allowlist_function(function); @@ -134,31 +143,30 @@ fn generate_bindings(customize_bindings: &dyn Fn(bindgen::Builder) -> bindgen::B .header("wrapper.h") // Tell cargo to invalidate the built crate whenever any of the // included header files changed. - .parse_callbacks(Box::new(bindgen::CargoCallbacks)); + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())); bindings = customize_bindings(bindings); - // Write the bindings to the $OUT_DIR/bindings.rs file. - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings // Finish the builder and generate the bindings. .generate() // Unwrap the Result and panic on failure. .expect("Unable to generate bindings") - .write_to_file(out_path.join("bindings.rs")) + .write_to_file(output_path) .expect("Couldn't write bindings!"); } fn cargo_common() { - println!("cargo:rustc-link-lib=dylib={}", CLAMAV_LIBRARY_NAME); + if local_clamav_include_path().is_none() { + println!("cargo:rustc-link-lib=dylib={}", CLAMAV_LIBRARY_NAME); + } // Tell cargo to invalidate the built crate whenever the wrapper changes println!("cargo:rerun-if-changed=wrapper.h"); } #[cfg(windows)] -fn main() { +pub fn main() { let include_paths = match vcpkg::find_package("clamav") { Ok(pkg) => pkg.include_paths, Err(err) => { @@ -201,26 +209,87 @@ fn main() { } #[cfg(unix)] -fn main() { - let libclamav = pkg_config::Config::new() - .atleast_version("0.103") - .probe("libclamav") - .unwrap(); - - let mut include_paths = libclamav.include_paths; - - if let Some(val) = std::env::var_os("OPENSSL_ROOT_DIR") { - let mut openssl_include_dir = PathBuf::from(val); - openssl_include_dir.push("include"); - include_paths.push(openssl_include_dir); +fn main() -> anyhow::Result<()> { + let mut include_paths = vec![]; + + let mut output_path_intmod = PathBuf::from(env::var("OUT_DIR")?); + output_path_intmod.push("sys.rs"); + + let local_include_path = local_clamav_include_path(); + + if let Some(include_path) = &local_include_path { + // It seems we're being compiled from within the ClamAV source tree. + // Confirm that clamav.h is there, too + + include_paths.push(include_path.clone()); + + build_internal::bindgen_internal(&output_path_intmod)?; + } else { + // This crate is being referenced from an external project. Utilize the + // system-installed copy of libclamav (as located using pkg-config). + + let libclamav = pkg_config::Config::new() + .atleast_version("0.103") + .probe("libclamav") + .unwrap(); + + include_paths.extend_from_slice(&libclamav.include_paths); + + // Build a vestigial `sys` module, as there will be no access to + // internal APIs. + let mut fh = std::fs::File::create(&output_path_intmod)?; + writeln!(fh, "// This file intentionally left blank").expect("write"); } - cargo_common(); - generate_bindings(&|x: bindgen::Builder| -> bindgen::Builder { - let mut x = x; - for include_path in &include_paths { - x = x.clang_arg("-I").clang_arg(include_path.to_str().unwrap()); + // Write the bindings to the $OUT_DIR/bindings.rs file. + let mut output_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + output_path.push("bindings.rs"); + if local_include_path.is_none() || (local_include_path.is_some() && in_maintainer_mode()) { + cargo_common(); + generate_bindings( + &output_path, + &|builder: bindgen::Builder| -> bindgen::Builder { + let mut builder = builder; + for include_path in &include_paths { + builder = builder + .clang_arg("-I") + .clang_arg(include_path.to_str().unwrap()); + } + builder + }, + ); + // And place a copy in the source tree (for potential check-in) + std::fs::copy(&output_path, BINDGEN_OUTPUT_FILE)?; + } else { + // Otherwise, just copy the pre-generated file to the specified + // location. + std::fs::copy(BINDGEN_OUTPUT_FILE, &output_path)?; + } + + Ok(()) +} + +fn local_clamav_include_path() -> Option { + let manifest_dir = + PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").expect("get CARGO_MANIFEST_DIR env")); + let mut libclamav_dir = manifest_dir + .parent() + .expect("get manifest dir parent") + .to_path_buf(); + libclamav_dir.push("libclamav"); + if libclamav_dir.metadata().is_ok_and(|md| md.is_dir()) { + // It seems we're being compiled from within the ClamAV source tree. + // Just confirm that clamav.h is there, too + let mut clamav_h_path = libclamav_dir.clone(); + clamav_h_path.push("clamav.h"); + if clamav_h_path.metadata().is_ok_and(|md| md.is_file()) { + return Some(libclamav_dir); } - x - }); + } + + None +} + +pub(crate) fn in_maintainer_mode() -> bool { + env::var("MAINTAINER_MODE").unwrap_or_default() == "ON" } diff --git a/clamav-sys/build_internal.rs b/clamav-sys/build_internal.rs index 36dd19dd77..d0236b3c6b 100644 --- a/clamav-sys/build_internal.rs +++ b/clamav-sys/build_internal.rs @@ -1,6 +1,7 @@ use std::env; use std::path::{Path, PathBuf}; +use anyhow::anyhow; use bindgen::builder; // Note to maintainers: this is currently a hybrid of examination of the @@ -83,15 +84,13 @@ const BINDGEN_INCLUDE_PATHS: &[&str] = &[ "-I../libclammspack", ]; -// Write the bindings to this file: -const BINDGEN_OUTPUT_FILE: &str = "src/sys.rs"; - -const C_HEADER_OUTPUT: &str = "clamav_rust.h"; +// Write the internal bindings to this file in maintainer mode +const BINDGEN_OUTPUT_FILE: &str = "no-libclang/sys.rs"; // Environment variable name prefixes worth including for diags const ENV_PATTERNS: &[&str] = &["CARGO_", "RUST", "LIB"]; -fn main() -> Result<(), &'static str> { +pub fn bindgen_internal(output_path: &Path) -> anyhow::Result<()> { // Dump the command line and interesting environment variables for diagnostic // purposes. These will end up in a 'stderr' file under the target directory, // in a ".../clamav_rust-" subdirectory @@ -101,16 +100,12 @@ fn main() -> Result<(), &'static str> { std::env::vars() .filter(|(k, _)| ENV_PATTERNS.iter().any(|prefix| k.starts_with(prefix))) .for_each(|(k, v)| eprintln!(" {}={:?}", k, v)); - - detect_clamav_build()?; + detect_clamav_build().map_err(|e| anyhow!("detect_clamav_build: {e}"))?; // We only want to generate bindings for `cargo build`, not `cargo test`. // FindRust.cmake defines $CARGO_CMD so we can differentiate. let cargo_cmd = env::var("CARGO_CMD").unwrap_or_else(|_| "".into()); if cargo_cmd == "build" { - // Always generate the C-headers when CMake kicks off a build. - execute_cbindgen()?; - // Only generate the `.rs` bindings when maintainer-mode is enabled. // // Bindgen requires libclang, which may not readily available, so we @@ -118,9 +113,16 @@ fn main() -> Result<(), &'static str> { // to update them, as needed. // On the plus-side, this means that our `.rs` file is present before our // first build, so at least rust-analyzer will be happy. - let maintainer_mode = env::var("MAINTAINER_MODE").unwrap_or_else(|_| "".into()); - if maintainer_mode == "ON" { - execute_bindgen()?; + if super::in_maintainer_mode() { + execute_bindgen(output_path).map_err(|e| anyhow!("execute_bindgen: {e}"))?; + // And place a copy in the source tree (for potential check-in) + std::fs::copy(output_path, BINDGEN_OUTPUT_FILE) + .map_err(|e| anyhow!("copying {output_path:?} to {BINDGEN_OUTPUT_FILE}: {e}"))?; + } else { + // Otherwise, just copy the pre-generated file to the specified + // location. + std::fs::copy(BINDGEN_OUTPUT_FILE, output_path) + .map_err(|e| anyhow!("copying {BINDGEN_OUTPUT_FILE} to {output_path:?}: {e}"))?; } } else { eprintln!("NOTE: Not generating bindings because CARGO_CMD != build"); @@ -130,15 +132,13 @@ fn main() -> Result<(), &'static str> { } /// Use bindgen to generate Rust bindings to call into C libraries. -fn execute_bindgen() -> Result<(), &'static str> { +fn execute_bindgen(output_path: &Path) -> anyhow::Result<()> { let build_dir = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".into())); let build_include_path = format!("-I{}", build_dir.join(".").to_str().unwrap()); let has_include_directories = env::var("CARGO_INCLUDE_DIRECTORIES").ok(); // Configure and generate bindings. let mut builder = builder() - // Silence code-style warnings for generated bindings. - .raw_line("#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]") // Make the bindings pretty. .formatter(bindgen::Formatter::Rustfmt) // Disable the layout tests. @@ -173,33 +173,20 @@ fn execute_bindgen() -> Result<(), &'static str> { builder .generate() .expect("Generating Rust bindings for C code") - .write_to_file(BINDGEN_OUTPUT_FILE) + .write_to_file(output_path) .expect("Writing Rust bindings to output file"); - eprintln!("bindgen outputting \"{}\"", BINDGEN_OUTPUT_FILE); + eprintln!("bindgen outputting \"{:?}\"", output_path); Ok(()) } -/// Use cbindgen to generate C-header's for Rust static libraries. -fn execute_cbindgen() -> Result<(), &'static str> { - let crate_dir = env::var("CARGO_MANIFEST_DIR").or(Err("CARGO_MANIFEST_DIR not specified"))?; - let build_dir = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".into())); - let outfile_path = build_dir.join(C_HEADER_OUTPUT); - - // Useful for build diagnostics - eprintln!("cbindgen outputting {:?}", &outfile_path); - cbindgen::generate(crate_dir) - .expect("Unable to generate bindings") - .write_to_file(&outfile_path); - - Ok(()) -} - -fn detect_clamav_build() -> Result<(), &'static str> { +fn detect_clamav_build() -> anyhow::Result<()> { println!("cargo:rerun-if-env-changed=LIBCLAMAV"); - if search_and_link_lib("LIBCLAMAV")? { + if search_and_link_lib("LIBCLAMAV") + .map_err(|e| anyhow!("search_and_link_lib(LIBCLAMAV): {e}"))? + { eprintln!("NOTE: LIBCLAMAV defined. Examining LIB* environment variables"); // Need to link with libclamav dependencies @@ -208,7 +195,9 @@ fn detect_clamav_build() -> Result<(), &'static str> { if !llvm_libs.is_empty() { match env::var("LLVM_DIRS") { Err(env::VarError::NotPresent) => eprintln!("LLVM_DIRS not set"), - Err(env::VarError::NotUnicode(_)) => return Err("environment value not unicode"), + Err(env::VarError::NotUnicode(_)) => { + return Err(anyhow!("environment value not unicode")) + } Ok(s) => { if s.is_empty() { eprintln!("LLVM_DIRS not set"); @@ -268,11 +257,11 @@ fn detect_clamav_build() -> Result<(), &'static str> { // Return whether the specified environment variable has been set, and output // linking directives as a side-effect // -fn search_and_link_lib(environment_variable: &str) -> Result { +fn search_and_link_lib(environment_variable: &str) -> anyhow::Result { eprintln!(" - checking for {:?} in environment", environment_variable); let filepath_str = match env::var(environment_variable) { Err(env::VarError::NotPresent) => return Ok(false), - Err(env::VarError::NotUnicode(_)) => return Err("environment value not unicode"), + Err(env::VarError::NotUnicode(_)) => return Err(anyhow!("environment value not unicode")), Ok(s) => { if s.is_empty() { return Ok(false); @@ -282,7 +271,8 @@ fn search_and_link_lib(environment_variable: &str) -> Result } }; - let parsed_path = parse_lib_path(&filepath_str)?; + let parsed_path = parse_lib_path(&filepath_str) + .map_err(|e| anyhow!("parse_lib_path({filepath_str}): {e}"))?; eprintln!( " - adding {:?} to rustc library search path", &parsed_path.dir @@ -301,13 +291,13 @@ struct ParsedLibraryPath { // Parse a library path, returning the portion expected after the `-l`, and the // directory containing the library -fn parse_lib_path(path: &str) -> Result { +fn parse_lib_path(path: &str) -> anyhow::Result { let path = PathBuf::from(path); let file_name = path .file_name() - .ok_or("file name not found")? + .ok_or(anyhow!("file name not found"))? .to_str() - .ok_or("file name not unicode")?; + .ok_or(anyhow!("file name not unicode"))?; // This can't fail because it came from a &str let dir = path @@ -321,7 +311,7 @@ fn parse_lib_path(path: &str) -> Result { let full_libname = file_name .split('.') .next() - .ok_or("no '.' found in file name")?; + .ok_or(anyhow!("no '.' found in file name"))?; // Windows typically requires the full filename when linking system libraries, // but not when it's one of the locally-generated libraries. @@ -331,7 +321,7 @@ fn parse_lib_path(path: &str) -> Result { let libname = if should_trim_leading_lib { full_libname .strip_prefix("lib") - .ok_or(r#"file name doesn't begin with "lib""#)? + .ok_or(anyhow!(r#"file name doesn't begin with "lib""#))? } else { full_libname } diff --git a/clamav-sys/no-libclang/bindings.rs b/clamav-sys/no-libclang/bindings.rs new file mode 100644 index 0000000000..a6fd64063b --- /dev/null +++ b/clamav-sys/no-libclang/bindings.rs @@ -0,0 +1,1061 @@ +/* automatically generated by rust-bindgen 0.69.2 */ + +pub const CL_DB_PHISHING: u32 = 2; +pub const CL_DB_PHISHING_URLS: u32 = 8; +pub const CL_DB_PUA: u32 = 16; +pub const CL_DB_CVDNOTMP: u32 = 32; +pub const CL_DB_OFFICIAL: u32 = 64; +pub const CL_DB_PUA_MODE: u32 = 128; +pub const CL_DB_PUA_INCLUDE: u32 = 256; +pub const CL_DB_PUA_EXCLUDE: u32 = 512; +pub const CL_DB_COMPILED: u32 = 1024; +pub const CL_DB_DIRECTORY: u32 = 2048; +pub const CL_DB_OFFICIAL_ONLY: u32 = 4096; +pub const CL_DB_BYTECODE: u32 = 8192; +pub const CL_DB_SIGNED: u32 = 16384; +pub const CL_DB_BYTECODE_UNSIGNED: u32 = 32768; +pub const CL_DB_UNSIGNED: u32 = 65536; +pub const CL_DB_BYTECODE_STATS: u32 = 131072; +pub const CL_DB_ENHANCED: u32 = 262144; +pub const CL_DB_PCRE_STATS: u32 = 524288; +pub const CL_DB_YARA_EXCLUDE: u32 = 1048576; +pub const CL_DB_YARA_ONLY: u32 = 2097152; +pub const CL_DB_STDOPT: u32 = 8202; +pub const CL_SCAN_GENERAL_ALLMATCHES: u32 = 1; +pub const CL_SCAN_GENERAL_COLLECT_METADATA: u32 = 2; +pub const CL_SCAN_GENERAL_HEURISTICS: u32 = 4; +pub const CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE: u32 = 8; +pub const CL_SCAN_GENERAL_UNPRIVILEGED: u32 = 16; +pub const CL_SCAN_PARSE_ARCHIVE: u32 = 1; +pub const CL_SCAN_PARSE_ELF: u32 = 2; +pub const CL_SCAN_PARSE_PDF: u32 = 4; +pub const CL_SCAN_PARSE_SWF: u32 = 8; +pub const CL_SCAN_PARSE_HWP3: u32 = 16; +pub const CL_SCAN_PARSE_XMLDOCS: u32 = 32; +pub const CL_SCAN_PARSE_MAIL: u32 = 64; +pub const CL_SCAN_PARSE_OLE2: u32 = 128; +pub const CL_SCAN_PARSE_HTML: u32 = 256; +pub const CL_SCAN_PARSE_PE: u32 = 512; +pub const CL_SCAN_PARSE_ONENOTE: u32 = 1024; +pub const CL_SCAN_HEURISTIC_BROKEN: u32 = 2; +pub const CL_SCAN_HEURISTIC_EXCEEDS_MAX: u32 = 4; +pub const CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH: u32 = 8; +pub const CL_SCAN_HEURISTIC_PHISHING_CLOAK: u32 = 16; +pub const CL_SCAN_HEURISTIC_MACROS: u32 = 32; +pub const CL_SCAN_HEURISTIC_ENCRYPTED_ARCHIVE: u32 = 64; +pub const CL_SCAN_HEURISTIC_ENCRYPTED_DOC: u32 = 128; +pub const CL_SCAN_HEURISTIC_PARTITION_INTXN: u32 = 256; +pub const CL_SCAN_HEURISTIC_STRUCTURED: u32 = 512; +pub const CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL: u32 = 1024; +pub const CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED: u32 = 2048; +pub const CL_SCAN_HEURISTIC_STRUCTURED_CC: u32 = 4096; +pub const CL_SCAN_HEURISTIC_BROKEN_MEDIA: u32 = 8192; +pub const CL_SCAN_MAIL_PARTIAL_MESSAGE: u32 = 1; +pub const CL_SCAN_DEV_COLLECT_SHA: u32 = 1; +pub const CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO: u32 = 2; +pub const ENGINE_OPTIONS_NONE: u32 = 0; +pub const ENGINE_OPTIONS_DISABLE_CACHE: u32 = 1; +pub const ENGINE_OPTIONS_FORCE_TO_DISK: u32 = 2; +pub const ENGINE_OPTIONS_DISABLE_PE_STATS: u32 = 4; +pub const ENGINE_OPTIONS_DISABLE_PE_CERTS: u32 = 8; +pub const ENGINE_OPTIONS_PE_DUMPCERTS: u32 = 16; +pub const CL_INIT_DEFAULT: u32 = 0; +pub const LAYER_ATTRIBUTES_NONE: u32 = 0; +pub const LAYER_ATTRIBUTES_NORMALIZED: u32 = 1; +pub const LAYER_ATTRIBUTES_DECRYPTED: u32 = 2; +pub type __int64_t = ::std::os::raw::c_longlong; +pub type __darwin_time_t = ::std::os::raw::c_long; +pub type __darwin_off_t = __int64_t; +pub type time_t = __darwin_time_t; +pub type off_t = __darwin_off_t; +impl cl_error_t { + pub const CL_CLEAN: cl_error_t = cl_error_t(0); +} +impl cl_error_t { + pub const CL_SUCCESS: cl_error_t = cl_error_t(0); +} +impl cl_error_t { + pub const CL_VIRUS: cl_error_t = cl_error_t(1); +} +impl cl_error_t { + pub const CL_ENULLARG: cl_error_t = cl_error_t(2); +} +impl cl_error_t { + pub const CL_EARG: cl_error_t = cl_error_t(3); +} +impl cl_error_t { + pub const CL_EMALFDB: cl_error_t = cl_error_t(4); +} +impl cl_error_t { + pub const CL_ECVD: cl_error_t = cl_error_t(5); +} +impl cl_error_t { + pub const CL_EVERIFY: cl_error_t = cl_error_t(6); +} +impl cl_error_t { + pub const CL_EUNPACK: cl_error_t = cl_error_t(7); +} +impl cl_error_t { + pub const CL_EOPEN: cl_error_t = cl_error_t(8); +} +impl cl_error_t { + pub const CL_ECREAT: cl_error_t = cl_error_t(9); +} +impl cl_error_t { + pub const CL_EUNLINK: cl_error_t = cl_error_t(10); +} +impl cl_error_t { + pub const CL_ESTAT: cl_error_t = cl_error_t(11); +} +impl cl_error_t { + pub const CL_EREAD: cl_error_t = cl_error_t(12); +} +impl cl_error_t { + pub const CL_ESEEK: cl_error_t = cl_error_t(13); +} +impl cl_error_t { + pub const CL_EWRITE: cl_error_t = cl_error_t(14); +} +impl cl_error_t { + pub const CL_EDUP: cl_error_t = cl_error_t(15); +} +impl cl_error_t { + pub const CL_EACCES: cl_error_t = cl_error_t(16); +} +impl cl_error_t { + pub const CL_ETMPFILE: cl_error_t = cl_error_t(17); +} +impl cl_error_t { + pub const CL_ETMPDIR: cl_error_t = cl_error_t(18); +} +impl cl_error_t { + pub const CL_EMAP: cl_error_t = cl_error_t(19); +} +impl cl_error_t { + pub const CL_EMEM: cl_error_t = cl_error_t(20); +} +impl cl_error_t { + pub const CL_ETIMEOUT: cl_error_t = cl_error_t(21); +} +impl cl_error_t { + pub const CL_BREAK: cl_error_t = cl_error_t(22); +} +impl cl_error_t { + pub const CL_EMAXREC: cl_error_t = cl_error_t(23); +} +impl cl_error_t { + pub const CL_EMAXSIZE: cl_error_t = cl_error_t(24); +} +impl cl_error_t { + pub const CL_EMAXFILES: cl_error_t = cl_error_t(25); +} +impl cl_error_t { + pub const CL_EFORMAT: cl_error_t = cl_error_t(26); +} +impl cl_error_t { + pub const CL_EPARSE: cl_error_t = cl_error_t(27); +} +impl cl_error_t { + pub const CL_EBYTECODE: cl_error_t = cl_error_t(28); +} +impl cl_error_t { + pub const CL_EBYTECODE_TESTFAIL: cl_error_t = cl_error_t(29); +} +impl cl_error_t { + pub const CL_ELOCK: cl_error_t = cl_error_t(30); +} +impl cl_error_t { + pub const CL_EBUSY: cl_error_t = cl_error_t(31); +} +impl cl_error_t { + pub const CL_ESTATE: cl_error_t = cl_error_t(32); +} +impl cl_error_t { + pub const CL_VERIFIED: cl_error_t = cl_error_t(33); +} +impl cl_error_t { + pub const CL_ERROR: cl_error_t = cl_error_t(34); +} +impl cl_error_t { + pub const CL_ELAST_ERROR: cl_error_t = cl_error_t(35); +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct cl_error_t(pub ::std::os::raw::c_uint); +#[doc = " scan options"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_scan_options { + pub general: u32, + pub parse: u32, + pub heuristic: u32, + pub mail: u32, + pub dev: u32, +} +#[test] +fn bindgen_test_layout_cl_scan_options() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 20usize, + concat!("Size of: ", stringify!(cl_scan_options)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(cl_scan_options)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).general) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(cl_scan_options), + "::", + stringify!(general) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).parse) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(cl_scan_options), + "::", + stringify!(parse) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).heuristic) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(cl_scan_options), + "::", + stringify!(heuristic) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).mail) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(cl_scan_options), + "::", + stringify!(mail) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).dev) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(cl_scan_options), + "::", + stringify!(dev) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_engine { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_settings { + _unused: [u8; 0], +} +extern "C" { + #[doc = " @brief Enable debug messages"] + pub fn cl_debug(); +} +extern "C" { + #[doc = " @brief This function initializes the openssl crypto system.\n\n Called by cl_init() and does not need to be cleaned up as de-init\n is handled automatically by openssl 1.0.2.h and 1.1.0\n\n @return Always returns 0"] + pub fn cl_initialize_crypto() -> ::std::os::raw::c_int; +} +extern "C" { + #[doc = " @brief This is a deprecated function that used to clean up ssl crypto inits.\n\n Call to EVP_cleanup() has been removed since cleanup is now handled by\n auto-deinit as of openssl 1.0.2h and 1.1.0"] + pub fn cl_cleanup_crypto(); +} +extern "C" { + #[doc = " @brief Initialize the ClamAV library.\n\n @param initoptions Unused.\n @return cl_error_t CL_SUCCESS if everything initialized correctly."] + pub fn cl_init(initoptions: ::std::os::raw::c_uint) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Allocate a new scanning engine and initialize default settings.\n\n The engine should be freed with `cl_engine_free()`.\n\n @return struct cl_engine* Pointer to the scanning engine."] + pub fn cl_engine_new() -> *mut cl_engine; +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_SCANSIZE: cl_engine_field = cl_engine_field(0); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_FILESIZE: cl_engine_field = cl_engine_field(1); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_RECURSION: cl_engine_field = cl_engine_field(2); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_FILES: cl_engine_field = cl_engine_field(3); +} +impl cl_engine_field { + pub const CL_ENGINE_MIN_CC_COUNT: cl_engine_field = cl_engine_field(4); +} +impl cl_engine_field { + pub const CL_ENGINE_MIN_SSN_COUNT: cl_engine_field = cl_engine_field(5); +} +impl cl_engine_field { + pub const CL_ENGINE_PUA_CATEGORIES: cl_engine_field = cl_engine_field(6); +} +impl cl_engine_field { + pub const CL_ENGINE_DB_OPTIONS: cl_engine_field = cl_engine_field(7); +} +impl cl_engine_field { + pub const CL_ENGINE_DB_VERSION: cl_engine_field = cl_engine_field(8); +} +impl cl_engine_field { + pub const CL_ENGINE_DB_TIME: cl_engine_field = cl_engine_field(9); +} +impl cl_engine_field { + pub const CL_ENGINE_AC_ONLY: cl_engine_field = cl_engine_field(10); +} +impl cl_engine_field { + pub const CL_ENGINE_AC_MINDEPTH: cl_engine_field = cl_engine_field(11); +} +impl cl_engine_field { + pub const CL_ENGINE_AC_MAXDEPTH: cl_engine_field = cl_engine_field(12); +} +impl cl_engine_field { + pub const CL_ENGINE_TMPDIR: cl_engine_field = cl_engine_field(13); +} +impl cl_engine_field { + pub const CL_ENGINE_KEEPTMP: cl_engine_field = cl_engine_field(14); +} +impl cl_engine_field { + pub const CL_ENGINE_BYTECODE_SECURITY: cl_engine_field = cl_engine_field(15); +} +impl cl_engine_field { + pub const CL_ENGINE_BYTECODE_TIMEOUT: cl_engine_field = cl_engine_field(16); +} +impl cl_engine_field { + pub const CL_ENGINE_BYTECODE_MODE: cl_engine_field = cl_engine_field(17); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_EMBEDDEDPE: cl_engine_field = cl_engine_field(18); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_HTMLNORMALIZE: cl_engine_field = cl_engine_field(19); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_HTMLNOTAGS: cl_engine_field = cl_engine_field(20); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_SCRIPTNORMALIZE: cl_engine_field = cl_engine_field(21); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_ZIPTYPERCG: cl_engine_field = cl_engine_field(22); +} +impl cl_engine_field { + pub const CL_ENGINE_FORCETODISK: cl_engine_field = cl_engine_field(23); +} +impl cl_engine_field { + pub const CL_ENGINE_CACHE_SIZE: cl_engine_field = cl_engine_field(24); +} +impl cl_engine_field { + pub const CL_ENGINE_DISABLE_CACHE: cl_engine_field = cl_engine_field(25); +} +impl cl_engine_field { + pub const CL_ENGINE_DISABLE_PE_STATS: cl_engine_field = cl_engine_field(26); +} +impl cl_engine_field { + pub const CL_ENGINE_STATS_TIMEOUT: cl_engine_field = cl_engine_field(27); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_PARTITIONS: cl_engine_field = cl_engine_field(28); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_ICONSPE: cl_engine_field = cl_engine_field(29); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_RECHWP3: cl_engine_field = cl_engine_field(30); +} +impl cl_engine_field { + pub const CL_ENGINE_MAX_SCANTIME: cl_engine_field = cl_engine_field(31); +} +impl cl_engine_field { + pub const CL_ENGINE_PCRE_MATCH_LIMIT: cl_engine_field = cl_engine_field(32); +} +impl cl_engine_field { + pub const CL_ENGINE_PCRE_RECMATCH_LIMIT: cl_engine_field = cl_engine_field(33); +} +impl cl_engine_field { + pub const CL_ENGINE_PCRE_MAX_FILESIZE: cl_engine_field = cl_engine_field(34); +} +impl cl_engine_field { + pub const CL_ENGINE_DISABLE_PE_CERTS: cl_engine_field = cl_engine_field(35); +} +impl cl_engine_field { + pub const CL_ENGINE_PE_DUMPCERTS: cl_engine_field = cl_engine_field(36); +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct cl_engine_field(pub ::std::os::raw::c_uint); +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_section_hash { + pub md5: [::std::os::raw::c_uchar; 16usize], + pub len: usize, +} +#[test] +fn bindgen_test_layout_cli_section_hash() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(cli_section_hash)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(cli_section_hash)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).md5) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(cli_section_hash), + "::", + stringify!(md5) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(cli_section_hash), + "::", + stringify!(len) + ) + ); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_stats_sections { + pub nsections: usize, + pub sections: *mut cli_section_hash, +} +#[test] +fn bindgen_test_layout_cli_stats_sections() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(cli_stats_sections)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(cli_stats_sections)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).nsections) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(cli_stats_sections), + "::", + stringify!(nsections) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sections) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(cli_stats_sections), + "::", + stringify!(sections) + ) + ); +} +pub type stats_section_t = cli_stats_sections; +extern "C" { + #[doc = " @brief Set a numerical engine option.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine An initialized scan engine.\n @param cl_engine_field A CL_ENGINE option.\n @param num The new engine option value.\n @return cl_error_t CL_SUCCESS if successfully set.\n @return cl_error_t CL_EARG if the field number was incorrect.\n @return cl_error_t CL_ENULLARG null arguments were provided."] + pub fn cl_engine_set_num( + engine: *mut cl_engine, + field: cl_engine_field, + num: ::std::os::raw::c_longlong, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Get a numerical engine option.\n\n @param engine An initialized scan engine.\n @param cl_engine_field A CL_ENGINE option.\n @param err (optional) A cl_error_t status code.\n @return long long The numerical option value."] + pub fn cl_engine_get_num( + engine: *const cl_engine, + field: cl_engine_field, + err: *mut ::std::os::raw::c_int, + ) -> ::std::os::raw::c_longlong; +} +extern "C" { + #[doc = " @brief Set a string engine option.\n\n If the string option has already been set, the existing string will be free'd\n and the new string will replace it.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine An initialized scan engine.\n @param cl_engine_field A CL_ENGINE option.\n @param str The new engine option value.\n @return cl_error_t CL_SUCCESS if successfully set.\n @return cl_error_t CL_EARG if the field number was incorrect.\n @return cl_error_t CL_EMEM if a memory allocation error occurred.\n @return cl_error_t CL_ENULLARG null arguments were provided."] + pub fn cl_engine_set_str( + engine: *mut cl_engine, + field: cl_engine_field, + str_: *const ::std::os::raw::c_char, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Get a string engine option.\n\n @param engine An initialized scan engine.\n @param cl_engine_field A CL_ENGINE option.\n @param err (optional) A cl_error_t status code.\n @return const char * The string option value."] + pub fn cl_engine_get_str( + engine: *const cl_engine, + field: cl_engine_field, + err: *mut ::std::os::raw::c_int, + ) -> *const ::std::os::raw::c_char; +} +extern "C" { + #[doc = " @brief Copy the settings from an existing scan engine.\n\n The cl_settings pointer is allocated and must be freed with cl_engine_settings_free().\n\n @param engine An configured scan engine.\n @return struct cl_settings* The settings."] + pub fn cl_engine_settings_copy(engine: *const cl_engine) -> *mut cl_settings; +} +extern "C" { + #[doc = " @brief Apply settings from a settings structure to a scan engine.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine A scan engine.\n @param settings The settings.\n @return cl_error_t CL_SUCCESS if successful.\n @return cl_error_t CL_EMEM if a memory allocation error occurred."] + pub fn cl_engine_settings_apply( + engine: *mut cl_engine, + settings: *const cl_settings, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Free a settings struct pointer.\n\n @param settings The settings struct pointer.\n @return cl_error_t CL_SUCCESS if successful.\n @return cl_error_t CL_ENULLARG null arguments were provided."] + pub fn cl_engine_settings_free(settings: *mut cl_settings) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Prepare the scanning engine.\n\n Call this after all required databases have been loaded and settings have\n been applied.\n\n @param engine A scan engine.\n @return cl_error_t CL_SUCCESS if successful.\n @return cl_error_t CL_ENULLARG null arguments were provided."] + pub fn cl_engine_compile(engine: *mut cl_engine) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Add a reference count to the engine.\n\n Thread safety mechanism so that the engine is not free'd by another thread.\n\n The engine is initialized with refcount = 1, so this only needs to be called\n for additional scanning threads.\n\n @param engine A scan engine.\n @return cl_error_t CL_SUCCESS if successful.\n @return cl_error_t CL_ENULLARG null arguments were provided."] + pub fn cl_engine_addref(engine: *mut cl_engine) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Free an engine.\n\n Will lower the reference count on an engine. If the reference count hits\n zero, the engine will be freed.\n\n @param engine A scan engine.\n @return cl_error_t CL_SUCCESS if successful.\n @return cl_error_t CL_ENULLARG null arguments were provided."] + pub fn cl_engine_free(engine: *mut cl_engine) -> cl_error_t; +} +#[doc = " @brief Pre-cache callback.\n\n Called for each processed file (both the entry level - AKA 'outer' - file and\n inner files - those generated when processing archive and container files), before\n the actual scanning takes place.\n\n @param fd File descriptor which is about to be scanned.\n @param type File type detected via magic - i.e. NOT on the fly - (e.g. \"CL_TYPE_MSEXE\").\n @param context Opaque application provided data.\n @return CL_CLEAN = File is scanned.\n @return CL_BREAK = Allowed by callback - file is skipped and marked as clean.\n @return CL_VIRUS = Blocked by callback - file is skipped and marked as infected."] +pub type clcb_pre_cache = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + type_: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +extern "C" { + #[doc = " @brief Set a custom pre-cache callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_pre_cache(engine: *mut cl_engine, callback: clcb_pre_cache); +} +#[doc = " @brief File inspection callback.\n\n DISCLAIMER: This interface is to be considered unstable while we continue to evaluate it.\n We may change this interface in the future.\n\n Called for each NEW file (inner and outer).\n Provides capability to record embedded file information during a scan.\n\n @param fd Current file descriptor which is about to be scanned.\n @param type Current file type detected via magic - i.e. NOT on the fly - (e.g. \"CL_TYPE_MSEXE\").\n @param ancestors An array of ancestors filenames of size `recursion_level`. filenames may be NULL.\n @param parent_file_size Parent file size.\n @param file_name Current file name, or NULL if the file does not have a name or ClamAV failed to record the name.\n @param file_size Current file size.\n @param file_buffer Current file buffer pointer.\n @param recursion_level Recursion level / depth of the current file.\n @param layer_attributes See LAYER_ATTRIBUTES_* flags.\n @param context Opaque application provided data.\n @return CL_CLEAN = File is scanned.\n @return CL_BREAK = Whitelisted by callback - file is skipped and marked as clean.\n @return CL_VIRUS = Blacklisted by callback - file is skipped and marked as infected."] +pub type clcb_file_inspection = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + type_: *const ::std::os::raw::c_char, + ancestors: *mut *const ::std::os::raw::c_char, + parent_file_size: usize, + file_name: *const ::std::os::raw::c_char, + file_size: usize, + file_buffer: *const ::std::os::raw::c_char, + recursion_level: u32, + layer_attributes: u32, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +extern "C" { + #[doc = " @brief Set a custom file inspection callback function.\n\n DISCLAIMER: This interface is to be considered unstable while we continue to evaluate it.\n We may change this interface in the future.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_file_inspection( + engine: *mut cl_engine, + callback: clcb_file_inspection, + ); +} +#[doc = " @brief Pre-scan callback.\n\n Called for each NEW file (inner and outer) before the scanning takes place. This is\n roughly the same as clcb_before_cache, but it is affected by clean file caching.\n This means that it won't be called if a clean cached file (inner or outer) is\n scanned a second time.\n\n @param fd File descriptor which is about to be scanned.\n @param type File type detected via magic - i.e. NOT on the fly - (e.g. \"CL_TYPE_MSEXE\").\n @param context Opaque application provided data.\n @return CL_CLEAN = File is scanned.\n @return CL_BREAK = Allowed by callback - file is skipped and marked as clean.\n @return CL_VIRUS = Blocked by callback - file is skipped and marked as infected."] +pub type clcb_pre_scan = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + type_: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +extern "C" { + #[doc = " @brief Set a custom pre-scan callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_pre_scan(engine: *mut cl_engine, callback: clcb_pre_scan); +} +#[doc = " @brief Post-scan callback.\n\n Called for each processed file (inner and outer), after the scanning is complete.\n In all-match mode, the virname will be one of the matches, but there is no\n guarantee in which order the matches will occur, thus the final virname may\n be any one of the matches.\n\n @param fd File descriptor which was scanned.\n @param result The scan result for the file.\n @param virname A signature name if there was one or more matches.\n @param context Opaque application provided data.\n @return Scan result is not overridden.\n @return CL_BREAK = Allowed by callback - scan result is set to CL_CLEAN.\n @return Blocked by callback - scan result is set to CL_VIRUS."] +pub type clcb_post_scan = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + result: ::std::os::raw::c_int, + virname: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +extern "C" { + #[doc = " @brief Set a custom post-scan callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_post_scan(engine: *mut cl_engine, callback: clcb_post_scan); +} +#[doc = " @brief Virus-found callback.\n\n Called for each signature match.\n If all-match is enabled, clcb_virus_found() may be called multiple times per\n scan.\n\n In addition, clcb_virus_found() does not have a return value and thus.\n can not be used to ignore the match.\n\n @param fd File descriptor which was scanned.\n @param virname Virus name.\n @param context Opaque application provided data."] +pub type clcb_virus_found = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + virname: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ), +>; +extern "C" { + #[doc = " @brief Set a custom virus-found callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_virus_found(engine: *mut cl_engine, callback: clcb_virus_found); +} +#[doc = " @brief Signature-load callback.\n\n May be used to ignore signatures at database load time.\n\n WARNING: Some signatures (notably ldb, cbc) can be dependent upon other signatures.\n Failure to preserve dependency chains will result in database loading failure.\n It is the implementor's responsibility to guarantee consistency.\n\n @param type The signature type (e.g. \"db\", \"ndb\", \"mdb\", etc.)\n @param name Signature name.\n @param custom The signature is official (custom == 0) or custom (custom != 0)\n @param context Opaque application provided data\n @return 0 to load the current signature.\n @return Non-0 to skip the current signature."] +pub type clcb_sigload = ::std::option::Option< + unsafe extern "C" fn( + type_: *const ::std::os::raw::c_char, + name: *const ::std::os::raw::c_char, + custom: ::std::os::raw::c_uint, + context: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, +>; +extern "C" { + #[doc = " @brief Set a custom signature-load callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer.\n @param context Opaque application provided data."] + pub fn cl_engine_set_clcb_sigload( + engine: *mut cl_engine, + callback: clcb_sigload, + context: *mut ::std::os::raw::c_void, + ); +} +impl cl_msg { + pub const CL_MSG_INFO_VERBOSE: cl_msg = cl_msg(32); +} +impl cl_msg { + pub const CL_MSG_WARN: cl_msg = cl_msg(64); +} +impl cl_msg { + pub const CL_MSG_ERROR: cl_msg = cl_msg(128); +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct cl_msg(pub ::std::os::raw::c_uint); +#[doc = " @brief Progress callback for sig-load, engine-compile, and engine-free.\n\n Progress is complete when total_items == now_completed.\n\n Note: The callback should return CL_SUCCESS. We reserve the right to have it\n cancel the operation in the future if you return something else...\n ... but for now, the return value will be ignored.\n\n @param total_items Total number of items\n @param now_completed Number of items completed\n @param context Opaque application provided data\n @return cl_error_t reserved for future use"] +pub type clcb_progress = ::std::option::Option< + unsafe extern "C" fn( + total_items: usize, + now_completed: usize, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +extern "C" { + #[doc = " @brief Set a progress callback function to be called incrementally during a\n database load.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine\n @param callback The callback function pointer\n @param context Opaque application provided data"] + pub fn cl_engine_set_clcb_sigload_progress( + engine: *mut cl_engine, + callback: clcb_progress, + context: *mut ::std::os::raw::c_void, + ); +} +extern "C" { + #[doc = " @brief Set a progress callback function to be called incrementally during an\n engine compile.\n\n Disclaimer: the number of items for this is a rough estimate of the items that\n tend to take longest to compile and doesn't represent an accurate number of\n things compiled.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine\n @param callback The callback function pointer\n @param context Opaque application provided data"] + pub fn cl_engine_set_clcb_engine_compile_progress( + engine: *mut cl_engine, + callback: clcb_progress, + context: *mut ::std::os::raw::c_void, + ); +} +extern "C" { + #[doc = " @brief Set a progress callback function to be called incrementally during an\n engine free (if the engine is in fact freed).\n\n Disclaimer: the number of items for this is a rough estimate of the items that\n tend to take longest to free and doesn't represent an accurate number of\n things freed.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine\n @param callback The callback function pointer\n @param context Opaque application provided data"] + pub fn cl_engine_set_clcb_engine_free_progress( + engine: *mut cl_engine, + callback: clcb_progress, + context: *mut ::std::os::raw::c_void, + ); +} +#[doc = " @brief Logging message callback for info, warning, and error messages.\n\n The specified callback will be called instead of logging to stderr.\n Messages of lower severity than specified are logged as usual.\n\n Callback may be used to silence logging by assigning a do-nothing function.\n Does not affect debug log messages.\n\n Just like with cl_debug() this must be called before going multithreaded.\n Callable before cl_init, if you want to log messages from cl_init() itself.\n\n You can use context of cl_scandesc_callback to convey more information to\n the callback (such as the filename!).\n\n Note: setting a 2nd callbacks overwrites previous, multiple callbacks are not\n supported.\n\n @param severity Message severity (CL_MSG_INFO_VERBOSE, CL_MSG_WARN, or CL_MSG_ERROR).\n @param fullmsg The log message including the \"LibClamAV : \" prefix.\n @param msg The log message.\n @param context Opaque application provided data."] +pub type clcb_msg = ::std::option::Option< + unsafe extern "C" fn( + severity: cl_msg, + fullmsg: *const ::std::os::raw::c_char, + msg: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ), +>; +extern "C" { + #[doc = " @brief Set a custom logging message callback function for all of libclamav.\n\n @param callback The callback function pointer."] + pub fn cl_set_clcb_msg(callback: clcb_msg); +} +#[doc = " @brief LibClamAV hash stats callback.\n\n Callback that provides the hash of a scanned sample if a signature alerted.\n Provides a mechanism to record detection statistics.\n\n @param fd File descriptor if available, else -1.\n @param size Sample size\n @param md5 Sample md5 hash\n @param virname Signature name that the sample matched against\n @param context Opaque application provided data"] +pub type clcb_hash = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + size: ::std::os::raw::c_ulonglong, + md5: *const ::std::os::raw::c_uchar, + virname: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ), +>; +extern "C" { + #[doc = " @brief Set a custom hash stats callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_hash(engine: *mut cl_engine, callback: clcb_hash); +} +#[doc = " @brief Archive meta matching callback function.\n\n May be used to block archive/container samples based on archive metadata.\n Function is invoked multiple times per archive. Typically once per contained file.\n\n Note: Used by the --archive-verbose clamscan option. Overriding this will alter\n the output from --archive-verbose.\n\n @param container_type String name of type (CL_TYPE).\n @param fsize_container Sample size\n @param filename Filename associated with the data in archive.\n @param fsize_real Size of file after decompression (according to the archive).\n @param is_encrypted Boolean non-zero if the contained file is encrypted.\n @param filepos_container File index in container.\n @param context Opaque application provided data.\n @return CL_VIRUS to block (alert on)\n @return CL_CLEAN to continue scanning"] +pub type clcb_meta = ::std::option::Option< + unsafe extern "C" fn( + container_type: *const ::std::os::raw::c_char, + fsize_container: ::std::os::raw::c_ulong, + filename: *const ::std::os::raw::c_char, + fsize_real: ::std::os::raw::c_ulong, + is_encrypted: ::std::os::raw::c_int, + filepos_container: ::std::os::raw::c_uint, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +extern "C" { + #[doc = " @brief Set a custom archive metadata matching callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_meta(engine: *mut cl_engine, callback: clcb_meta); +} +#[doc = " @brief File properties callback function.\n\n Invoked after a scan the CL_SCAN_GENERAL_COLLECT_METADATA general scan option\n is enabled and libclamav was built with json support.\n\n @param j_propstr File properties/metadata in a JSON encoded string.\n @param rc The cl_error_t return code from the scan.\n @param cbdata Opaque application provided data."] +pub type clcb_file_props = ::std::option::Option< + unsafe extern "C" fn( + j_propstr: *const ::std::os::raw::c_char, + rc: ::std::os::raw::c_int, + cbdata: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, +>; +extern "C" { + #[doc = " @brief Set a custom file properties callback function.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_file_props(engine: *mut cl_engine, callback: clcb_file_props); +} +extern "C" { + #[doc = " @brief Set a pointer the caller-defined cbdata structure.\n\n The data must persist at least until `clcb_stats_submit()` is called, or\n `clcb_stats_flush()` is called (optional).\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] + pub fn cl_engine_set_stats_set_cbdata( + engine: *mut cl_engine, + cbdata: *mut ::std::os::raw::c_void, + ); +} +#[doc = " @brief Add sample metadata to the statistics for a sample that matched on a signature.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param sections PE section data, if applicable.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_add_sample = ::std::option::Option< + unsafe extern "C" fn( + virname: *const ::std::os::raw::c_char, + md5: *const ::std::os::raw::c_uchar, + size: usize, + sections: *mut stats_section_t, + cbdata: *mut ::std::os::raw::c_void, + ), +>; +extern "C" { + #[doc = " @brief Set a custom callback function to add sample metadata to a statistics report.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_add_sample( + engine: *mut cl_engine, + callback: clcb_stats_add_sample, + ); +} +#[doc = " @brief Remove a specific sample from the statistics report.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_remove_sample = ::std::option::Option< + unsafe extern "C" fn( + virname: *const ::std::os::raw::c_char, + md5: *const ::std::os::raw::c_uchar, + size: usize, + cbdata: *mut ::std::os::raw::c_void, + ), +>; +extern "C" { + #[doc = " @brief Set a custom callback function to remove sample metadata from a statistics report.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_remove_sample( + engine: *mut cl_engine, + callback: clcb_stats_remove_sample, + ); +} +#[doc = " @brief Decrement the hit count listed in the statistics report for a specific sample.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_decrement_count = ::std::option::Option< + unsafe extern "C" fn( + virname: *const ::std::os::raw::c_char, + md5: *const ::std::os::raw::c_uchar, + size: usize, + cbdata: *mut ::std::os::raw::c_void, + ), +>; +extern "C" { + #[doc = " @brief Set a custom callback function to decrement the hit count listed in the statistics report for a specific sample.\n\n This function may remove the sample from the report if the hit count is decremented to 0.\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_decrement_count( + engine: *mut cl_engine, + callback: clcb_stats_decrement_count, + ); +} +#[doc = " @brief Function to submit a statistics report.\n\n @param engine The initialized scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_submit = ::std::option::Option< + unsafe extern "C" fn(engine: *mut cl_engine, cbdata: *mut ::std::os::raw::c_void), +>; +extern "C" { + #[doc = " @brief Set a custom callback function to submit the statistics report.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_submit(engine: *mut cl_engine, callback: clcb_stats_submit); +} +#[doc = " @brief Function to flush/free the statistics report data.\n\n @param engine The initialized scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_flush = ::std::option::Option< + unsafe extern "C" fn(engine: *mut cl_engine, cbdata: *mut ::std::os::raw::c_void), +>; +extern "C" { + #[doc = " @brief Set a custom callback function to flush/free the statistics report data.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_flush(engine: *mut cl_engine, callback: clcb_stats_flush); +} +#[doc = " @brief Function to get the number of samples listed in the statistics report.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_get_num = + ::std::option::Option usize>; +extern "C" { + #[doc = " @brief Set a custom callback function to get the number of samples listed in the statistics report.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_get_num(engine: *mut cl_engine, callback: clcb_stats_get_num); +} +#[doc = " @brief Function to get the size of memory used to store the statistics report.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_get_size = + ::std::option::Option usize>; +extern "C" { + #[doc = " @brief Set a custom callback function to get the size of memory used to store the statistics report.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_get_size(engine: *mut cl_engine, callback: clcb_stats_get_size); +} +#[doc = " @brief Function to get the machine's unique host ID.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_get_hostid = ::std::option::Option< + unsafe extern "C" fn(cbdata: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_char, +>; +extern "C" { + #[doc = " @brief Set a custom callback function to get the machine's unique host ID.\n\n Caution: changing options for an engine that is in-use is not thread-safe!\n\n @param engine The initialized scanning engine.\n @param callback The callback function pointer."] + pub fn cl_engine_set_clcb_stats_get_hostid( + engine: *mut cl_engine, + callback: clcb_stats_get_hostid, + ); +} +extern "C" { + #[doc = " @brief Function enables the built-in statistics reporting feature.\n\n @param engine The initialized scanning engine."] + pub fn cl_engine_stats_enable(engine: *mut cl_engine); +} +extern "C" { + #[doc = " @brief Scan a file, given a file descriptor.\n\n @param desc File descriptor of an open file. The caller must provide this or the map.\n @param filename (optional) Filepath of the open file descriptor or file map.\n @param[out] virname Will be set to a statically allocated (i.e. needs not be freed) signature name if the scan matches against a signature.\n @param[out] scanned The number of bytes scanned.\n @param engine The scanning engine.\n @param scanoptions Scanning options.\n @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occurred during the scan."] + pub fn cl_scandesc( + desc: ::std::os::raw::c_int, + filename: *const ::std::os::raw::c_char, + virname: *mut *const ::std::os::raw::c_char, + scanned: *mut ::std::os::raw::c_ulong, + engine: *const cl_engine, + scanoptions: *mut cl_scan_options, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Scan a file, given a file descriptor.\n\n This callback variant allows the caller to provide a context structure that caller provided callback functions can interpret.\n\n @param desc File descriptor of an open file. The caller must provide this or the map.\n @param filename (optional) Filepath of the open file descriptor or file map.\n @param[out] virname Will be set to a statically allocated (i.e. needs not be freed) signature name if the scan matches against a signature.\n @param[out] scanned The number of bytes scanned.\n @param engine The scanning engine.\n @param scanoptions Scanning options.\n @param[in,out] context An opaque context structure allowing the caller to record details about the sample being scanned.\n @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occurred during the scan."] + pub fn cl_scandesc_callback( + desc: ::std::os::raw::c_int, + filename: *const ::std::os::raw::c_char, + virname: *mut *const ::std::os::raw::c_char, + scanned: *mut ::std::os::raw::c_ulong, + engine: *const cl_engine, + scanoptions: *mut cl_scan_options, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Scan a file, given a filename.\n\n @param filename Filepath of the file to be scanned.\n @param[out] virname Will be set to a statically allocated (i.e. needs not be freed) signature name if the scan matches against a signature.\n @param[out] scanned The number of bytes scanned.\n @param engine The scanning engine.\n @param scanoptions Scanning options.\n @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occurred during the scan."] + pub fn cl_scanfile( + filename: *const ::std::os::raw::c_char, + virname: *mut *const ::std::os::raw::c_char, + scanned: *mut ::std::os::raw::c_ulong, + engine: *const cl_engine, + scanoptions: *mut cl_scan_options, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Scan a file, given a filename.\n\n This callback variant allows the caller to provide a context structure that caller provided callback functions can interpret.\n\n @param filename Filepath of the file to be scanned.\n @param[out] virname Will be set to a statically allocated (i.e. needs not be freed) signature name if the scan matches against a signature.\n @param[out] scanned The number of bytes scanned.\n @param engine The scanning engine.\n @param scanoptions Scanning options.\n @param[in,out] context An opaque context structure allowing the caller to record details about the sample being scanned.\n @return cl_error_t CL_CLEAN, CL_VIRUS, or an error code if an error occurred during the scan."] + pub fn cl_scanfile_callback( + filename: *const ::std::os::raw::c_char, + virname: *mut *const ::std::os::raw::c_char, + scanned: *mut ::std::os::raw::c_ulong, + engine: *const cl_engine, + scanoptions: *mut cl_scan_options, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Load the signature databases found at the path.\n\n @param path May be a file or directory.\n @param engine The engine to load the signatures into\n @param[out] signo The number of signatures loaded\n @param dboptions Database load bitflag field. See the CL_DB_* defines, above.\n @return cl_error_t"] + pub fn cl_load( + path: *const ::std::os::raw::c_char, + engine: *mut cl_engine, + signo: *mut ::std::os::raw::c_uint, + dboptions: ::std::os::raw::c_uint, + ) -> cl_error_t; +} +extern "C" { + #[doc = " @brief Get the default database directory path.\n\n @return const char*"] + pub fn cl_retdbdir() -> *const ::std::os::raw::c_char; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_cvd { + pub time: *mut ::std::os::raw::c_char, + pub version: ::std::os::raw::c_uint, + pub sigs: ::std::os::raw::c_uint, + pub fl: ::std::os::raw::c_uint, + pub md5: *mut ::std::os::raw::c_char, + pub dsig: *mut ::std::os::raw::c_char, + pub builder: *mut ::std::os::raw::c_char, + pub stime: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_cl_cvd() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 56usize, + concat!("Size of: ", stringify!(cl_cvd)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(cl_cvd)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).time) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(time) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(version) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sigs) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(sigs) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).fl) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(fl) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).md5) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(md5) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).dsig) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(dsig) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).builder) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(builder) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).stime) as usize - ptr as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(cl_cvd), + "::", + stringify!(stime) + ) + ); +} +extern "C" { + #[doc = " @brief Parse the CVD header.\n\n Buffer length is not an argument, and the check must be done\n by the caller cl_cvdhead().\n\n The returned pointer must be free'd with cl_cvdfree().\n\n @param head Pointer to the header data buffer.\n @return struct cl_cvd* Pointer to an allocated CVD header data structure."] + pub fn cl_cvdparse(head: *const ::std::os::raw::c_char) -> *mut cl_cvd; +} +extern "C" { + #[doc = " @brief Free a CVD header struct.\n\n @param cvd Pointer to a CVD header struct."] + pub fn cl_cvdfree(cvd: *mut cl_cvd); +} +extern "C" { + #[doc = " @brief Get the Functionality Level (FLEVEL).\n\n @return unsigned int The FLEVEL."] + pub fn cl_retflevel() -> ::std::os::raw::c_uint; +} +extern "C" { + #[doc = " @brief Get the ClamAV version string.\n\n E.g. clamav-0.100.0-beta\n\n @return const char* The version string."] + pub fn cl_retver() -> *const ::std::os::raw::c_char; +} +extern "C" { + pub fn cl_strerror(clerror: cl_error_t) -> *const ::std::os::raw::c_char; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_fmap { + _unused: [u8; 0], +} +pub type cl_fmap_t = cl_fmap; +#[doc = " @brief Read callback function type.\n\n A callback function pointer type for reading data from a cl_fmap_t that uses\n reads data from a handle interface.\n\n Read 'count' bytes starting at 'offset' into the buffer 'buf'\n\n Thread safety: It is guaranteed that only one callback is executing for a\n specific handle at any time, but there might be multiple callbacks executing\n for different handle at the same time.\n\n @param handle The handle passed to cl_fmap_open_handle, its meaning is up\n to the callback's implementation\n @param buf A buffer to read data into, must be at least offset + count\n bytes in size.\n @param count The number of bytes to read.\n @param offset The offset into buf to read the data to. If successful,\n the number of bytes actually read is returned. Upon reading\n end-of-file, zero is returned. Otherwise, a -1 is returned\n and the global variable errno is set to indicate the error."] +pub type clcb_pread = ::std::option::Option< + unsafe extern "C" fn( + handle: *mut ::std::os::raw::c_void, + buf: *mut ::std::os::raw::c_void, + count: usize, + offset: off_t, + ) -> off_t, +>; +extern "C" { + #[doc = " @brief Open a map given a handle.\n\n Open a map for scanning custom data accessed by a handle and pread (lseek +\n read)-like interface. For example a file descriptor or a WIN32 HANDLE.\n By default fmap will use aging to discard old data, unless you tell it not\n to.\n\n The handle will be passed to the callback each time.\n\n @param handle A handle that may be accessed using lseek + read.\n @param offset Initial offset to start scanning.\n @param len Length of the data from the start (not the offset).\n @param pread_cb A callback function to read data from the handle.\n @param use_aging Set to a non-zero value to enable aging.\n @return cl_fmap_t* A map representing the handle interface."] + pub fn cl_fmap_open_handle( + handle: *mut ::std::os::raw::c_void, + offset: usize, + len: usize, + pread_cb: clcb_pread, + use_aging: ::std::os::raw::c_int, + ) -> *mut cl_fmap_t; +} +extern "C" { + #[doc = " @brief Open a map given a buffer.\n\n Open a map for scanning custom data, where the data is already in memory,\n either in the form of a buffer, a memory mapped file, etc.\n Note that the memory [start, start+len) must be the _entire_ file,\n you can't give it parts of a file and expect detection to work.\n\n @param start Pointer to a buffer of data.\n @param len Length in bytes of the data.\n @return cl_fmap_t* A map representing the buffer."] + pub fn cl_fmap_open_memory(start: *const ::std::os::raw::c_void, len: usize) -> *mut cl_fmap_t; +} +extern "C" { + #[doc = " @brief Releases resources associated with the map.\n\n You should release any resources you hold only after (handles, maps) calling\n this function.\n\n @param map Map to be closed."] + pub fn cl_fmap_close(arg1: *mut cl_fmap_t); +} +extern "C" { + #[doc = " @brief Scan custom data.\n\n @param map Buffer to be scanned, in form of a cl_fmap_t.\n @param filename Name of data origin. Does not need to be an actual\n file on disk. May be NULL if a name is not available.\n @param[out] virname Pointer to receive the signature match name name if a\n signature matched.\n @param[out] scanned Number of bytes scanned.\n @param engine The scanning engine.\n @param scanoptions The scanning options struct.\n @param context An application-defined context struct, opaque to\n libclamav. May be used within your callback functions.\n @return cl_error_t CL_CLEAN if no signature matched. CL_VIRUS if a\n signature matched. Another CL_E* error code if an\n error occurred."] + pub fn cl_scanmap_callback( + map: *mut cl_fmap_t, + filename: *const ::std::os::raw::c_char, + virname: *mut *const ::std::os::raw::c_char, + scanned: *mut ::std::os::raw::c_ulong, + engine: *const cl_engine, + scanoptions: *mut cl_scan_options, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t; +} diff --git a/clamav-sys/no-libclang/sys.rs b/clamav-sys/no-libclang/sys.rs new file mode 100644 index 0000000000..15a3600fd1 --- /dev/null +++ b/clamav-sys/no-libclang/sys.rs @@ -0,0 +1,1220 @@ +/* automatically generated by rust-bindgen 0.69.2 */ + +pub type __int32_t = ::std::os::raw::c_int; +pub type __int64_t = ::std::os::raw::c_longlong; +pub type __darwin_time_t = ::std::os::raw::c_long; +pub type __darwin_off_t = __int64_t; +pub type __darwin_suseconds_t = __int32_t; +pub type off_t = __darwin_off_t; +pub type time_t = __darwin_time_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct timeval { + pub tv_sec: __darwin_time_t, + pub tv_usec: __darwin_suseconds_t, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bignum_st { + _unused: [u8; 0], +} +pub type BIGNUM = bignum_st; +pub const cl_error_t_CL_CLEAN: cl_error_t = 0; +pub const cl_error_t_CL_SUCCESS: cl_error_t = 0; +pub const cl_error_t_CL_VIRUS: cl_error_t = 1; +pub const cl_error_t_CL_ENULLARG: cl_error_t = 2; +pub const cl_error_t_CL_EARG: cl_error_t = 3; +pub const cl_error_t_CL_EMALFDB: cl_error_t = 4; +pub const cl_error_t_CL_ECVD: cl_error_t = 5; +pub const cl_error_t_CL_EVERIFY: cl_error_t = 6; +pub const cl_error_t_CL_EUNPACK: cl_error_t = 7; +pub const cl_error_t_CL_EOPEN: cl_error_t = 8; +pub const cl_error_t_CL_ECREAT: cl_error_t = 9; +pub const cl_error_t_CL_EUNLINK: cl_error_t = 10; +pub const cl_error_t_CL_ESTAT: cl_error_t = 11; +pub const cl_error_t_CL_EREAD: cl_error_t = 12; +pub const cl_error_t_CL_ESEEK: cl_error_t = 13; +pub const cl_error_t_CL_EWRITE: cl_error_t = 14; +pub const cl_error_t_CL_EDUP: cl_error_t = 15; +pub const cl_error_t_CL_EACCES: cl_error_t = 16; +pub const cl_error_t_CL_ETMPFILE: cl_error_t = 17; +pub const cl_error_t_CL_ETMPDIR: cl_error_t = 18; +pub const cl_error_t_CL_EMAP: cl_error_t = 19; +pub const cl_error_t_CL_EMEM: cl_error_t = 20; +pub const cl_error_t_CL_ETIMEOUT: cl_error_t = 21; +pub const cl_error_t_CL_BREAK: cl_error_t = 22; +pub const cl_error_t_CL_EMAXREC: cl_error_t = 23; +pub const cl_error_t_CL_EMAXSIZE: cl_error_t = 24; +pub const cl_error_t_CL_EMAXFILES: cl_error_t = 25; +pub const cl_error_t_CL_EFORMAT: cl_error_t = 26; +pub const cl_error_t_CL_EPARSE: cl_error_t = 27; +pub const cl_error_t_CL_EBYTECODE: cl_error_t = 28; +pub const cl_error_t_CL_EBYTECODE_TESTFAIL: cl_error_t = 29; +pub const cl_error_t_CL_ELOCK: cl_error_t = 30; +pub const cl_error_t_CL_EBUSY: cl_error_t = 31; +pub const cl_error_t_CL_ESTATE: cl_error_t = 32; +pub const cl_error_t_CL_VERIFIED: cl_error_t = 33; +pub const cl_error_t_CL_ERROR: cl_error_t = 34; +pub const cl_error_t_CL_ELAST_ERROR: cl_error_t = 35; +pub type cl_error_t = ::std::os::raw::c_uint; +#[doc = " scan options"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_scan_options { + pub general: u32, + pub parse: u32, + pub heuristic: u32, + pub mail: u32, + pub dev: u32, +} +pub const bytecode_security_CL_BYTECODE_TRUST_ALL: bytecode_security = 0; +pub const bytecode_security_CL_BYTECODE_TRUST_SIGNED: bytecode_security = 1; +pub const bytecode_security_CL_BYTECODE_TRUST_NOTHING: bytecode_security = 2; +pub type bytecode_security = ::std::os::raw::c_uint; +pub const bytecode_mode_CL_BYTECODE_MODE_AUTO: bytecode_mode = 0; +pub const bytecode_mode_CL_BYTECODE_MODE_JIT: bytecode_mode = 1; +pub const bytecode_mode_CL_BYTECODE_MODE_INTERPRETER: bytecode_mode = 2; +pub const bytecode_mode_CL_BYTECODE_MODE_TEST: bytecode_mode = 3; +pub const bytecode_mode_CL_BYTECODE_MODE_OFF: bytecode_mode = 4; +pub type bytecode_mode = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_section_hash { + pub md5: [::std::os::raw::c_uchar; 16usize], + pub len: usize, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_stats_sections { + pub nsections: usize, + pub sections: *mut cli_section_hash, +} +pub type stats_section_t = cli_stats_sections; +#[doc = " @brief Pre-cache callback.\n\n Called for each processed file (both the entry level - AKA 'outer' - file and\n inner files - those generated when processing archive and container files), before\n the actual scanning takes place.\n\n @param fd File descriptor which is about to be scanned.\n @param type File type detected via magic - i.e. NOT on the fly - (e.g. \"CL_TYPE_MSEXE\").\n @param context Opaque application provided data.\n @return CL_CLEAN = File is scanned.\n @return CL_BREAK = Allowed by callback - file is skipped and marked as clean.\n @return CL_VIRUS = Blocked by callback - file is skipped and marked as infected."] +pub type clcb_pre_cache = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + type_: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +#[doc = " @brief File inspection callback.\n\n DISCLAIMER: This interface is to be considered unstable while we continue to evaluate it.\n We may change this interface in the future.\n\n Called for each NEW file (inner and outer).\n Provides capability to record embedded file information during a scan.\n\n @param fd Current file descriptor which is about to be scanned.\n @param type Current file type detected via magic - i.e. NOT on the fly - (e.g. \"CL_TYPE_MSEXE\").\n @param ancestors An array of ancestors filenames of size `recursion_level`. filenames may be NULL.\n @param parent_file_size Parent file size.\n @param file_name Current file name, or NULL if the file does not have a name or ClamAV failed to record the name.\n @param file_size Current file size.\n @param file_buffer Current file buffer pointer.\n @param recursion_level Recursion level / depth of the current file.\n @param layer_attributes See LAYER_ATTRIBUTES_* flags.\n @param context Opaque application provided data.\n @return CL_CLEAN = File is scanned.\n @return CL_BREAK = Whitelisted by callback - file is skipped and marked as clean.\n @return CL_VIRUS = Blacklisted by callback - file is skipped and marked as infected."] +pub type clcb_file_inspection = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + type_: *const ::std::os::raw::c_char, + ancestors: *mut *const ::std::os::raw::c_char, + parent_file_size: usize, + file_name: *const ::std::os::raw::c_char, + file_size: usize, + file_buffer: *const ::std::os::raw::c_char, + recursion_level: u32, + layer_attributes: u32, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +#[doc = " @brief Pre-scan callback.\n\n Called for each NEW file (inner and outer) before the scanning takes place. This is\n roughly the same as clcb_before_cache, but it is affected by clean file caching.\n This means that it won't be called if a clean cached file (inner or outer) is\n scanned a second time.\n\n @param fd File descriptor which is about to be scanned.\n @param type File type detected via magic - i.e. NOT on the fly - (e.g. \"CL_TYPE_MSEXE\").\n @param context Opaque application provided data.\n @return CL_CLEAN = File is scanned.\n @return CL_BREAK = Allowed by callback - file is skipped and marked as clean.\n @return CL_VIRUS = Blocked by callback - file is skipped and marked as infected."] +pub type clcb_pre_scan = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + type_: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +#[doc = " @brief Post-scan callback.\n\n Called for each processed file (inner and outer), after the scanning is complete.\n In all-match mode, the virname will be one of the matches, but there is no\n guarantee in which order the matches will occur, thus the final virname may\n be any one of the matches.\n\n @param fd File descriptor which was scanned.\n @param result The scan result for the file.\n @param virname A signature name if there was one or more matches.\n @param context Opaque application provided data.\n @return Scan result is not overridden.\n @return CL_BREAK = Allowed by callback - scan result is set to CL_CLEAN.\n @return Blocked by callback - scan result is set to CL_VIRUS."] +pub type clcb_post_scan = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + result: ::std::os::raw::c_int, + virname: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +#[doc = " @brief Virus-found callback.\n\n Called for each signature match.\n If all-match is enabled, clcb_virus_found() may be called multiple times per\n scan.\n\n In addition, clcb_virus_found() does not have a return value and thus.\n can not be used to ignore the match.\n\n @param fd File descriptor which was scanned.\n @param virname Virus name.\n @param context Opaque application provided data."] +pub type clcb_virus_found = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + virname: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " @brief Signature-load callback.\n\n May be used to ignore signatures at database load time.\n\n WARNING: Some signatures (notably ldb, cbc) can be dependent upon other signatures.\n Failure to preserve dependency chains will result in database loading failure.\n It is the implementor's responsibility to guarantee consistency.\n\n @param type The signature type (e.g. \"db\", \"ndb\", \"mdb\", etc.)\n @param name Signature name.\n @param custom The signature is official (custom == 0) or custom (custom != 0)\n @param context Opaque application provided data\n @return 0 to load the current signature.\n @return Non-0 to skip the current signature."] +pub type clcb_sigload = ::std::option::Option< + unsafe extern "C" fn( + type_: *const ::std::os::raw::c_char, + name: *const ::std::os::raw::c_char, + custom: ::std::os::raw::c_uint, + context: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, +>; +#[doc = " @brief Progress callback for sig-load, engine-compile, and engine-free.\n\n Progress is complete when total_items == now_completed.\n\n Note: The callback should return CL_SUCCESS. We reserve the right to have it\n cancel the operation in the future if you return something else...\n ... but for now, the return value will be ignored.\n\n @param total_items Total number of items\n @param now_completed Number of items completed\n @param context Opaque application provided data\n @return cl_error_t reserved for future use"] +pub type clcb_progress = ::std::option::Option< + unsafe extern "C" fn( + total_items: usize, + now_completed: usize, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +#[doc = " @brief LibClamAV hash stats callback.\n\n Callback that provides the hash of a scanned sample if a signature alerted.\n Provides a mechanism to record detection statistics.\n\n @param fd File descriptor if available, else -1.\n @param size Sample size\n @param md5 Sample md5 hash\n @param virname Signature name that the sample matched against\n @param context Opaque application provided data"] +pub type clcb_hash = ::std::option::Option< + unsafe extern "C" fn( + fd: ::std::os::raw::c_int, + size: ::std::os::raw::c_ulonglong, + md5: *const ::std::os::raw::c_uchar, + virname: *const ::std::os::raw::c_char, + context: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " @brief Archive meta matching callback function.\n\n May be used to block archive/container samples based on archive metadata.\n Function is invoked multiple times per archive. Typically once per contained file.\n\n Note: Used by the --archive-verbose clamscan option. Overriding this will alter\n the output from --archive-verbose.\n\n @param container_type String name of type (CL_TYPE).\n @param fsize_container Sample size\n @param filename Filename associated with the data in archive.\n @param fsize_real Size of file after decompression (according to the archive).\n @param is_encrypted Boolean non-zero if the contained file is encrypted.\n @param filepos_container File index in container.\n @param context Opaque application provided data.\n @return CL_VIRUS to block (alert on)\n @return CL_CLEAN to continue scanning"] +pub type clcb_meta = ::std::option::Option< + unsafe extern "C" fn( + container_type: *const ::std::os::raw::c_char, + fsize_container: ::std::os::raw::c_ulong, + filename: *const ::std::os::raw::c_char, + fsize_real: ::std::os::raw::c_ulong, + is_encrypted: ::std::os::raw::c_int, + filepos_container: ::std::os::raw::c_uint, + context: *mut ::std::os::raw::c_void, + ) -> cl_error_t, +>; +#[doc = " @brief File properties callback function.\n\n Invoked after a scan the CL_SCAN_GENERAL_COLLECT_METADATA general scan option\n is enabled and libclamav was built with json support.\n\n @param j_propstr File properties/metadata in a JSON encoded string.\n @param rc The cl_error_t return code from the scan.\n @param cbdata Opaque application provided data."] +pub type clcb_file_props = ::std::option::Option< + unsafe extern "C" fn( + j_propstr: *const ::std::os::raw::c_char, + rc: ::std::os::raw::c_int, + cbdata: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, +>; +#[doc = " @brief generic data callback function.\n\n Callback handler prototype for callbacks passing back data and application context.\n\n @param data A pointer to some data. Should be treated as read-only and may be freed after callback.\n @param data_len The length of data.\n @param cbdata Opaque application provided data."] +pub type clcb_generic_data = ::std::option::Option< + unsafe extern "C" fn( + data: *const ::std::os::raw::c_uchar, + data_len: usize, + cbdata: *mut ::std::os::raw::c_void, + ) -> ::std::os::raw::c_int, +>; +#[doc = " @brief Add sample metadata to the statistics for a sample that matched on a signature.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param sections PE section data, if applicable.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_add_sample = ::std::option::Option< + unsafe extern "C" fn( + virname: *const ::std::os::raw::c_char, + md5: *const ::std::os::raw::c_uchar, + size: usize, + sections: *mut stats_section_t, + cbdata: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " @brief Remove a specific sample from the statistics report.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_remove_sample = ::std::option::Option< + unsafe extern "C" fn( + virname: *const ::std::os::raw::c_char, + md5: *const ::std::os::raw::c_uchar, + size: usize, + cbdata: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " @brief Decrement the hit count listed in the statistics report for a specific sample.\n\n @param virname Name of the signature that matched.\n @param md5 Sample hash.\n @param size Sample size.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_decrement_count = ::std::option::Option< + unsafe extern "C" fn( + virname: *const ::std::os::raw::c_char, + md5: *const ::std::os::raw::c_uchar, + size: usize, + cbdata: *mut ::std::os::raw::c_void, + ), +>; +#[doc = " @brief Function to submit a statistics report.\n\n @param engine The initialized scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_submit = ::std::option::Option< + unsafe extern "C" fn(engine: *mut cl_engine, cbdata: *mut ::std::os::raw::c_void), +>; +#[doc = " @brief Function to flush/free the statistics report data.\n\n @param engine The initialized scanning engine.\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_flush = ::std::option::Option< + unsafe extern "C" fn(engine: *mut cl_engine, cbdata: *mut ::std::os::raw::c_void), +>; +#[doc = " @brief Function to get the number of samples listed in the statistics report.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_get_num = + ::std::option::Option usize>; +#[doc = " @brief Function to get the size of memory used to store the statistics report.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_get_size = + ::std::option::Option usize>; +#[doc = " @brief Function to get the machine's unique host ID.\n\n @param cbdata The statistics data. Probably a pointer to a malloc'd struct."] +pub type clcb_stats_get_hostid = ::std::option::Option< + unsafe extern "C" fn(cbdata: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_char, +>; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_cvd { + pub time: *mut ::std::os::raw::c_char, + pub version: ::std::os::raw::c_uint, + pub sigs: ::std::os::raw::c_uint, + pub fl: ::std::os::raw::c_uint, + pub md5: *mut ::std::os::raw::c_char, + pub dsig: *mut ::std::os::raw::c_char, + pub builder: *mut ::std::os::raw::c_char, + pub stime: ::std::os::raw::c_uint, +} +pub type cl_fmap_t = cl_fmap; +#[doc = " @brief Read callback function type.\n\n A callback function pointer type for reading data from a cl_fmap_t that uses\n reads data from a handle interface.\n\n Read 'count' bytes starting at 'offset' into the buffer 'buf'\n\n Thread safety: It is guaranteed that only one callback is executing for a\n specific handle at any time, but there might be multiple callbacks executing\n for different handle at the same time.\n\n @param handle The handle passed to cl_fmap_open_handle, its meaning is up\n to the callback's implementation\n @param buf A buffer to read data into, must be at least offset + count\n bytes in size.\n @param count The number of bytes to read.\n @param offset The offset into buf to read the data to. If successful,\n the number of bytes actually read is returned. Upon reading\n end-of-file, zero is returned. Otherwise, a -1 is returned\n and the global variable errno is set to indicate the error."] +pub type clcb_pread = ::std::option::Option< + unsafe extern "C" fn( + handle: *mut ::std::os::raw::c_void, + buf: *mut ::std::os::raw::c_void, + count: usize, + offset: off_t, + ) -> off_t, +>; +pub type fmap_t = cl_fmap_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_fmap { + pub handle: *mut ::std::os::raw::c_void, + pub pread_cb: clcb_pread, + pub data: *const ::std::os::raw::c_void, + pub mtime: u64, + pub pages: u64, + pub pgsz: u64, + pub paged: u64, + pub aging: bool, + #[doc = " indicates if we should age off memory mapped pages"] + pub dont_cache_flag: bool, + #[doc = " indicates if we should not cache scan results for this fmap. Used if limits exceeded"] + pub handle_is_fd: bool, + #[doc = " non-zero if map->handle is an fd."] + pub offset: usize, + #[doc = " file offset representing start of original fmap, if the fmap created reading from a file starting at offset other than 0"] + pub nested_offset: usize, + #[doc = " offset from start of original fmap (data) for nested scan. 0 for orig fmap."] + pub real_len: usize, + #[doc = " len from start of original fmap (data) to end of current (possibly nested) map."] + pub len: usize, + #[doc = " length of data from nested_offset, accessible via current fmap"] + pub unmap: ::std::option::Option, + pub need: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut fmap_t, + at: usize, + len: usize, + lock: ::std::os::raw::c_int, + ) -> *const ::std::os::raw::c_void, + >, + pub need_offstr: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut fmap_t, + at: usize, + len_hint: usize, + ) -> *const ::std::os::raw::c_void, + >, + pub gets: ::std::option::Option< + unsafe extern "C" fn( + arg1: *mut fmap_t, + dst: *mut ::std::os::raw::c_char, + at: *mut usize, + max_len: usize, + ) -> *const ::std::os::raw::c_void, + >, + pub unneed_off: + ::std::option::Option, + pub windows_file_handle: *mut ::std::os::raw::c_void, + pub windows_map_handle: *mut ::std::os::raw::c_void, + pub have_md5: bool, + pub md5: [::std::os::raw::c_uchar; 16usize], + pub have_sha1: bool, + pub sha1: [::std::os::raw::c_uchar; 20usize], + pub have_sha256: bool, + pub sha256: [::std::os::raw::c_uchar; 32usize], + pub bitmap: *mut u64, + pub name: *mut ::std::os::raw::c_char, +} +pub const cli_file_CL_TYPE_ANY: cli_file = 0; +pub const cli_file_CL_TYPE_TEXT_ASCII: cli_file = 500; +pub const cli_file_CL_TYPE_TEXT_UTF8: cli_file = 501; +pub const cli_file_CL_TYPE_TEXT_UTF16LE: cli_file = 502; +pub const cli_file_CL_TYPE_TEXT_UTF16BE: cli_file = 503; +pub const cli_file_CL_TYPE_BINARY_DATA: cli_file = 504; +pub const cli_file_CL_TYPE_ERROR: cli_file = 505; +pub const cli_file_CL_TYPE_MSEXE: cli_file = 506; +pub const cli_file_CL_TYPE_ELF: cli_file = 507; +pub const cli_file_CL_TYPE_MACHO: cli_file = 508; +pub const cli_file_CL_TYPE_MACHO_UNIBIN: cli_file = 509; +pub const cli_file_CL_TYPE_POSIX_TAR: cli_file = 510; +pub const cli_file_CL_TYPE_OLD_TAR: cli_file = 511; +pub const cli_file_CL_TYPE_CPIO_OLD: cli_file = 512; +pub const cli_file_CL_TYPE_CPIO_ODC: cli_file = 513; +pub const cli_file_CL_TYPE_CPIO_NEWC: cli_file = 514; +pub const cli_file_CL_TYPE_CPIO_CRC: cli_file = 515; +pub const cli_file_CL_TYPE_GZ: cli_file = 516; +pub const cli_file_CL_TYPE_ZIP: cli_file = 517; +pub const cli_file_CL_TYPE_BZ: cli_file = 518; +pub const cli_file_CL_TYPE_RAR: cli_file = 519; +pub const cli_file_CL_TYPE_ARJ: cli_file = 520; +pub const cli_file_CL_TYPE_MSSZDD: cli_file = 521; +pub const cli_file_CL_TYPE_MSOLE2: cli_file = 522; +pub const cli_file_CL_TYPE_MSCAB: cli_file = 523; +pub const cli_file_CL_TYPE_MSCHM: cli_file = 524; +pub const cli_file_CL_TYPE_SIS: cli_file = 525; +pub const cli_file_CL_TYPE_SCRENC: cli_file = 526; +pub const cli_file_CL_TYPE_GRAPHICS: cli_file = 527; +pub const cli_file_CL_TYPE_GIF: cli_file = 528; +pub const cli_file_CL_TYPE_PNG: cli_file = 529; +pub const cli_file_CL_TYPE_JPEG: cli_file = 530; +pub const cli_file_CL_TYPE_TIFF: cli_file = 531; +pub const cli_file_CL_TYPE_RIFF: cli_file = 532; +pub const cli_file_CL_TYPE_BINHEX: cli_file = 533; +pub const cli_file_CL_TYPE_TNEF: cli_file = 534; +pub const cli_file_CL_TYPE_CRYPTFF: cli_file = 535; +pub const cli_file_CL_TYPE_PDF: cli_file = 536; +pub const cli_file_CL_TYPE_UUENCODED: cli_file = 537; +pub const cli_file_CL_TYPE_SCRIPT: cli_file = 538; +pub const cli_file_CL_TYPE_HTML_UTF16: cli_file = 539; +pub const cli_file_CL_TYPE_RTF: cli_file = 540; +pub const cli_file_CL_TYPE_7Z: cli_file = 541; +pub const cli_file_CL_TYPE_SWF: cli_file = 542; +pub const cli_file_CL_TYPE_JAVA: cli_file = 543; +pub const cli_file_CL_TYPE_XAR: cli_file = 544; +pub const cli_file_CL_TYPE_XZ: cli_file = 545; +pub const cli_file_CL_TYPE_OOXML_WORD: cli_file = 546; +pub const cli_file_CL_TYPE_OOXML_PPT: cli_file = 547; +pub const cli_file_CL_TYPE_OOXML_XL: cli_file = 548; +pub const cli_file_CL_TYPE_INTERNAL: cli_file = 549; +pub const cli_file_CL_TYPE_HWP3: cli_file = 550; +pub const cli_file_CL_TYPE_OOXML_HWP: cli_file = 551; +pub const cli_file_CL_TYPE_PS: cli_file = 552; +pub const cli_file_CL_TYPE_EGG: cli_file = 553; +pub const cli_file_CL_TYPE_ONENOTE: cli_file = 554; +pub const cli_file_CL_TYPE_PYTHON_COMPILED: cli_file = 555; +pub const cli_file_CL_TYPE_PART_ANY: cli_file = 556; +pub const cli_file_CL_TYPE_PART_HFSPLUS: cli_file = 557; +pub const cli_file_CL_TYPE_MBR: cli_file = 558; +pub const cli_file_CL_TYPE_HTML: cli_file = 559; +pub const cli_file_CL_TYPE_MAIL: cli_file = 560; +pub const cli_file_CL_TYPE_SFX: cli_file = 561; +pub const cli_file_CL_TYPE_ZIPSFX: cli_file = 562; +pub const cli_file_CL_TYPE_RARSFX: cli_file = 563; +pub const cli_file_CL_TYPE_7ZSFX: cli_file = 564; +pub const cli_file_CL_TYPE_CABSFX: cli_file = 565; +pub const cli_file_CL_TYPE_ARJSFX: cli_file = 566; +pub const cli_file_CL_TYPE_EGGSFX: cli_file = 567; +pub const cli_file_CL_TYPE_NULSFT: cli_file = 568; +pub const cli_file_CL_TYPE_AUTOIT: cli_file = 569; +pub const cli_file_CL_TYPE_ISHIELD_MSI: cli_file = 570; +pub const cli_file_CL_TYPE_ISO9660: cli_file = 571; +pub const cli_file_CL_TYPE_DMG: cli_file = 572; +pub const cli_file_CL_TYPE_GPT: cli_file = 573; +pub const cli_file_CL_TYPE_APM: cli_file = 574; +pub const cli_file_CL_TYPE_XDP: cli_file = 575; +pub const cli_file_CL_TYPE_XML_WORD: cli_file = 576; +pub const cli_file_CL_TYPE_XML_XL: cli_file = 577; +pub const cli_file_CL_TYPE_XML_HWP: cli_file = 578; +pub const cli_file_CL_TYPE_HWPOLE2: cli_file = 579; +pub const cli_file_CL_TYPE_MHTML: cli_file = 580; +pub const cli_file_CL_TYPE_LNK: cli_file = 581; +pub const cli_file_CL_TYPE_UDF: cli_file = 582; +pub const cli_file_CL_TYPE_OTHER: cli_file = 583; +pub const cli_file_CL_TYPE_IGNORED: cli_file = 584; +pub type cli_file = ::std::os::raw::c_uint; +pub use self::cli_file as cli_file_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_ftype { + pub type_: cli_file_t, + pub offset: u32, + pub magic: *mut ::std::os::raw::c_uchar, + pub tname: *mut ::std::os::raw::c_char, + pub next: *mut cli_ftype, + pub length: u16, +} +pub type mpool_t = ::std::os::raw::c_void; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_dconf { + pub pe: u32, + pub elf: u32, + pub macho: u32, + pub archive: u32, + pub doc: u32, + pub mail: u32, + pub other: u32, + pub phishing: u32, + pub bytecode: u32, + pub stats: u32, + pub pcre: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct regex_t { + pub re_magic: ::std::os::raw::c_int, + pub re_nsub: usize, + pub re_endp: *const ::std::os::raw::c_char, + pub re_g: *mut re_guts, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bytecode_metadata { + pub compiler: *mut ::std::os::raw::c_char, + pub sigmaker: *mut ::std::os::raw::c_char, + pub timestamp: u64, + pub formatlevel: ::std::os::raw::c_uint, + pub minfunc: ::std::os::raw::c_uint, + pub maxfunc: ::std::os::raw::c_uint, + pub maxresource: ::std::os::raw::c_uint, + pub targetExclude: ::std::os::raw::c_uint, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_environment { + pub platform_id_a: u32, + pub platform_id_b: u32, + pub platform_id_c: u32, + pub c_version: u32, + pub cpp_version: u32, + pub functionality_level: u32, + pub dconf_level: u32, + pub engine_version: [i8; 65usize], + pub triple: [i8; 65usize], + pub cpu: [i8; 65usize], + pub sysname: [i8; 65usize], + pub release: [i8; 65usize], + pub version: [i8; 65usize], + pub machine: [i8; 65usize], + pub big_endian: u8, + pub sizeof_ptr: u8, + pub arch: u8, + pub os_category: u8, + pub os: u8, + pub compiler: u8, + pub has_jit_compiled: u8, + pub os_features: u8, + pub reserved0: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bc_func { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bc_type { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bc_dbgnode { + _unused: [u8; 0], +} +pub const bc_state_bc_skip: bc_state = 0; +pub const bc_state_bc_loaded: bc_state = 1; +pub const bc_state_bc_jit: bc_state = 2; +pub const bc_state_bc_interp: bc_state = 3; +pub const bc_state_bc_disabled: bc_state = 4; +pub type bc_state = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bc { + pub metadata: bytecode_metadata, + pub id: ::std::os::raw::c_uint, + pub kind: ::std::os::raw::c_uint, + pub num_types: ::std::os::raw::c_uint, + pub num_func: ::std::os::raw::c_uint, + pub funcs: *mut cli_bc_func, + pub types: *mut cli_bc_type, + pub globals: *mut *mut u64, + pub globaltys: *mut u16, + pub num_globals: usize, + pub state: bc_state, + pub uses_apis: *mut bitset_tag, + pub lsig: *mut ::std::os::raw::c_char, + pub vnameprefix: *mut ::std::os::raw::c_char, + pub vnames: *mut *mut ::std::os::raw::c_char, + pub vnames_cnt: ::std::os::raw::c_uint, + pub start_tid: u16, + pub dbgnodes: *mut cli_bc_dbgnode, + pub dbgnode_cnt: ::std::os::raw::c_uint, + pub hook_lsig_id: ::std::os::raw::c_uint, + pub trusted: ::std::os::raw::c_uint, + pub numGlobalBytes: u32, + pub globalBytes: *mut u8, + pub sigtime_id: u32, + pub sigmatch_id: u32, + pub hook_name: *mut ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_all_bc { + pub all_bcs: *mut cli_bc, + pub count: ::std::os::raw::c_uint, + pub engine: *mut cli_bcengine, + pub env: cli_environment, + pub inited: ::std::os::raw::c_int, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_events { + _unused: [u8; 0], +} +pub type cli_events_t = cli_events; +pub const cli_crt_hashtype_CLI_HASHTYPE_ANY: cli_crt_hashtype = 0; +pub const cli_crt_hashtype_CLI_SHA1RSA: cli_crt_hashtype = 1; +pub const cli_crt_hashtype_CLI_MD5RSA: cli_crt_hashtype = 2; +pub const cli_crt_hashtype_CLI_MD2RSA: cli_crt_hashtype = 3; +pub const cli_crt_hashtype_CLI_RSA: cli_crt_hashtype = 4; +pub const cli_crt_hashtype_CLI_SHA256RSA: cli_crt_hashtype = 5; +pub const cli_crt_hashtype_CLI_SHA384RSA: cli_crt_hashtype = 6; +pub const cli_crt_hashtype_CLI_SHA512RSA: cli_crt_hashtype = 7; +pub type cli_crt_hashtype = ::std::os::raw::c_uint; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_crt_t { + pub name: *mut ::std::os::raw::c_char, + pub raw_subject: [u8; 64usize], + pub raw_issuer: [u8; 64usize], + pub raw_serial: [u8; 64usize], + pub subject: [u8; 20usize], + pub issuer: [u8; 20usize], + pub serial: [u8; 20usize], + pub ignore_serial: ::std::os::raw::c_int, + pub tbshash: [u8; 64usize], + pub n: *mut BIGNUM, + pub e: *mut BIGNUM, + pub sig: *mut BIGNUM, + pub not_before: time_t, + pub not_after: time_t, + pub hashtype: cli_crt_hashtype, + pub certSign: ::std::os::raw::c_int, + pub codeSign: ::std::os::raw::c_int, + pub timeSign: ::std::os::raw::c_int, + pub isBlocked: ::std::os::raw::c_int, + pub prev: *mut cli_crt_t, + pub next: *mut cli_crt_t, +} +pub type cli_crt = cli_crt_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct crtmgr { + pub crts: *mut cli_crt, + pub items: ::std::os::raw::c_uint, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bitset_tag { + pub bitset: *mut ::std::os::raw::c_uchar, + pub length: ::std::os::raw::c_ulong, +} +pub type bitset_t = bitset_tag; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct image_fuzzy_hash { + pub hash: [u8; 8usize], +} +pub type image_fuzzy_hash_t = image_fuzzy_hash; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct recursion_level_tag { + pub type_: cli_file_t, + pub size: usize, + pub fmap: *mut cl_fmap_t, + pub recursion_level_buffer: u32, + pub recursion_level_buffer_fmap: u32, + pub attributes: u32, + pub image_fuzzy_hash: image_fuzzy_hash_t, + pub calculated_image_fuzzy_hash: bool, +} +pub type recursion_level_t = recursion_level_tag; +pub type evidence_t = *mut ::std::os::raw::c_void; +pub type onedump_t = *mut ::std::os::raw::c_void; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_ctx_tag { + pub target_filepath: *mut ::std::os::raw::c_char, + pub sub_filepath: *const ::std::os::raw::c_char, + pub sub_tmpdir: *mut ::std::os::raw::c_char, + pub evidence: evidence_t, + pub scanned: *mut ::std::os::raw::c_ulong, + pub root: *const cli_matcher, + pub engine: *const cl_engine, + pub scansize: u64, + pub options: *mut cl_scan_options, + pub scannedfiles: ::std::os::raw::c_uint, + pub corrupted_input: ::std::os::raw::c_uint, + pub recursion_stack: *mut recursion_level_t, + pub recursion_stack_size: u32, + pub recursion_level: u32, + pub fmap: *mut fmap_t, + pub handlertype_hash: [::std::os::raw::c_uchar; 16usize], + pub dconf: *mut cli_dconf, + pub hook_lsig_matches: *mut bitset_t, + pub cb_ctx: *mut ::std::os::raw::c_void, + pub perf: *mut cli_events_t, + pub time_limit: timeval, + pub limit_exceeded: bool, + pub abort_scan: bool, +} +pub type cli_ctx = cli_ctx_tag; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct icomtr { + pub group: [::std::os::raw::c_uint; 2usize], + pub color_avg: [::std::os::raw::c_uint; 3usize], + pub color_x: [::std::os::raw::c_uint; 3usize], + pub color_y: [::std::os::raw::c_uint; 3usize], + pub gray_avg: [::std::os::raw::c_uint; 3usize], + pub gray_x: [::std::os::raw::c_uint; 3usize], + pub gray_y: [::std::os::raw::c_uint; 3usize], + pub bright_avg: [::std::os::raw::c_uint; 3usize], + pub bright_x: [::std::os::raw::c_uint; 3usize], + pub bright_y: [::std::os::raw::c_uint; 3usize], + pub dark_avg: [::std::os::raw::c_uint; 3usize], + pub dark_x: [::std::os::raw::c_uint; 3usize], + pub dark_y: [::std::os::raw::c_uint; 3usize], + pub edge_avg: [::std::os::raw::c_uint; 3usize], + pub edge_x: [::std::os::raw::c_uint; 3usize], + pub edge_y: [::std::os::raw::c_uint; 3usize], + pub noedge_avg: [::std::os::raw::c_uint; 3usize], + pub noedge_x: [::std::os::raw::c_uint; 3usize], + pub noedge_y: [::std::os::raw::c_uint; 3usize], + pub rsum: ::std::os::raw::c_uint, + pub gsum: ::std::os::raw::c_uint, + pub bsum: ::std::os::raw::c_uint, + pub ccount: ::std::os::raw::c_uint, + pub name: *mut ::std::os::raw::c_char, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct icon_matcher { + pub group_names: [*mut *mut ::std::os::raw::c_char; 2usize], + pub group_counts: [::std::os::raw::c_uint; 2usize], + pub icons: [*mut icomtr; 3usize], + pub icon_counts: [::std::os::raw::c_uint; 3usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_dbinfo { + pub name: *mut ::std::os::raw::c_char, + pub hash: *mut ::std::os::raw::c_char, + pub size: usize, + pub cvd: *mut cl_cvd, + pub next: *mut cli_dbinfo, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_pwdb { + pub name: *mut ::std::os::raw::c_char, + pub passwd: *mut ::std::os::raw::c_char, + pub length: u16, + pub next: *mut cli_pwdb, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cl_engine { + pub refcount: u32, + pub sdb: u32, + pub dboptions: u32, + pub dbversion: [u32; 2usize], + pub ac_only: u32, + pub ac_mindepth: u32, + pub ac_maxdepth: u32, + pub tmpdir: *mut ::std::os::raw::c_char, + pub keeptmp: u32, + pub engine_options: u64, + pub cache_size: u32, + pub maxscantime: u32, + pub maxscansize: u64, + pub maxfilesize: u64, + pub max_recursion_level: u32, + pub maxfiles: u32, + pub min_cc_count: u32, + pub min_ssn_count: u32, + pub root: *mut *mut cli_matcher, + pub hm_hdb: *mut cli_matcher, + pub hm_mdb: *mut cli_matcher, + pub hm_imp: *mut cli_matcher, + pub hm_fp: *mut cli_matcher, + pub cdb: *mut cli_cdb, + pub allow_list_matcher: *mut regex_matcher, + pub domain_list_matcher: *mut regex_matcher, + pub phishcheck: *mut phishcheck, + pub dconf: *mut cli_dconf, + pub ftypes: *mut cli_ftype, + pub ptypes: *mut cli_ftype, + pub pwdbs: *mut *mut cli_pwdb, + pub test_root: *mut cli_matcher, + pub ignored: *mut cli_matcher, + pub pua_cats: *mut ::std::os::raw::c_char, + pub iconcheck: *mut icon_matcher, + pub cache: *mut CACHE, + pub dbinfo: *mut cli_dbinfo, + pub num_total_signatures: usize, + pub mempool: *mut mpool_t, + pub cmgr: crtmgr, + pub cb_file_inspection: clcb_file_inspection, + pub cb_pre_cache: clcb_pre_cache, + pub cb_pre_scan: clcb_pre_scan, + pub cb_post_scan: clcb_post_scan, + pub cb_virus_found: clcb_virus_found, + pub cb_sigload: clcb_sigload, + pub cb_sigload_ctx: *mut ::std::os::raw::c_void, + pub cb_hash: clcb_hash, + pub cb_meta: clcb_meta, + pub cb_vba: clcb_generic_data, + pub cb_file_props: clcb_file_props, + pub cb_sigload_progress: clcb_progress, + pub cb_sigload_progress_ctx: *mut ::std::os::raw::c_void, + pub cb_engine_compile_progress: clcb_progress, + pub cb_engine_compile_progress_ctx: *mut ::std::os::raw::c_void, + pub cb_engine_free_progress: clcb_progress, + pub cb_engine_free_progress_ctx: *mut ::std::os::raw::c_void, + pub bcs: cli_all_bc, + pub hooks: [*mut ::std::os::raw::c_uint; 7usize], + pub hooks_cnt: [::std::os::raw::c_uint; 7usize], + pub hook_lsig_ids: ::std::os::raw::c_uint, + pub bytecode_security: bytecode_security, + pub bytecode_timeout: u32, + pub bytecode_mode: bytecode_mode, + pub maxembeddedpe: u64, + pub maxhtmlnormalize: u64, + pub maxhtmlnotags: u64, + pub maxscriptnormalize: u64, + pub maxziptypercg: u64, + pub stats_data: *mut ::std::os::raw::c_void, + pub cb_stats_add_sample: clcb_stats_add_sample, + pub cb_stats_remove_sample: clcb_stats_remove_sample, + pub cb_stats_decrement_count: clcb_stats_decrement_count, + pub cb_stats_submit: clcb_stats_submit, + pub cb_stats_flush: clcb_stats_flush, + pub cb_stats_get_num: clcb_stats_get_num, + pub cb_stats_get_size: clcb_stats_get_size, + pub cb_stats_get_hostid: clcb_stats_get_hostid, + pub maxpartitions: u32, + pub maxiconspe: u32, + pub maxrechwp3: u32, + pub pcre_match_limit: u64, + pub pcre_recmatch_limit: u64, + pub pcre_max_filesize: u64, +} +extern "C" { + #[doc = " @brief Append an alert.\n\n An FP-check will verify that the file is not allowed.\n The allow list check does not happen before the scan because allowing files\n is so infrequent that such action would be detrimental to performance.\n\n TODO: Replace implementation with severity scale, and severity threshold\n wherein signatures that do not meet the threshold are documented in JSON\n metadata but do not halt the scan.\n\n @param ctx The scan context.\n @param virname The alert name.\n @return cl_error_t CL_VIRUS if scan should be halted due to an alert, CL_CLEAN if scan should continue."] + pub fn cli_append_virus( + ctx: *mut cli_ctx, + virname: *const ::std::os::raw::c_char, + ) -> cl_error_t; +} +extern "C" { + pub fn cli_warnmsg(str_: *const ::std::os::raw::c_char, ...); +} +extern "C" { + pub fn cli_errmsg(str_: *const ::std::os::raw::c_char, ...); +} +extern "C" { + pub fn cli_infomsg_simple(fmt: *const ::std::os::raw::c_char, ...); +} +extern "C" { + pub fn cli_dbgmsg_no_inline(str_: *const ::std::os::raw::c_char, ...); +} +extern "C" { + #[doc = " @brief Get the libclamav debug flag (e.g. if debug logging is enabled)\n\n This is required for unit tests to be able to link with clamav.dll and not\n directly manipulate libclamav global variables."] + pub fn cli_get_debug_flag() -> u8; +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cli_htu32_element { + pub key: u32, + pub data: cli_htu32_element__bindgen_ty_1, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union cli_htu32_element__bindgen_ty_1 { + pub as_size_t: usize, + pub as_ptr: *mut ::std::os::raw::c_void, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_htu32 { + pub htable: *mut cli_htu32_element, + pub capacity: usize, + pub used: usize, + pub maxfill: usize, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_hashset { + pub keys: *mut u32, + pub bitmap: *mut u32, + pub mempool: *mut mpool_t, + pub capacity: u32, + pub mask: u32, + pub count: u32, + pub limit: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_subsig_matches { + pub last: u32, + pub next: u32, + pub offsets: [u32; 16usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_lsig_matches { + pub subsigs: u32, + pub matches: [*mut cli_subsig_matches; 1usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_ac_data { + pub offmatrix: *mut *mut *mut u32, + pub partsigs: u32, + pub lsigs: u32, + pub reloffsigs: u32, + pub lsigcnt: *mut *mut u32, + pub lsigsuboff_last: *mut *mut u32, + pub lsigsuboff_first: *mut *mut u32, + pub lsig_matches: *mut *mut cli_lsig_matches, + pub yr_matches: *mut u8, + pub offset: *mut u32, + pub macro_lastmatch: [u32; 32usize], + #[doc = " Hashset for versioninfo matching"] + pub vinfo: *const cli_hashset, + pub min_partno: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_alt_node { + pub str_: *mut u16, + pub len: u16, + pub unique: u8, + pub next: *mut cli_alt_node, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cli_ac_special { + pub alt: cli_ac_special__bindgen_ty_1, + pub len: [u16; 2usize], + pub num: u16, + pub type_: u16, + pub negative: u16, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union cli_ac_special__bindgen_ty_1 { + pub byte: *mut ::std::os::raw::c_uchar, + pub f_str: *mut *mut ::std::os::raw::c_uchar, + pub v_str: *mut cli_alt_node, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_ac_patt { + pub pattern: *mut u16, + pub prefix: *mut u16, + pub length: [u16; 3usize], + pub prefix_length: [u16; 3usize], + pub mindist: u32, + pub maxdist: u32, + pub sigid: u32, + pub lsigid: [u32; 3usize], + pub ch: [u16; 2usize], + pub virname: *mut ::std::os::raw::c_char, + pub customdata: *mut ::std::os::raw::c_void, + pub ch_mindist: [u16; 2usize], + pub ch_maxdist: [u16; 2usize], + pub parts: u16, + pub partno: u16, + pub special: u16, + pub special_pattern: u16, + pub special_table: *mut *mut cli_ac_special, + pub rtype: u16, + pub type_: u16, + pub offdata: [u32; 4usize], + pub offset_min: u32, + pub offset_max: u32, + pub boundary: u32, + pub depth: u8, + pub sigopts: u8, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cli_ac_list { + pub me: *mut cli_ac_patt, + pub __bindgen_anon_1: cli_ac_list__bindgen_ty_1, + pub next_same: *mut cli_ac_list, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union cli_ac_list__bindgen_ty_1 { + pub node: *mut cli_ac_node, + pub next: *mut cli_ac_list, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_ac_node { + pub list: *mut cli_ac_list, + pub trans: *mut *mut cli_ac_node, + pub fail: *mut cli_ac_node, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_ac_result { + pub virname: *const ::std::os::raw::c_char, + pub customdata: *mut ::std::os::raw::c_void, + pub offset: off_t, + pub next: *mut cli_ac_result, +} +extern "C" { + #[doc = " @brief Increment the count for a subsignature of a logical signature.\n\n This is and alternative to lsig_increment_subsig_match() for use in subsigs that don't have a specific offset,\n like byte-compare subsigs and fuzzy-hash subsigs."] + pub fn lsig_increment_subsig_match(mdata: *mut cli_ac_data, lsig_id: u32, subsig_id: u32); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bm_patt { + pub pattern: *mut ::std::os::raw::c_uchar, + pub prefix: *mut ::std::os::raw::c_uchar, + pub virname: *mut ::std::os::raw::c_char, + pub offdata: [u32; 4usize], + pub offset_min: u32, + pub offset_max: u32, + pub next: *mut cli_bm_patt, + pub length: u16, + pub prefix_length: u16, + pub cnt: u16, + pub pattern0: ::std::os::raw::c_uchar, + pub boundary: u32, + pub filesize: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_sz_hash { + pub hash_array: *mut u8, + pub virusnames: *mut *const ::std::os::raw::c_char, + pub items: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_hash_patt { + pub sizehashes: [cli_htu32; 3usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_hash_wild { + pub hashes: [cli_sz_hash; 3usize], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct pcre2_real_match_context_8 { + _unused: [u8; 0], +} +pub type pcre2_match_context_8 = pcre2_real_match_context_8; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct pcre2_real_code_8 { + _unused: [u8; 0], +} +pub type pcre2_code_8 = pcre2_real_code_8; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_pcre_data { + pub re: *mut pcre2_code_8, + pub mctx: *mut pcre2_match_context_8, + pub options: ::std::os::raw::c_int, + pub expression: *mut ::std::os::raw::c_char, + pub search_offset: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_pcre_meta { + pub trigger: *mut ::std::os::raw::c_char, + pub lsigid: [u32; 3usize], + pub pdata: cli_pcre_data, + pub offdata: [u32; 4usize], + pub offset_min: u32, + pub offset_max: u32, + pub flags: u32, + pub statname: *mut ::std::os::raw::c_char, + pub sigtime_id: u32, + pub sigmatch_id: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bcomp_meta { + pub ref_subsigid: u16, + pub lsigid: [u32; 3usize], + pub offset: isize, + pub options: u16, + pub byte_len: usize, + pub comps: *mut *mut cli_bcomp_comp, + pub comp_count: u32, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bcomp_comp { + pub comp_symbol: ::std::os::raw::c_char, + pub comp_value: i64, +} +pub const tdb_type_CLI_TDB_UINT: tdb_type = 0; +pub const tdb_type_CLI_TDB_RANGE: tdb_type = 1; +pub const tdb_type_CLI_TDB_STR: tdb_type = 2; +pub const tdb_type_CLI_TDB_RANGE2: tdb_type = 3; +pub const tdb_type_CLI_TDB_FTYPE: tdb_type = 4; +pub const tdb_type_CLI_TDB_FTYPE_EXPR: tdb_type = 5; +pub type tdb_type = ::std::os::raw::c_uint; +pub use self::tdb_type as tdb_type_t; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_lsig_tdb { + pub val: *mut u32, + pub range: *mut u32, + pub str_: *mut ::std::os::raw::c_char, + pub cnt: [tdb_type_t; 3usize], + pub subsigs: u32, + pub target: *const u32, + pub engine: *const u32, + pub nos: *const u32, + pub ep: *const u32, + pub filesize: *const u32, + pub container: *const u32, + pub handlertype: *const u32, + pub intermediates: *const u32, + pub icongrp1: *const ::std::os::raw::c_char, + pub icongrp2: *const ::std::os::raw::c_char, + pub macro_ptids: *mut u32, + pub mempool: *mut mpool_t, +} +pub const lsig_type_CLI_LSIG_NORMAL: lsig_type = 0; +pub const lsig_type_CLI_YARA_NORMAL: lsig_type = 1; +pub const lsig_type_CLI_YARA_OFFSET: lsig_type = 2; +pub type lsig_type = ::std::os::raw::c_uint; +pub use self::lsig_type as lsig_type_t; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct cli_ac_lsig { + pub id: u32, + pub bc_idx: ::std::os::raw::c_uint, + pub type_: lsig_type_t, + pub flag: u8, + pub u: cli_ac_lsig__bindgen_ty_1, + pub virname: *mut ::std::os::raw::c_char, + pub tdb: cli_lsig_tdb, +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union cli_ac_lsig__bindgen_ty_1 { + pub logic: *mut ::std::os::raw::c_char, + pub code_start: *mut u8, +} +pub type fuzzyhashmap_t = *mut ::std::os::raw::c_void; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_matcher { + pub type_: ::std::os::raw::c_uint, + pub bm_shift: *mut u8, + pub bm_suffix: *mut *mut cli_bm_patt, + pub bm_pattab: *mut *mut cli_bm_patt, + pub soff: *mut u32, + pub soff_len: u32, + pub bm_offmode: u32, + pub bm_patterns: u32, + pub bm_reloff_num: u32, + pub bm_absoff_num: u32, + pub hm: cli_hash_patt, + pub hwild: cli_hash_wild, + pub ac_partsigs: u32, + pub ac_nodes: u32, + pub ac_lists: u32, + pub ac_patterns: u32, + pub ac_lsigs: u32, + pub ac_lsigtable: *mut *mut cli_ac_lsig, + pub ac_root: *mut cli_ac_node, + pub ac_nodetable: *mut *mut cli_ac_node, + pub ac_listtable: *mut *mut cli_ac_list, + pub ac_pattable: *mut *mut cli_ac_patt, + pub ac_reloff: *mut *mut cli_ac_patt, + pub ac_reloff_num: u32, + pub ac_absoff_num: u32, + pub ac_mindepth: u8, + pub ac_maxdepth: u8, + pub filter: *mut filter, + pub maxpatlen: u16, + pub ac_only: u8, + pub pcre_metas: u32, + pub pcre_metatable: *mut *mut cli_pcre_meta, + pub pcre_reloff_num: u32, + pub pcre_absoff_num: u32, + pub bcomp_metas: u32, + pub bcomp_metatable: *mut *mut cli_bcomp_meta, + pub fuzzy_hashmap: fuzzyhashmap_t, + pub linked_bcs: u32, + pub trans_array: *mut *mut *mut cli_ac_node, + pub trans_cnt: usize, + pub trans_capacity: usize, + pub mempool: *mut mpool_t, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_cdb { + pub virname: *mut ::std::os::raw::c_char, + pub ctype: cli_file_t, + pub name: regex_t, + pub csize: [usize; 2usize], + pub fsizec: [usize; 2usize], + pub fsizer: [usize; 2usize], + pub encrypted: ::std::os::raw::c_int, + pub filepos: [::std::os::raw::c_uint; 2usize], + pub res1: ::std::os::raw::c_int, + pub res2: *mut ::std::os::raw::c_void, + pub next: *mut cli_cdb, +} +extern "C" { + pub fn cli_versig2( + sha256: *const ::std::os::raw::c_uchar, + dsig_str: *const ::std::os::raw::c_char, + n_str: *const ::std::os::raw::c_char, + e_str: *const ::std::os::raw::c_char, + ) -> ::std::os::raw::c_int; +} +extern "C" { + #[doc = " @brief Connect to a signing server, send the data to be signed, and return the digital signature.\n\n Caller is responsible for freeing the returned dsig.\n\n @param host\n @param user\n @param data\n @param datalen\n @param mode\n @return char*"] + pub fn cli_getdsig( + host: *const ::std::os::raw::c_char, + user: *const ::std::os::raw::c_char, + data: *const ::std::os::raw::c_uchar, + datalen: ::std::os::raw::c_uint, + mode: ::std::os::raw::c_ushort, + ) -> *mut ::std::os::raw::c_char; +} +pub type css_image_extractor_t = *mut ::std::os::raw::c_void; +pub type css_image_handle_t = *mut ::std::os::raw::c_void; +extern "C" { + #[doc = " @brief Convenience wrapper for cli_magic_scan_nested_fmap_type().\n\n Creates an fmap and calls cli_magic_scan_nested_fmap_type() for you, with type CL_TYPE_ANY.\n\n @param buffer Pointer to the buffer to be scanned.\n @param length Size in bytes of the buffer being scanned.\n @param ctx Scanning context structure.\n @param name (optional) Original name of the file (to set fmap name metadata)\n @param attributes Layer attributes of the file being scanned (is it normalized, decrypted, etc)\n @return int CL_SUCCESS, or an error code."] + pub fn cli_magic_scan_buff( + buffer: *const ::std::os::raw::c_void, + length: usize, + ctx: *mut cli_ctx, + name: *const ::std::os::raw::c_char, + attributes: u32, + ) -> cl_error_t; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct re_guts { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct cli_bcengine { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct regex_matcher { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct phishcheck { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct CACHE { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct filter { + pub _address: u8, +} diff --git a/clamav-sys/src/lib.rs b/clamav-sys/src/lib.rs index a926b9551d..cdcec82945 100644 --- a/clamav-sys/src/lib.rs +++ b/clamav-sys/src/lib.rs @@ -27,6 +27,11 @@ use std::ffi::CStr; include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod sys { + include!(concat!(env!("OUT_DIR"), "/sys.rs")); +} + impl Default for cl_scan_options { fn default() -> Self { cl_scan_options { diff --git a/libclamav_rust/Cargo.toml b/libclamav_rust/Cargo.toml index 26a3a22b3a..54fb7eefd1 100644 --- a/libclamav_rust/Cargo.toml +++ b/libclamav_rust/Cargo.toml @@ -19,14 +19,15 @@ num-traits = "0.2" base64 = "0.21.0" sha1 = "0.10.5" unicode-segmentation = "1.10.1" -bindgen = "0.65" onenote_parser = { git = "https://github.com/Cisco-Talos/onenote.rs.git", branch = "CLAM-2329-new-from-slice" } hex-literal = "0.4.1" +clamav-sys = { path = "../clamav-sys" } [lib] crate-type = ["staticlib"] name = "clamav_rust" [build-dependencies] -cbindgen = { version ="0.25", default-features = false } -bindgen = "0.65" +cbindgen = { version = "0.26", default-features = false } +bindgen = "0.69" +anyhow = "1.0" diff --git a/libclamav_rust/build.rs b/libclamav_rust/build.rs index 36dd19dd77..6585862ae2 100644 --- a/libclamav_rust/build.rs +++ b/libclamav_rust/build.rs @@ -1,7 +1,7 @@ use std::env; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; -use bindgen::builder; +use anyhow::anyhow; // Note to maintainers: this is currently a hybrid of examination of the // CMake environment, and leaning on Rust `cfg` elements. Ideally, it @@ -14,84 +14,12 @@ use bindgen::builder; // // https://doc.rust-lang.org/reference/conditional-compilation.html -// A list of environment variables to query to determine additional libraries -// that need to be linked to resolve dependencies. -const LIB_ENV_LINK: &[&str] = &[ - "LIBSSL", - "LIBCRYPTO", - "LIBZ", - "LIBBZ2", - "LIBPCRE2", - "LIBXML2", - "LIBCURL", - "LIBJSONC", - "LIBCLAMMSPACK", - "LIBCLAMUNRARIFACE", - "LIBCLAMUNRAR", - "LIBICONV", -]; - -// The same, but additional values to check on Windows platforms -const LIB_ENV_LINK_WINDOWS: &[&str] = &["LIBPTHREADW32", "LIBWIN32COMPAT"]; - -// Additional [verbatim] libraries to link on Windows platforms -const LIB_LINK_WINDOWS: &[&str] = &["wsock32", "ws2_32", "Shell32", "User32"]; - -// Windows library names that must have the leading `lib` trimmed (if encountered) -const WINDOWS_TRIM_LOCAL_LIB: &[&str] = &["libclamav", "libclammspack"]; - -// Generate bindings for these functions: -const BINDGEN_FUNCTIONS: &[&str] = &[ - "cli_ctx", - "cli_warnmsg", - "cli_dbgmsg_no_inline", - "cli_infomsg_simple", - "cli_errmsg", - "cli_append_virus", - "lsig_increment_subsig_match", - "cli_versig2", - "cli_getdsig", - "cli_get_debug_flag", - "cli_magic_scan_buff", -]; - -// Generate bindings for these types (structs, enums): -const BINDGEN_TYPES: &[&str] = &[ - "cli_matcher", - "cli_ac_data", - "cli_ac_result", - "css_image_extractor_t", - "css_image_handle_t", - "onedump_t", -]; - -// Find the required functions and types in these headers: -const BINDGEN_HEADERS: &[&str] = &[ - "../libclamav/matcher.h", - "../libclamav/matcher-ac.h", - "../libclamav/others.h", - "../libclamav/dsig.h", - "../libclamav/htmlnorm.h", - "../libclamav/fmap.h", - "../libclamav/scanners.h", -]; - -// Find the required headers in these directories: -const BINDGEN_INCLUDE_PATHS: &[&str] = &[ - "-I../libclamav", - "-I../libclamunrar_iface", - "-I../libclammspack", -]; - -// Write the bindings to this file: -const BINDGEN_OUTPUT_FILE: &str = "src/sys.rs"; - const C_HEADER_OUTPUT: &str = "clamav_rust.h"; // Environment variable name prefixes worth including for diags const ENV_PATTERNS: &[&str] = &["CARGO_", "RUST", "LIB"]; -fn main() -> Result<(), &'static str> { +pub fn main() -> anyhow::Result<()> { // Dump the command line and interesting environment variables for diagnostic // purposes. These will end up in a 'stderr' file under the target directory, // in a ".../clamav_rust-" subdirectory @@ -102,26 +30,12 @@ fn main() -> Result<(), &'static str> { .filter(|(k, _)| ENV_PATTERNS.iter().any(|prefix| k.starts_with(prefix))) .for_each(|(k, v)| eprintln!(" {}={:?}", k, v)); - detect_clamav_build()?; - // We only want to generate bindings for `cargo build`, not `cargo test`. // FindRust.cmake defines $CARGO_CMD so we can differentiate. let cargo_cmd = env::var("CARGO_CMD").unwrap_or_else(|_| "".into()); if cargo_cmd == "build" { // Always generate the C-headers when CMake kicks off a build. execute_cbindgen()?; - - // Only generate the `.rs` bindings when maintainer-mode is enabled. - // - // Bindgen requires libclang, which may not readily available, so we - // will commit the bindings to version control and use maintainer-mode - // to update them, as needed. - // On the plus-side, this means that our `.rs` file is present before our - // first build, so at least rust-analyzer will be happy. - let maintainer_mode = env::var("MAINTAINER_MODE").unwrap_or_else(|_| "".into()); - if maintainer_mode == "ON" { - execute_bindgen()?; - } } else { eprintln!("NOTE: Not generating bindings because CARGO_CMD != build"); } @@ -129,61 +43,10 @@ fn main() -> Result<(), &'static str> { Ok(()) } -/// Use bindgen to generate Rust bindings to call into C libraries. -fn execute_bindgen() -> Result<(), &'static str> { - let build_dir = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".into())); - let build_include_path = format!("-I{}", build_dir.join(".").to_str().unwrap()); - let has_include_directories = env::var("CARGO_INCLUDE_DIRECTORIES").ok(); - - // Configure and generate bindings. - let mut builder = builder() - // Silence code-style warnings for generated bindings. - .raw_line("#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]") - // Make the bindings pretty. - .formatter(bindgen::Formatter::Rustfmt) - // Disable the layout tests. - // We're committing to source control. Pointer width, integer size, etc - // are probably not the same when generated as when compiled. - .layout_tests(false) - // Enable bindgen to find generated headers in the build directory, too. - .clang_arg(build_include_path); - - // If include directories were specified, add them to the builder. - if let Some(include_directories) = has_include_directories { - for include_directory in include_directories.split(';') { - // Enable bindgen to find dependencies headers. - builder = builder.clang_arg(format!("-I{include_directory}")); - } - } - - for &include_path in BINDGEN_INCLUDE_PATHS { - builder = builder.clang_arg(include_path); - } - for &header in BINDGEN_HEADERS { - builder = builder.header(header); - } - for &c_function in BINDGEN_FUNCTIONS { - builder = builder.allowlist_function(c_function); - } - for &c_type in BINDGEN_TYPES { - builder = builder.allowlist_type(c_type); - } - - // Generate! - builder - .generate() - .expect("Generating Rust bindings for C code") - .write_to_file(BINDGEN_OUTPUT_FILE) - .expect("Writing Rust bindings to output file"); - - eprintln!("bindgen outputting \"{}\"", BINDGEN_OUTPUT_FILE); - - Ok(()) -} - /// Use cbindgen to generate C-header's for Rust static libraries. -fn execute_cbindgen() -> Result<(), &'static str> { - let crate_dir = env::var("CARGO_MANIFEST_DIR").or(Err("CARGO_MANIFEST_DIR not specified"))?; +fn execute_cbindgen() -> anyhow::Result<()> { + let crate_dir = + env::var("CARGO_MANIFEST_DIR").or(Err(anyhow!("CARGO_MANIFEST_DIR not specified")))?; let build_dir = PathBuf::from(env::var("CARGO_TARGET_DIR").unwrap_or_else(|_| ".".into())); let outfile_path = build_dir.join(C_HEADER_OUTPUT); @@ -195,147 +58,3 @@ fn execute_cbindgen() -> Result<(), &'static str> { Ok(()) } - -fn detect_clamav_build() -> Result<(), &'static str> { - println!("cargo:rerun-if-env-changed=LIBCLAMAV"); - - if search_and_link_lib("LIBCLAMAV")? { - eprintln!("NOTE: LIBCLAMAV defined. Examining LIB* environment variables"); - // Need to link with libclamav dependencies - - // LLVM is optional, and don't have a path to each library like we do with the other libs. - let llvm_libs = env::var("LLVM_LIBS").unwrap_or("".into()); - if !llvm_libs.is_empty() { - match env::var("LLVM_DIRS") { - Err(env::VarError::NotPresent) => eprintln!("LLVM_DIRS not set"), - Err(env::VarError::NotUnicode(_)) => return Err("environment value not unicode"), - Ok(s) => { - if s.is_empty() { - eprintln!("LLVM_DIRS not set"); - } else { - s.split(',').for_each(|dirpath| { - println!("cargo:rustc-link-search={}", dirpath); - }); - } - } - }; - - llvm_libs - .split(',') - .for_each(|filepath_str| match parse_lib_path(filepath_str) { - Ok(parsed_path) => { - println!("cargo:rustc-link-search={}", parsed_path.dir); - eprintln!(" - requesting that rustc link {:?}", &parsed_path.libname); - println!("cargo:rustc-link-lib={}", parsed_path.libname); - } - Err(_) => { - eprintln!(" - requesting that rustc link {:?}", filepath_str); - println!("cargo:rustc-link-lib={}", filepath_str); - } - }); - } - - for var in LIB_ENV_LINK { - let _ = search_and_link_lib(var); - } - - if cfg!(windows) { - for var in LIB_ENV_LINK_WINDOWS { - let _ = search_and_link_lib(var); - } - for lib in LIB_LINK_WINDOWS { - println!("cargo:rustc-link-lib={}", lib); - } - } else { - // Link the test executable with libstdc++ on unix systems, - // This is needed for fully-static build where clamav & 3rd party - // dependencies excluding the std libs are static. - if cfg!(target_os = "linux") { - eprintln!("NOTE: linking libstdc++ (linux target)"); - println!("cargo:rustc-link-lib=stdc++"); - } else { - eprintln!("NOTE: NOT linking libstdc++ (non-linux target)"); - } - } - } else { - println!("NOTE: LIBCLAMAV not defined"); - } - - Ok(()) -} - -// -// Return whether the specified environment variable has been set, and output -// linking directives as a side-effect -// -fn search_and_link_lib(environment_variable: &str) -> Result { - eprintln!(" - checking for {:?} in environment", environment_variable); - let filepath_str = match env::var(environment_variable) { - Err(env::VarError::NotPresent) => return Ok(false), - Err(env::VarError::NotUnicode(_)) => return Err("environment value not unicode"), - Ok(s) => { - if s.is_empty() { - return Ok(false); - } else { - s - } - } - }; - - let parsed_path = parse_lib_path(&filepath_str)?; - eprintln!( - " - adding {:?} to rustc library search path", - &parsed_path.dir - ); - println!("cargo:rustc-link-search={}", parsed_path.dir); - eprintln!(" - requesting that rustc link {:?}", &parsed_path.libname); - println!("cargo:rustc-link-lib={}", parsed_path.libname); - - Ok(true) -} - -struct ParsedLibraryPath { - dir: String, - libname: String, -} - -// Parse a library path, returning the portion expected after the `-l`, and the -// directory containing the library -fn parse_lib_path(path: &str) -> Result { - let path = PathBuf::from(path); - let file_name = path - .file_name() - .ok_or("file name not found")? - .to_str() - .ok_or("file name not unicode")?; - - // This can't fail because it came from a &str - let dir = path - .parent() - .unwrap_or_else(|| Path::new(".")) - .to_str() - .unwrap() - .to_owned(); - - // Grab the portion up to the first '.' - let full_libname = file_name - .split('.') - .next() - .ok_or("no '.' found in file name")?; - - // Windows typically requires the full filename when linking system libraries, - // but not when it's one of the locally-generated libraries. - let should_trim_leading_lib = - !cfg!(windows) || WINDOWS_TRIM_LOCAL_LIB.iter().any(|s| *s == full_libname); - - let libname = if should_trim_leading_lib { - full_libname - .strip_prefix("lib") - .ok_or(r#"file name doesn't begin with "lib""#)? - } else { - full_libname - } - .to_owned(); - - Ok(ParsedLibraryPath { dir, libname }) -} diff --git a/libclamav_rust/src/lib.rs b/libclamav_rust/src/lib.rs index 3a19b84b50..b66a592fa9 100644 --- a/libclamav_rust/src/lib.rs +++ b/libclamav_rust/src/lib.rs @@ -21,7 +21,7 @@ */ /// cbindgen:ignore -pub mod sys; +pub use clamav_sys::sys; pub mod cdiff; pub mod css_image_extract; From 8ba0464f7d5cf1a24326d50bc97fdf3b87901c7f Mon Sep 17 00:00:00 2001 From: Scott Hutton Date: Wed, 24 Jan 2024 13:55:04 -0800 Subject: [PATCH 4/4] Refactor win/unix; additional env detection --- clamav-sys/build.rs | 148 +++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 65 deletions(-) diff --git a/clamav-sys/build.rs b/clamav-sys/build.rs index 3560260371..e4b7defb25 100644 --- a/clamav-sys/build.rs +++ b/clamav-sys/build.rs @@ -139,6 +139,7 @@ fn generate_bindings( bindings = bindings.allowlist_var(constant); } + // TODO: this wrapper probably isn't necessary. clamav.h could simply be located bindings = bindings .header("wrapper.h") // Tell cargo to invalidate the built crate whenever any of the @@ -165,76 +166,79 @@ fn cargo_common() { println!("cargo:rerun-if-changed=wrapper.h"); } -#[cfg(windows)] -pub fn main() { - let include_paths = match vcpkg::find_package("clamav") { - Ok(pkg) => pkg.include_paths, - Err(err) => { - println!( - "cargo:warning=Either vcpkg is not installed, or an error occurred in vcpkg: {}", - err - ); - let clamav_source = PathBuf::from(env::var("CLAMAV_SOURCE").expect("CLAMAV_SOURCE environment variable must be set and point to ClamAV's source directory")); - let clamav_build = PathBuf::from(env::var("CLAMAV_BUILD").expect("CLAMAV_BUILD environment variable must be set and point to ClamAV's build directory")); - let openssl_include = PathBuf::from(env::var("OPENSSL_INCLUDE").expect("OPENSSL_INCLUDE environment variable must be set and point to openssl's include directory")); - let profile = env::var("PROFILE").unwrap(); - - let library_path = match profile.as_str() { - "debug" => std::path::Path::new(&clamav_build).join("libclamav/Debug"), - "release" => std::path::Path::new(&clamav_build).join("libclamav/Release"), - _ => panic!("Unexpected build profile"), - }; - - println!( - "cargo:rustc-link-search=native={}", - library_path.to_str().unwrap() - ); - - vec![ - clamav_source.join("libclamav"), - clamav_build, - openssl_include, - ] - } - }; - +fn main() -> anyhow::Result<()> { cargo_common(); - generate_bindings(&|x: bindgen::Builder| -> bindgen::Builder { - let mut x = x; - for include_path in &include_paths { - x = x.clang_arg("-I").clang_arg(include_path.to_str().unwrap()); - } - x - }); -} -#[cfg(unix)] -fn main() -> anyhow::Result<()> { let mut include_paths = vec![]; + // Test whether being built as part of ClamAV source + let local_include_path = local_clamav_include_path(); + if let Some(path) = &local_include_path { + eprintln!("Local ClamAV include path: {path:?}",); + } + eprintln!( + "Building as part of ClamAV: {:?}", + building_under_clamav_cmake() + ); + eprintln!("Maintainer mode: {:?}", in_maintainer_mode()); + + // Generate temporary path for the generated "internal" module let mut output_path_intmod = PathBuf::from(env::var("OUT_DIR")?); output_path_intmod.push("sys.rs"); - let local_include_path = local_clamav_include_path(); - - if let Some(include_path) = &local_include_path { - // It seems we're being compiled from within the ClamAV source tree. - // Confirm that clamav.h is there, too + // Find headers + if let Some(path) = &local_include_path { + include_paths.push(path.clone()); + } else { + // This crate is being referenced from an external project that doesn't + // have access to the ClamAV source tree. Utilize the system-installed + // copy of libclamav (as located using pkg-config). + + #[cfg(not(windows))] + { + let libclamav = pkg_config::Config::new() + .atleast_version("0.103") + .probe("libclamav") + .unwrap(); + + include_paths.extend_from_slice(&libclamav.include_paths); + } - include_paths.push(include_path.clone()); + #[cfg(windows)] + match vcpkg::find_package("clamav") { + Ok(pkg) => include_paths.extend_from_slice(&pkg.include_paths), + Err(err) => { + println!( + "cargo:warning=Either vcpkg is not installed, or an error occurred in vcpkg: {}", + err + ); + // Attempt to examine user-supplied variables to find the dependencies + let clamav_source = PathBuf::from(env::var("CLAMAV_SOURCE").expect("CLAMAV_SOURCE environment variable must be set and point to ClamAV's source directory")); + let clamav_build = PathBuf::from(env::var("CLAMAV_BUILD").expect("CLAMAV_BUILD environment variable must be set and point to ClamAV's build directory")); + let openssl_include = PathBuf::from(env::var("OPENSSL_INCLUDE").expect("OPENSSL_INCLUDE environment variable must be set and point to openssl's include directory")); + let profile = env::var("PROFILE").unwrap(); + + let library_path = match profile.as_str() { + "debug" => std::path::Path::new(&clamav_build).join("libclamav/Debug"), + "release" => std::path::Path::new(&clamav_build).join("libclamav/Release"), + _ => panic!("Unexpected build profile"), + }; + + println!( + "cargo:rustc-link-search=native={}", + library_path.to_str().unwrap() + ); + + include_paths.push(clamav_source.join("libclamav")); + include_paths.push(clamav_build); + include_paths.push(openssl_include); + } + }; + } + if building_under_clamav_cmake() { build_internal::bindgen_internal(&output_path_intmod)?; } else { - // This crate is being referenced from an external project. Utilize the - // system-installed copy of libclamav (as located using pkg-config). - - let libclamav = pkg_config::Config::new() - .atleast_version("0.103") - .probe("libclamav") - .unwrap(); - - include_paths.extend_from_slice(&libclamav.include_paths); - // Build a vestigial `sys` module, as there will be no access to // internal APIs. let mut fh = std::fs::File::create(&output_path_intmod)?; @@ -244,8 +248,7 @@ fn main() -> anyhow::Result<()> { // Write the bindings to the $OUT_DIR/bindings.rs file. let mut output_path = PathBuf::from(env::var("OUT_DIR").unwrap()); output_path.push("bindings.rs"); - if local_include_path.is_none() || (local_include_path.is_some() && in_maintainer_mode()) { - cargo_common(); + if !building_under_clamav_cmake() || (local_include_path.is_some() && in_maintainer_mode()) { generate_bindings( &output_path, &|builder: bindgen::Builder| -> bindgen::Builder { @@ -258,14 +261,19 @@ fn main() -> anyhow::Result<()> { builder }, ); - // And place a copy in the source tree (for potential check-in) - std::fs::copy(&output_path, BINDGEN_OUTPUT_FILE)?; } else { - // Otherwise, just copy the pre-generated file to the specified - // location. + // If building within ClamAV and not in maintainer mode, just copy the + // "cached" version, as libclang may not be available. std::fs::copy(BINDGEN_OUTPUT_FILE, &output_path)?; } + if in_maintainer_mode() { + // Copy the pre-generated file to the specified location. This should + // *not* be done when packaging `clamav-sys`, as it will touch the + // source tree, and `cargo package` will report an error. + std::fs::copy(&output_path, BINDGEN_OUTPUT_FILE)?; + } + Ok(()) } @@ -290,6 +298,16 @@ fn local_clamav_include_path() -> Option { None } +/// Return whether "maintiner mode" has been enabled in a ClamAV build. pub(crate) fn in_maintainer_mode() -> bool { env::var("MAINTAINER_MODE").unwrap_or_default() == "ON" } + +/// Return whether or not this crate's build is being performed as part of a ClamAV build +pub(crate) fn building_under_clamav_cmake() -> bool { + // Note, PROJECT_NAME is examined rather than CMAKE_PROJECT_NAME, as it's + // *possible* for a ClamAV build to be embedded within another CMake-based + // build, which would have a global CMAKE_PROJECT_NAME that is *not* + // "ClamAV" + env::var("PROJECT_NAME").unwrap_or_default() == "ClamAV" +}