1// Licensed under the Apache License, Version 2.0 (the "License"); 2// you may not use this file except in compliance with the License. 3// You may obtain a copy of the License at 4// 5// http://www.apache.org/licenses/LICENSE-2.0 6// 7// Unless required by applicable law or agreed to in writing, software 8// distributed under the License is distributed on an "AS IS" BASIS, 9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10// See the License for the specific language governing permissions and 11// limitations under the License. 12// 13 14//! Build and version information. 15 16use cfg_if::cfg_if; 17use openssl_macros::corresponds; 18use std::ffi::CStr; 19 20cfg_if! { 21 if #[cfg(any(ossl110, libressl271))] { 22 use ffi::{ 23 OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR, 24 OpenSSL_version_num, OpenSSL_version, 25 }; 26 } else { 27 use ffi::{ 28 SSLEAY_VERSION as OPENSSL_VERSION, SSLEAY_CFLAGS as OPENSSL_CFLAGS, 29 SSLEAY_BUILT_ON as OPENSSL_BUILT_ON, SSLEAY_PLATFORM as OPENSSL_PLATFORM, 30 SSLEAY_DIR as OPENSSL_DIR, SSLeay as OpenSSL_version_num, 31 SSLeay_version as OpenSSL_version, 32 }; 33 } 34} 35 36/// OPENSSL_VERSION_NUMBER is a numeric release version identifier: 37/// 38/// `MNNFFPPS: major minor fix patch status` 39/// 40/// The status nibble has one of the values 0 for development, 1 to e for betas 1 to 14, and f for release. 41/// 42/// for example 43/// 44/// `0x000906000 == 0.9.6 dev` 45/// `0x000906023 == 0.9.6b beta 3` 46/// `0x00090605f == 0.9.6e release` 47#[corresponds(OpenSSL_version_num)] 48pub fn number() -> i64 { 49 unsafe { OpenSSL_version_num() as i64 } 50} 51 52/// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000". 53#[corresponds(OpenSSL_version)] 54pub fn version() -> &'static str { 55 unsafe { 56 CStr::from_ptr(OpenSSL_version(OPENSSL_VERSION)) 57 .to_str() 58 .unwrap() 59 } 60} 61 62/// The compiler flags set for the compilation process in the form "compiler: ..." if available or 63/// "compiler: information not available" otherwise. 64#[corresponds(OpenSSL_version)] 65pub fn c_flags() -> &'static str { 66 unsafe { 67 CStr::from_ptr(OpenSSL_version(OPENSSL_CFLAGS)) 68 .to_str() 69 .unwrap() 70 } 71} 72 73/// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise. 74#[corresponds(OpenSSL_version)] 75pub fn built_on() -> &'static str { 76 unsafe { 77 CStr::from_ptr(OpenSSL_version(OPENSSL_BUILT_ON)) 78 .to_str() 79 .unwrap() 80 } 81} 82 83/// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise. 84#[corresponds(OpenSSL_version)] 85pub fn platform() -> &'static str { 86 unsafe { 87 CStr::from_ptr(OpenSSL_version(OPENSSL_PLATFORM)) 88 .to_str() 89 .unwrap() 90 } 91} 92 93/// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise. 94#[corresponds(OpenSSL_version)] 95pub fn dir() -> &'static str { 96 unsafe { 97 CStr::from_ptr(OpenSSL_version(OPENSSL_DIR)) 98 .to_str() 99 .unwrap() 100 } 101} 102 103/// This test ensures that we do not segfault when calling the functions of this module 104/// and that the strings respect a reasonable format. 105#[test] 106fn test_versions() { 107 println!("Number: '{}'", number()); 108 println!("Version: '{}'", version()); 109 println!("C flags: '{}'", c_flags()); 110 println!("Built on: '{}'", built_on()); 111 println!("Platform: '{}'", platform()); 112 println!("Dir: '{}'", dir()); 113 114 #[cfg(not(any(libressl, boringssl)))] 115 fn expected_name() -> &'static str { 116 "OpenSSL" 117 } 118 #[cfg(libressl)] 119 fn expected_name() -> &'static str { 120 "LibreSSL" 121 } 122 #[cfg(boringssl)] 123 fn expected_name() -> &'static str { 124 "BoringSSL" 125 } 126 127 assert!(number() > 0); 128 assert!(version().starts_with(expected_name())); 129 assert!(c_flags().starts_with("compiler:")); 130 // some distributions patch out dates out of openssl so that the builds are reproducible 131 if !built_on().is_empty() { 132 assert!(built_on().starts_with("built on:")); 133 } 134 assert!(dir().starts_with("OPENSSLDIR:")); 135} 136