/*
 * Copyright (C) 2021 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.
 */

// `loopdevice` module provides `attach` and `detach` functions that are for attaching and
// detaching a regular file to and from a loop device. Note that
// `loopdev`(https://crates.io/crates/loopdev) is a public alternative to this. In-house
// implementation was chosen to make Android-specific changes (like the use of the new
// LOOP_CONFIGURE instead of the legacy LOOP_SET_FD + LOOP_SET_STATUS64 combo which is considerably
// slower than the former).

mod sys;

use anyhow::{Context, Result};
use data_model::DataInit;
use libc::O_DIRECT;
use std::fs::{File, OpenOptions};
use std::mem::size_of;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::{Path, PathBuf};
use std::thread;
use std::time::{Duration, Instant};

use crate::loopdevice::sys::*;
use crate::util::*;

// These are old-style ioctls, thus *_bad.
nix::ioctl_none_bad!(_loop_ctl_get_free, LOOP_CTL_GET_FREE);
nix::ioctl_write_ptr_bad!(_loop_configure, LOOP_CONFIGURE, loop_config);
#[cfg(test)]
nix::ioctl_none_bad!(_loop_clr_fd, LOOP_CLR_FD);

fn loop_ctl_get_free(ctrl_file: &File) -> Result<i32> {
    // SAFETY: this ioctl changes the state in kernel, but not the state in this process.
    // The returned device number is a global resource; not tied to this process. So, we don't
    // need to keep track of it.
    Ok(unsafe { _loop_ctl_get_free(ctrl_file.as_raw_fd()) }?)
}

fn loop_configure(device_file: &File, config: &loop_config) -> Result<i32> {
    // SAFETY: this ioctl changes the state in kernel, but not the state in this process.
    Ok(unsafe { _loop_configure(device_file.as_raw_fd(), config) }?)
}

#[cfg(test)]
fn loop_clr_fd(device_file: &File) -> Result<i32> {
    // SAFETY: this ioctl disassociates the loop device with `device_file`, where the FD will
    // remain opened afterward. The association itself is kept for open FDs.
    Ok(unsafe { _loop_clr_fd(device_file.as_raw_fd()) }?)
}

/// Creates a loop device and attach the given file at `path` as the backing store.
pub fn attach<P: AsRef<Path>>(
    path: P,
    offset: u64,
    size_limit: u64,
    direct_io: bool,
) -> Result<PathBuf> {
    // Attaching a file to a loop device can make a race condition; a loop device number obtained
    // from LOOP_CTL_GET_FREE might have been used by another thread or process. In that case the
    // subsequet LOOP_CONFIGURE ioctl returns with EBUSY. Try until it succeeds.
    //
    // Note that the timing parameters below are chosen rather arbitrarily. In practice (i.e.
    // inside Microdroid) we can't experience the race condition because `apkverity` is the only
    // user of /dev/loop-control at the moment. This loop is mostly for testing where multiple
    // tests run concurrently.
    const TIMEOUT: Duration = Duration::from_secs(1);
    const INTERVAL: Duration = Duration::from_millis(10);

    let begin = Instant::now();
    loop {
        match try_attach(&path, offset, size_limit, direct_io) {
            Ok(loop_dev) => return Ok(loop_dev),
            Err(e) => {
                if begin.elapsed() > TIMEOUT {
                    return Err(e);
                }
            }
        };
        thread::sleep(INTERVAL);
    }
}

#[cfg(not(target_os = "android"))]
const LOOP_DEV_PREFIX: &str = "/dev/loop";

#[cfg(target_os = "android")]
const LOOP_DEV_PREFIX: &str = "/dev/block/loop";

fn try_attach<P: AsRef<Path>>(
    path: P,
    offset: u64,
    size_limit: u64,
    direct_io: bool,
) -> Result<PathBuf> {
    // Get a free loop device
    wait_for_path(LOOP_CONTROL)?;
    let ctrl_file = OpenOptions::new()
        .read(true)
        .write(true)
        .open(LOOP_CONTROL)
        .context("Failed to open loop control")?;
    let num = loop_ctl_get_free(&ctrl_file).context("Failed to get free loop device")?;

    // Construct the loop_info64 struct
    let backing_file = OpenOptions::new()
        .read(true)
        .custom_flags(if direct_io { O_DIRECT } else { 0 })
        .open(&path)
        .context(format!("failed to open {:?}", path.as_ref()))?;
    // safe because the size of the array is the same as the size of the struct
    let mut config: loop_config =
        *DataInit::from_mut_slice(&mut [0; size_of::<loop_config>()]).unwrap();
    config.fd = backing_file.as_raw_fd() as u32;
    config.block_size = 4096;
    config.info.lo_offset = offset;
    config.info.lo_sizelimit = size_limit;
    config.info.lo_flags = Flag::LO_FLAGS_READ_ONLY;
    if direct_io {
        config.info.lo_flags.insert(Flag::LO_FLAGS_DIRECT_IO);
    }

    // Configure the loop device to attach the backing file
    let device_path = format!("{}{}", LOOP_DEV_PREFIX, num);
    wait_for_path(&device_path)?;
    let device_file = OpenOptions::new()
        .read(true)
        .write(true)
        .open(&device_path)
        .context(format!("failed to open {:?}", &device_path))?;
    loop_configure(&device_file, &config)
        .context(format!("Failed to configure {:?}", &device_path))?;

    Ok(PathBuf::from(device_path))
}

/// Detaches backing file from the loop device `path`.
#[cfg(test)]
pub fn detach<P: AsRef<Path>>(path: P) -> Result<()> {
    let device_file = OpenOptions::new().read(true).write(true).open(&path)?;
    loop_clr_fd(&device_file)?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use std::path::Path;

    fn create_empty_file(path: &Path, size: u64) {
        let f = File::create(path).unwrap();
        f.set_len(size).unwrap();
    }

    fn is_direct_io(dev: &Path) -> bool {
        let dio = Path::new("/sys/block").join(dev.file_name().unwrap()).join("loop/dio");
        "1" == fs::read_to_string(&dio).unwrap().trim()
    }

    #[test]
    fn attach_loop_device_with_dio() {
        let a_dir = tempfile::TempDir::new().unwrap();
        let a_file = a_dir.path().join("test");
        let a_size = 4096u64;
        create_empty_file(&a_file, a_size);
        let dev = attach(a_file, 0, a_size, /*direct_io*/ true).unwrap();
        scopeguard::defer! {
            detach(&dev).unwrap();
        }
        assert!(is_direct_io(&dev));
    }

    #[test]
    fn attach_loop_device_without_dio() {
        let a_dir = tempfile::TempDir::new().unwrap();
        let a_file = a_dir.path().join("test");
        let a_size = 4096u64;
        create_empty_file(&a_file, a_size);
        let dev = attach(a_file, 0, a_size, /*direct_io*/ false).unwrap();
        scopeguard::defer! {
            detach(&dev).unwrap();
        }
        assert!(!is_direct_io(&dev));
    }
}
