// Copyright 2024, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! This module implements zram setup functionality.
//!
//! The setup implemented in this module assumes that the zram kernel module has been loaded early on init with only 1 zram device (`zram0`).
//!
//! zram kernel documentation https://docs.kernel.org/admin-guide/blockdev/zram.html

#[cfg(test)]
mod tests;

use std::io;

use crate::os::get_page_count;
use crate::os::get_page_size;
use crate::zram::SysfsZramApi;

const MKSWAP_BIN_PATH: &str = "/system/bin/mkswap";
const ZRAM_DEVICE_PATH: &str = "/dev/block/zram0";
const PROC_SWAPS_PATH: &str = "/proc/swaps";

const MAX_ZRAM_PERCENTAGE_ALLOWED: u64 = 500;

/// [SetupApi] is the mockable interface for swap operations.
#[cfg_attr(test, mockall::automock)]
pub trait SetupApi {
    /// Set up zram swap device, returning whether the command succeeded and its output.
    fn mkswap(device_path: &str) -> io::Result<std::process::Output>;
    /// Specify the zram swap device.
    fn swapon(device_path: &std::ffi::CStr) -> io::Result<()>;
    /// Read swaps areas in use.
    fn read_swap_areas() -> io::Result<String>;
}

/// The implementation of [SetupApi].
pub struct SetupApiImpl;

impl SetupApi for SetupApiImpl {
    fn mkswap(device_path: &str) -> io::Result<std::process::Output> {
        std::process::Command::new(MKSWAP_BIN_PATH).arg(device_path).output()
    }

    fn swapon(device_path: &std::ffi::CStr) -> io::Result<()> {
        // SAFETY: device_path is a nul-terminated string.
        let res = unsafe { libc::swapon(device_path.as_ptr(), 0) };
        if res == 0 {
            Ok(())
        } else {
            Err(std::io::Error::last_os_error())
        }
    }

    fn read_swap_areas() -> io::Result<String> {
        std::fs::read_to_string(PROC_SWAPS_PATH)
    }
}

/// Whether or not zram is already set up on the device.
pub fn is_zram_swap_activated<S: SetupApi>() -> io::Result<bool> {
    let swaps = S::read_swap_areas()?;
    // Skip the first line which is header.
    let swap_lines = swaps.lines().skip(1);
    // Swap is turned on if swap file contains entry with zram keyword.
    for line in swap_lines {
        if line.contains("zram") {
            return Ok(true);
        }
    }
    Ok(false)
}

/// Error from [parse_zram_size_spec].
#[derive(Debug, thiserror::Error)]
pub enum ZramSpecError {
    /// Zram size was not specified
    #[error("zram size is not specified")]
    EmptyZramSizeSpec,
    /// Zram size percentage needs to be between 1 and 500%
    #[error(
        "zram size percentage {0} is out of range (expected the between 1 and {MAX_ZRAM_PERCENTAGE_ALLOWED})"
    )]
    ZramPercentageOutOfRange(u64),
    /// Parsing zram size error
    #[error("zram size is not an int: {0}")]
    ParseZramSize(#[from] std::num::ParseIntError),
}

/// Parse zram size that can be specified by a percentage or an absolute value.
pub fn parse_zram_size_spec(spec: &str) -> Result<u64, ZramSpecError> {
    parse_size_spec_with_page_info(spec, get_page_size(), get_page_count())
}

fn parse_size_spec_with_page_info(
    spec: &str,
    system_page_size: u64,
    system_page_count: u64,
) -> Result<u64, ZramSpecError> {
    if spec.is_empty() {
        return Err(ZramSpecError::EmptyZramSizeSpec);
    }

    if let Some(percentage_str) = spec.strip_suffix('%') {
        let percentage = percentage_str.parse::<u64>()?;
        if percentage == 0 || percentage > MAX_ZRAM_PERCENTAGE_ALLOWED {
            return Err(ZramSpecError::ZramPercentageOutOfRange(percentage));
        }
        return Ok(system_page_count * percentage / 100 * system_page_size);
    }

    let zram_size = spec.parse::<u64>()?;
    Ok(zram_size)
}

/// Error from [activate].
#[derive(Debug, thiserror::Error)]
pub enum ZramActivationError {
    /// Failed to update zram disk size
    #[error("failed to write zram disk size: {0}")]
    UpdateZramDiskSize(std::io::Error),
    /// Failed to swapon
    #[error("swapon failed: {0}")]
    SwapOn(std::io::Error),
    /// Mkswap command failed
    #[error("failed to execute mkswap: {0}")]
    ExecuteMkSwap(std::io::Error),
    /// Mkswap command failed
    #[error("mkswap failed: {0:?}")]
    MkSwap(std::process::Output),
}

/// Set up a zram device with provided parameters.
pub fn activate_zram<Z: SysfsZramApi, S: SetupApi>(
    zram_size: u64,
) -> Result<(), ZramActivationError> {
    Z::write_disksize(&zram_size.to_string()).map_err(ZramActivationError::UpdateZramDiskSize)?;

    let output = S::mkswap(ZRAM_DEVICE_PATH).map_err(ZramActivationError::ExecuteMkSwap)?;
    if !output.status.success() {
        return Err(ZramActivationError::MkSwap(output));
    }

    let zram_device_path_cstring = std::ffi::CString::new(ZRAM_DEVICE_PATH)
        .expect("device path should have no nul characters");
    S::swapon(&zram_device_path_cstring).map_err(ZramActivationError::SwapOn)?;

    Ok(())
}
