// Copyright 2019 Intel Corporation. All Rights Reserved.
//
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause

//! Structures, helpers, and type definitions for working with
//! [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html).

use std::fmt::{Display, Formatter};
use std::io;
use std::result;

/// Wrapper over [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html).
///
/// The error number is an integer number set by system calls and some libc
/// functions in case of error.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Error(i32);

/// A specialized [Result](https://doc.rust-lang.org/std/result/enum.Result.html) type
/// for operations that can return `errno`.
///
/// This typedef is generally used to avoid writing out `errno::Error` directly and is
/// otherwise a direct mapping to `Result`.
pub type Result<T> = result::Result<T, Error>;

impl Error {
    /// Creates a new error from the given error number.
    ///
    /// # Arguments
    ///
    /// * `errno`: error number used for creating the `Error`.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate libc;
    /// extern crate vmm_sys_util;
    /// #
    /// # use libc;
    /// use vmm_sys_util::errno::Error;
    ///
    /// let err = Error::new(libc::EIO);
    /// ```
    pub fn new(errno: i32) -> Error {
        Error(errno)
    }

    /// Returns the last occurred `errno` wrapped in an `Error`.
    ///
    /// Calling `Error::last()` is the equivalent of using
    /// [`errno`](http://man7.org/linux/man-pages/man3/errno.3.html) in C/C++.
    /// The result of this function only has meaning after a libc call or syscall
    /// where `errno` was set.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate libc;
    /// extern crate vmm_sys_util;
    /// #
    /// # use libc;
    /// # use std::fs::File;
    /// # use std::io::{self, Read};
    /// # use std::env::temp_dir;
    /// use vmm_sys_util::errno::Error;
    /// #
    /// // Reading from a file without permissions returns an error.
    /// let mut path = temp_dir();
    /// path.push("test");
    /// let mut file = File::create(path).unwrap();
    /// let mut buf: Vec<u8> = Vec::new();
    /// assert!(file.read_to_end(&mut buf).is_err());
    ///
    /// // Retrieve the error number of the previous operation using `Error::last()`:
    /// let read_err = Error::last();
    /// #[cfg(unix)]
    /// assert_eq!(read_err, Error::new(libc::EBADF));
    /// #[cfg(not(unix))]
    /// assert_eq!(read_err, Error::new(libc::EIO));
    /// ```
    pub fn last() -> Error {
        // It's safe to unwrap because this `Error` was constructed via `last_os_error`.
        Error(io::Error::last_os_error().raw_os_error().unwrap())
    }

    /// Returns the raw integer value (`errno`) corresponding to this Error.
    ///
    /// # Examples
    /// ```
    /// extern crate vmm_sys_util;
    /// use vmm_sys_util::errno::Error;
    ///
    /// let err = Error::new(13);
    /// assert_eq!(err.errno(), 13);
    /// ```
    pub fn errno(self) -> i32 {
        self.0
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        io::Error::from_raw_os_error(self.0).fmt(f)
    }
}

impl std::error::Error for Error {}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::new(e.raw_os_error().unwrap_or_default())
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        io::Error::from_raw_os_error(err.0)
    }
}

/// Returns the last `errno` as a [`Result`] that is always an error.
///
/// [`Result`]: type.Result.html
pub fn errno_result<T>() -> Result<T> {
    Err(Error::last())
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tempfile::TempFile;
    use std::error::Error as _;
    use std::fs::OpenOptions;
    use std::io::{self, Read};

    #[test]
    pub fn test_errno() {
        #[cfg(unix)]
        let expected_errno = libc::EBADF;
        #[cfg(not(unix))]
        let expected_errno = libc::EIO;

        // try to read from a file without read permissions
        let temp_file = TempFile::new().unwrap();
        let path = temp_file.as_path().to_owned();
        // Drop temp_file so we can cleanly reuse path below.
        std::mem::drop(temp_file);
        let mut file = OpenOptions::new()
            .read(false)
            .write(true)
            .create(true)
            .truncate(true)
            .open(&path)
            .unwrap();
        let mut buf: Vec<u8> = Vec::new();
        assert!(file.read_to_end(&mut buf).is_err());

        // Test that errno_result returns Err and the error is the expected one.
        let last_err = errno_result::<i32>().unwrap_err();
        assert_eq!(last_err, Error::new(expected_errno));

        // Test that the inner value of `Error` corresponds to expected_errno.
        assert_eq!(last_err.errno(), expected_errno);
        assert!(last_err.source().is_none());

        // Test creating an `Error` from a `std::io::Error`.
        assert_eq!(last_err, Error::from(io::Error::last_os_error()));

        // Test that calling `last()` returns the same error as `errno_result()`.
        assert_eq!(last_err, Error::last());

        let last_err: io::Error = last_err.into();
        // Test creating a `std::io::Error` from an `Error`
        assert_eq!(io::Error::last_os_error().kind(), last_err.kind());

        assert!(std::fs::remove_file(&path).is_ok());
    }

    #[test]
    pub fn test_display() {
        // Test the display implementation.
        #[cfg(target_os = "linux")]
        assert_eq!(
            format!("{}", Error::new(libc::EBADF)),
            "Bad file descriptor (os error 9)"
        );
        #[cfg(not(unix))]
        assert_eq!(
            format!("{}", Error::new(libc::EIO)),
            "Access is denied. (os error 5)"
        );
    }
}
