Coverage Report

Created: 2025-12-31 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/vmm-sys-util-0.14.0/src/errno.rs
Line
Count
Source
1
// Copyright 2019 Intel Corporation. All Rights Reserved.
2
//
3
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
//
5
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
6
//
7
// SPDX-License-Identifier: BSD-3-Clause
8
9
//! Structures, helpers, and type definitions for working with
10
//! [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html).
11
12
use std::fmt::{Display, Formatter};
13
use std::io;
14
use std::result;
15
16
/// Wrapper over [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html).
17
///
18
/// The error number is an integer number set by system calls and some libc
19
/// functions in case of error.
20
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21
pub struct Error(i32);
22
23
/// A specialized [Result](https://doc.rust-lang.org/std/result/enum.Result.html) type
24
/// for operations that can return `errno`.
25
///
26
/// This typedef is generally used to avoid writing out `errno::Error` directly and is
27
/// otherwise a direct mapping to `Result`.
28
pub type Result<T> = result::Result<T, Error>;
29
30
impl Error {
31
    /// Creates a new error from the given error number.
32
    ///
33
    /// # Arguments
34
    ///
35
    /// * `errno`: error number used for creating the `Error`.
36
    ///
37
    /// # Examples
38
    ///
39
    /// ```
40
    /// # extern crate libc;
41
    /// extern crate vmm_sys_util;
42
    /// #
43
    /// # use libc;
44
    /// use vmm_sys_util::errno::Error;
45
    ///
46
    /// let err = Error::new(libc::EIO);
47
    /// ```
48
0
    pub fn new(errno: i32) -> Error {
49
0
        Error(errno)
50
0
    }
51
52
    /// Returns the last occurred `errno` wrapped in an `Error`.
53
    ///
54
    /// Calling `Error::last()` is the equivalent of using
55
    /// [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html) in C/C++.
56
    /// The result of this function only has meaning after a libc call or syscall
57
    /// where `errno` was set.
58
    ///
59
    /// # Examples
60
    ///
61
    /// ```
62
    /// # extern crate libc;
63
    /// extern crate vmm_sys_util;
64
    /// #
65
    /// # use libc;
66
    /// # use std::fs::File;
67
    /// # use std::io::{self, Read};
68
    /// # use std::env::temp_dir;
69
    /// use vmm_sys_util::errno::Error;
70
    /// #
71
    /// // Reading from a file without permissions returns an error.
72
    /// let mut path = temp_dir();
73
    /// path.push("test");
74
    /// let mut file = File::create(path).unwrap();
75
    /// let mut buf: Vec<u8> = Vec::new();
76
    /// assert!(file.read_to_end(&mut buf).is_err());
77
    ///
78
    /// // Retrieve the error number of the previous operation using `Error::last()`:
79
    /// let read_err = Error::last();
80
    /// #[cfg(unix)]
81
    /// assert_eq!(read_err, Error::new(libc::EBADF));
82
    /// #[cfg(not(unix))]
83
    /// assert_eq!(read_err, Error::new(libc::EIO));
84
    /// ```
85
564
    pub fn last() -> Error {
86
        // It's safe to unwrap because this `Error` was constructed via `last_os_error`.
87
564
        Error(io::Error::last_os_error().raw_os_error().unwrap())
88
564
    }
89
90
    /// Returns the raw integer value (`errno`) corresponding to this Error.
91
    ///
92
    /// # Examples
93
    /// ```
94
    /// extern crate vmm_sys_util;
95
    /// use vmm_sys_util::errno::Error;
96
    ///
97
    /// let err = Error::new(13);
98
    /// assert_eq!(err.errno(), 13);
99
    /// ```
100
0
    pub fn errno(self) -> i32 {
101
0
        self.0
102
0
    }
103
}
104
105
impl Display for Error {
106
0
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
107
0
        io::Error::from_raw_os_error(self.0).fmt(f)
108
0
    }
109
}
110
111
impl std::error::Error for Error {}
112
113
impl From<io::Error> for Error {
114
0
    fn from(e: io::Error) -> Self {
115
0
        Error::new(e.raw_os_error().unwrap_or_default())
116
0
    }
117
}
118
119
impl From<Error> for io::Error {
120
0
    fn from(err: Error) -> io::Error {
121
0
        io::Error::from_raw_os_error(err.0)
122
0
    }
123
}
124
125
/// Returns the last `errno` as a [`Result`] that is always an error.
126
///
127
/// [`Result`]: type.Result.html
128
564
pub fn errno_result<T>() -> Result<T> {
129
564
    Err(Error::last())
130
564
}
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<vmm_sys_util::tempfile::TempFile>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<vmm_sys_util::unix::tempdir::TempDir>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<vmm_sys_util::linux::timerfd::TimerFd>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<libc::unix::linux_like::linux::gnu::b64::sigset_t>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<bool>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<i32>
vmm_sys_util::errno::errno_result::<()>
Line
Count
Source
128
564
pub fn errno_result<T>() -> Result<T> {
129
564
    Err(Error::last())
130
564
}
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<u64>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<core::option::Option<alloc::sync::Arc<virtio_devices::console::ConsoleResizer>>>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<std::fs::File>
Unexecuted instantiation: vmm_sys_util::errno::errno_result::<(std::fs::File, std::fs::File, std::path::PathBuf)>
131
132
#[cfg(test)]
133
mod tests {
134
    use super::*;
135
    use crate::tempfile::TempFile;
136
    use std::error::Error as _;
137
    use std::fs::OpenOptions;
138
    use std::io::{self, Read};
139
140
    #[test]
141
    pub fn test_errno() {
142
        #[cfg(unix)]
143
        let expected_errno = libc::EBADF;
144
        #[cfg(not(unix))]
145
        let expected_errno = libc::EIO;
146
147
        // try to read from a file without read permissions
148
        let temp_file = TempFile::new().unwrap();
149
        let path = temp_file.as_path().to_owned();
150
        // Drop temp_file so we can cleanly reuse path below.
151
        std::mem::drop(temp_file);
152
        let mut file = OpenOptions::new()
153
            .read(false)
154
            .write(true)
155
            .create(true)
156
            .truncate(true)
157
            .open(&path)
158
            .unwrap();
159
        let mut buf: Vec<u8> = Vec::new();
160
        assert!(file.read_to_end(&mut buf).is_err());
161
162
        // Test that errno_result returns Err and the error is the expected one.
163
        let last_err = errno_result::<i32>().unwrap_err();
164
        assert_eq!(last_err, Error::new(expected_errno));
165
166
        // Test that the inner value of `Error` corresponds to expected_errno.
167
        assert_eq!(last_err.errno(), expected_errno);
168
        assert!(last_err.source().is_none());
169
170
        // Test creating an `Error` from a `std::io::Error`.
171
        assert_eq!(last_err, Error::from(io::Error::last_os_error()));
172
173
        // Test that calling `last()` returns the same error as `errno_result()`.
174
        assert_eq!(last_err, Error::last());
175
176
        let last_err: io::Error = last_err.into();
177
        // Test creating a `std::io::Error` from an `Error`
178
        assert_eq!(io::Error::last_os_error().kind(), last_err.kind());
179
180
        assert!(std::fs::remove_file(&path).is_ok());
181
    }
182
183
    #[test]
184
    pub fn test_display() {
185
        // Test the display implementation.
186
        #[cfg(target_os = "linux")]
187
        assert_eq!(
188
            format!("{}", Error::new(libc::EBADF)),
189
            "Bad file descriptor (os error 9)"
190
        );
191
        #[cfg(not(unix))]
192
        assert_eq!(
193
            format!("{}", Error::new(libc::EIO)),
194
            "Access is denied. (os error 5)"
195
        );
196
    }
197
}