]>
git.proxmox.com Git - cargo.git/blob - vendor/openssl/src/error.rs
1 //! Errors returned by OpenSSL library.
3 //! OpenSSL errors are stored in an `ErrorStack`. Most methods in the crate
4 //! returns a `Result<T, ErrorStack>` type.
9 //! use openssl::error::ErrorStack;
10 //! use openssl::bn::BigNum;
12 //! let an_error = BigNum::from_dec_str("Cannot parse letters");
15 //! Err(e) => println!("Parsing Error: {:?}", e),
18 use libc
::{c_char, c_int, c_ulong}
;
29 /// Collection of [`Error`]s from OpenSSL.
31 /// [`Error`]: struct.Error.html
32 #[derive(Debug, Clone)]
33 pub struct ErrorStack(Vec
<Error
>);
36 /// Returns the contents of the OpenSSL error stack.
37 pub fn get() -> ErrorStack
{
39 while let Some(err
) = Error
::get() {
45 /// Pushes the errors back onto the OpenSSL error stack.
47 for error
in self.errors() {
54 /// Returns the errors in the stack.
55 pub fn errors(&self) -> &[Error
] {
60 impl fmt
::Display
for ErrorStack
{
61 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
62 if self.0.is_empty
() {
63 return fmt
.write_str("OpenSSL error");
71 write
!(fmt
, "{}", err
)?
;
78 impl error
::Error
for ErrorStack {}
80 impl From
<ErrorStack
> for io
::Error
{
81 fn from(e
: ErrorStack
) -> io
::Error
{
82 io
::Error
::new(io
::ErrorKind
::Other
, e
)
86 impl From
<ErrorStack
> for fmt
::Error
{
87 fn from(_
: ErrorStack
) -> fmt
::Error
{
92 /// An error reported from OpenSSL.
98 data
: Option
<Cow
<'
static, str>>,
101 unsafe impl Sync
for Error {}
102 unsafe impl Send
for Error {}
105 /// Returns the first error on the OpenSSL error stack.
106 pub fn get() -> Option
<Error
> {
110 let mut file
= ptr
::null();
112 let mut data
= ptr
::null();
114 match ffi
::ERR_get_error_line_data(&mut file
, &mut line
, &mut data
, &mut flags
) {
117 // The memory referenced by data is only valid until that slot is overwritten
118 // in the error stack, so we'll need to copy it off if it's dynamic
119 let data
= if flags
& ffi
::ERR_TXT_STRING
!= 0 {
120 let bytes
= CStr
::from_ptr(data
as *const _
).to_bytes();
121 let data
= str::from_utf8(bytes
).unwrap();
122 let data
= if flags
& ffi
::ERR_TXT_MALLOCED
!= 0 {
123 Cow
::Owned(data
.to_string())
142 /// Pushes the error back onto the OpenSSL error stack.
146 ffi
::ERR_GET_LIB(self.code
),
147 ffi
::ERR_GET_FUNC(self.code
),
148 ffi
::ERR_GET_REASON(self.code
),
152 let data
= match self.data
{
153 Some(Cow
::Borrowed(data
)) => Some((data
.as_ptr() as *mut c_char
, 0)),
154 Some(Cow
::Owned(ref data
)) => {
155 let ptr
= ffi
::CRYPTO_malloc(
156 (data
.len() + 1) as _
,
157 concat
!(file
!(), "\0").as_ptr() as _
,
163 ptr
::copy_nonoverlapping(data
.as_ptr(), ptr
as *mut u8, data
.len());
164 *ptr
.add(data
.len()) = 0;
165 Some((ptr
, ffi
::ERR_TXT_MALLOCED
))
170 if let Some((ptr
, flags
)) = data
{
171 ffi
::ERR_set_error_data(ptr
, flags
| ffi
::ERR_TXT_STRING
);
176 /// Returns the raw OpenSSL error code for this error.
177 pub fn code(&self) -> c_ulong
{
181 /// Returns the name of the library reporting the error, if available.
182 pub fn library(&self) -> Option
<&'
static str> {
184 let cstr
= ffi
::ERR_lib_error_string(self.code
);
188 let bytes
= CStr
::from_ptr(cstr
as *const _
).to_bytes();
189 Some(str::from_utf8(bytes
).unwrap())
193 /// Returns the name of the function reporting the error.
194 pub fn function(&self) -> Option
<&'
static str> {
196 let cstr
= ffi
::ERR_func_error_string(self.code
);
200 let bytes
= CStr
::from_ptr(cstr
as *const _
).to_bytes();
201 Some(str::from_utf8(bytes
).unwrap())
205 /// Returns the reason for the error.
206 pub fn reason(&self) -> Option
<&'
static str> {
208 let cstr
= ffi
::ERR_reason_error_string(self.code
);
212 let bytes
= CStr
::from_ptr(cstr
as *const _
).to_bytes();
213 Some(str::from_utf8(bytes
).unwrap())
217 /// Returns the name of the source file which encountered the error.
218 pub fn file(&self) -> &'
static str {
220 assert
!(!self.file
.is_null());
221 let bytes
= CStr
::from_ptr(self.file
as *const _
).to_bytes();
222 str::from_utf8(bytes
).unwrap()
226 /// Returns the line in the source file which encountered the error.
227 pub fn line(&self) -> u32 {
231 /// Returns additional data describing the error.
232 #[allow(clippy::option_as_ref_deref)]
233 pub fn data(&self) -> Option
<&str> {
234 self.data
.as_ref().map(|s
| &**s
)
238 impl fmt
::Debug
for Error
{
239 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
240 let mut builder
= fmt
.debug_struct("Error");
241 builder
.field("code", &self.code());
242 if let Some(library
) = self.library() {
243 builder
.field("library", &library
);
245 if let Some(function
) = self.function() {
246 builder
.field("function", &function
);
248 if let Some(reason
) = self.reason() {
249 builder
.field("reason", &reason
);
251 builder
.field("file", &self.file());
252 builder
.field("line", &self.line());
253 if let Some(data
) = self.data() {
254 builder
.field("data", &data
);
260 impl fmt
::Display
for Error
{
261 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
262 write
!(fmt
, "error:{:08X}", self.code())?
;
263 match self.library() {
264 Some(l
) => write
!(fmt
, ":{}", l
)?
,
265 None
=> write
!(fmt
, ":lib({})", ffi
::ERR_GET_LIB(self.code()))?
,
267 match self.function() {
268 Some(f
) => write
!(fmt
, ":{}", f
)?
,
269 None
=> write
!(fmt
, ":func({})", ffi
::ERR_GET_FUNC(self.code()))?
,
271 match self.reason() {
272 Some(r
) => write
!(fmt
, ":{}", r
)?
,
273 None
=> write
!(fmt
, ":reason({})", ffi
::ERR_GET_REASON(self.code()))?
,
280 self.data().unwrap_or("")
285 impl error
::Error
for Error {}