-
Notifications
You must be signed in to change notification settings - Fork 706
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Complete merge of clamav-sys from separate repo
- Loading branch information
Showing
8 changed files
with
833 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,6 @@ | ||
[workspace] | ||
|
||
members = [ | ||
"libclamav_rust", | ||
] | ||
members = ["clamav-sys", "libclamav_rust"] | ||
|
||
[profile.dev.package."*"] | ||
opt-level = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/target | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
authors = [ | ||
"Jonas Zaddach <[email protected]>", | ||
"Scott Hutton <[email protected]>", | ||
] | ||
categories = ["external-ffi-bindings"] | ||
description = "ClamAV low level bindings for Rust" | ||
edition = "2021" | ||
homepage = "https://github.com/Cisco-Talos/clamav-sys/" | ||
license = "GPL-2.0" | ||
name = "clamav-sys" | ||
repository = "https://github.com/Cisco-Talos/clamav-sys/" | ||
version = "1.0.0" | ||
|
||
[build-dependencies] | ||
bindgen = "0.64.0" | ||
|
||
[target.'cfg(unix)'.build-dependencies] | ||
pkg-config = "0.3" | ||
|
||
[target.'cfg(windows)'.build-dependencies] | ||
vcpkg = "0.2.10" |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# clamav-sys | ||
|
||
clamav-sys is a minimal Rust interface around [libclamav](https://www.clamav.net). | ||
This package is not supposed to be used stand-alone, but only through its safe wrapper, | ||
clamav-rs. | ||
|
||
|
||
## Building | ||
|
||
### Unix (anything but Windows) | ||
You should have the `clamav-dev` package of your distribution installed (ClamAV | ||
with headers). The headers and library should be picked up automatically via | ||
pkg-config. | ||
|
||
### Windows | ||
#### vcpkg | ||
The preferred way of handling dependencies is `vcpkg`. | ||
Point `$env:VCPKG_ROOT` to your `vcpkg` installation, and set | ||
`$env:VCPKGRS_DYNAMIC=1` to use dynamic linking (the default method of linking will | ||
likely not work, as `pdcurses` doesn't support the `x64-windows-static-md` triplet). | ||
|
||
See the [vcpkg crate's documentation](https://docs.rs/vcpkg) for more details. | ||
|
||
Gotchas: | ||
- Windows has its own version of a zlib dll that is incompatbile with vcpkg. If | ||
you get a message such as "The procedure entry point gzdirect could not be | ||
located in the dynamic link library", you'll want to make sure that the vcpkg | ||
dynamic libraries in your PATH variable are preceding the Windows one. | ||
``` | ||
$env:PATH="$env:VCPKG_ROOT\installed\x64-windows\bin\;$env:PATH" | ||
``` | ||
This error is especially hard to diagnose in PowerShell, as the process will | ||
just hang without any output. In cmd.exe you'll get the aforementioned dialog | ||
box telling you about the error. | ||
|
||
|
||
#### Manual | ||
If `vcpkg` is not available or cannot be found on your system, the build defaults | ||
to a manual specification of dependencies. | ||
You will need to define the following environment variables: | ||
- `CLAMAV_SOURCE`: Points to the directory where the ClamAV source is located. | ||
- `CLAMAV_BUILD`: Points to the ClamAV build directory. | ||
- `OPENSSL_INCLUDE`: Points to the include directory containing `openssl/ssl.h`. | ||
|
||
### MacOS | ||
Install the development dependencies via `homebrew`: | ||
``` | ||
brew install clamav [email protected] | ||
``` | ||
|
||
OpenSSL is not included in the environment to avoid shadowing Apple's one, so | ||
you need to tell the build script where it is located: | ||
``` | ||
export OPENSSL_ROOT_DIR=/usr/local/Cellar/[email protected]/1.1.1i/ | ||
``` | ||
|
||
## Versioning | ||
The version number of `libclamav-sys` tracks ClamAV's version number. That is, | ||
you'll require at least ClamAV 1.0.0 to build `libclamav-sys` 1.0.0. As ClamAV | ||
usually doesn't do breaking API changes, you'll be able to use `libclamav-sys` | ||
with newer ClamAV versions. | ||
|
||
No attempt at preserving downward compatibility (using a `libclamav-sys` with | ||
a version number greater than ClamAV's) is made. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
// Copyright (C) 2020-2023 Cisco Systems, Inc. and/or its affiliates. All rights reserved. | ||
// | ||
// Authors: Jonas Zaddach, Scott Hutton | ||
// | ||
// This program is free software; you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License version 2 as | ||
// published by the Free Software Foundation. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program; if not, write to the Free Software | ||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
// MA 02110-1301, USA. | ||
|
||
use std::env; | ||
use std::path::PathBuf; | ||
|
||
// Generate bindings for these functions: | ||
const BINDGEN_FUNCTIONS: &[&str] = &[ | ||
"cl_cleanup_crypto", | ||
"cl_cvdfree", | ||
"cl_cvdparse", | ||
"cl_debug", | ||
"cl_engine_addref", | ||
"cl_engine_compile", | ||
"cl_engine_free", | ||
"cl_engine_get_num", | ||
"cl_engine_get_str", | ||
"cl_engine_new", | ||
"cl_engine_set_clcb_engine_compile_progress", | ||
"cl_engine_set_clcb_engine_free_progress", | ||
"cl_engine_set_clcb_file_inspection", | ||
"cl_engine_set_clcb_file_props", | ||
"cl_engine_set_clcb_hash", | ||
"cl_engine_set_clcb_meta", | ||
"cl_engine_set_clcb_post_scan", | ||
"cl_engine_set_clcb_pre_cache", | ||
"cl_engine_set_clcb_pre_scan", | ||
"cl_engine_set_clcb_sigload", | ||
"cl_engine_set_clcb_sigload_progress", | ||
"cl_engine_set_clcb_stats_add_sample", | ||
"cl_engine_set_clcb_stats_decrement_count", | ||
"cl_engine_set_clcb_stats_flush", | ||
"cl_engine_set_clcb_stats_get_hostid", | ||
"cl_engine_set_clcb_stats_get_num", | ||
"cl_engine_set_clcb_stats_get_size", | ||
"cl_engine_set_clcb_stats_remove_sample", | ||
"cl_engine_set_clcb_stats_submit", | ||
"cl_engine_set_clcb_virus_found", | ||
"cl_engine_set_num", | ||
"cl_engine_set_stats_set_cbdata", | ||
"cl_engine_set_str", | ||
"cl_engine_settings_apply", | ||
"cl_engine_settings_copy", | ||
"cl_engine_settings_free", | ||
"cl_engine_stats_enable", | ||
"cl_fmap_close", | ||
"cl_fmap_open_handle", | ||
"cl_fmap_open_memory", | ||
"cl_init", | ||
"cl_initialize_crypto", | ||
"cl_load", | ||
"cl_retdbdir", | ||
"cl_retflevel", | ||
"cl_retver", | ||
"cl_scandesc", | ||
"cl_scandesc_callback", | ||
"cl_scanfile", | ||
"cl_scanfile_callback", | ||
"cl_scanmap_callback", | ||
"cl_set_clcb_msg", | ||
"cl_strerror", | ||
"cli_append_virus", | ||
"cli_ctx", | ||
"cli_dbgmsg_no_inline", | ||
"cli_errmsg", | ||
"cli_get_debug_flag", | ||
"cli_getdsig", | ||
"cli_infomsg_simple", | ||
"cli_versig2", | ||
"cli_warnmsg", | ||
"lsig_increment_subsig_match", | ||
]; | ||
|
||
// Generate bindings for these types (structs, prototypes, etc.): | ||
const BINDGEN_TYPES: &[&str] = &[ | ||
"cl_cvd", | ||
"clcb_file_props", | ||
"clcb_meta", | ||
"clcb_post_scan", | ||
"clcb_pre_scan", | ||
"cli_ac_data", | ||
"cli_ac_result", | ||
"cli_matcher", | ||
"time_t", | ||
]; | ||
|
||
// Generate "newtype" enums for these C enums | ||
const BINDGEN_ENUMS: &[&str] = &["cl_engine_field", "cl_error_t", "cl_msg"]; | ||
|
||
const BINDGEN_CONSTANTS: &[&str] = &[ | ||
"CL_DB_.*", | ||
"CL_INIT_DEFAULT", | ||
"CL_SCAN_.*", | ||
"ENGINE_OPTIONS_.*", | ||
"LAYER_ATTRIBUTES_.*", | ||
]; | ||
|
||
const CLAMAV_LIBRARY_NAME: &str = "clamav"; | ||
|
||
fn generate_bindings(customize_bindings: &dyn Fn(bindgen::Builder) -> bindgen::Builder) { | ||
let mut bindings = bindgen::Builder::default(); | ||
for function in BINDGEN_FUNCTIONS { | ||
bindings = bindings.allowlist_function(function); | ||
} | ||
|
||
for typename in BINDGEN_TYPES { | ||
bindings = bindings.allowlist_type(typename); | ||
} | ||
|
||
for typename in BINDGEN_ENUMS { | ||
bindings = bindings.newtype_enum(typename); | ||
} | ||
|
||
for constant in BINDGEN_CONSTANTS { | ||
bindings = bindings.allowlist_var(constant); | ||
} | ||
|
||
bindings = bindings | ||
.header("wrapper.h") | ||
// Tell cargo to invalidate the built crate whenever any of the | ||
// included header files changed. | ||
.parse_callbacks(Box::new(bindgen::CargoCallbacks)); | ||
|
||
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")) | ||
.expect("Couldn't write bindings!"); | ||
} | ||
|
||
fn cargo_common() { | ||
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() { | ||
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, | ||
] | ||
} | ||
}; | ||
|
||
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() { | ||
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); | ||
} | ||
|
||
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 | ||
}); | ||
} |
Oops, something went wrong.