vmm_sys_util/
syscall.rs

1// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: BSD-3-Clause
3
4//! Wrapper for interpreting syscall exit codes.
5
6use std::os::raw::c_int;
7
8/// Wrapper to interpret syscall exit codes and provide a rustacean `io::Result`.
9#[derive(Debug)]
10pub struct SyscallReturnCode<T: From<i8> + Eq = c_int>(pub T);
11
12impl<T: From<i8> + Eq> SyscallReturnCode<T> {
13    /// Returns the last OS error if value is -1 or Ok(value) otherwise.
14    pub fn into_result(self) -> std::io::Result<T> {
15        if self.0 == T::from(-1) {
16            Err(std::io::Error::last_os_error())
17        } else {
18            Ok(self.0)
19        }
20    }
21    /// Returns the last OS error if value is -1 or Ok(()) otherwise.
22    pub fn into_empty_result(self) -> std::io::Result<()> {
23        self.into_result().map(|_| ())
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    #[test]
32    fn test_syscall_ops() {
33        let mut syscall_code = SyscallReturnCode(1);
34        match syscall_code.into_result() {
35            Ok(_value) => (),
36            _ => unreachable!(),
37        }
38
39        syscall_code = SyscallReturnCode(-1);
40        assert!(syscall_code.into_result().is_err());
41
42        syscall_code = SyscallReturnCode(1);
43        match syscall_code.into_empty_result() {
44            Ok(()) => (),
45            _ => unreachable!(),
46        }
47
48        syscall_code = SyscallReturnCode(-1);
49        assert!(syscall_code.into_empty_result().is_err());
50
51        let mut syscall_code_long = SyscallReturnCode(1i64);
52        match syscall_code_long.into_result() {
53            Ok(_value) => (),
54            _ => unreachable!(),
55        }
56
57        syscall_code_long = SyscallReturnCode(-1i64);
58        assert!(syscall_code_long.into_result().is_err());
59    }
60}