/*
 * 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.
 */

use anyhow::Result;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::ffi::CStr;
use std::fs::OpenOptions;
use std::io;
use std::mem::MaybeUninit;
use std::option::Option;
use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::time::Duration;

use fuse::filesystem::{Context, DirEntry, DirectoryIterator, Entry, FileSystem, ZeroCopyWriter};
use fuse::mount::MountOption;

use crate::common::{divide_roundup, COMMON_PAGE_SIZE};
use crate::fsverity::FsverityChunkedFileReader;
use crate::reader::{ChunkedFileReader, ReadOnlyDataByChunk};
use crate::remote_file::{RemoteChunkedFileReader, RemoteFsverityMerkleTreeReader};

// We're reading the backing file by chunk, so setting the block size to be the same.
const BLOCK_SIZE: usize = COMMON_PAGE_SIZE as usize;

const DEFAULT_METADATA_TIMEOUT: std::time::Duration = Duration::from_secs(5);

pub type Inode = u64;
type Handle = u64;

type RemoteFsverityChunkedFileReader =
    FsverityChunkedFileReader<RemoteChunkedFileReader, RemoteFsverityMerkleTreeReader>;

// A debug only type where everything are stored as local files.
type FileBackedFsverityChunkedFileReader =
    FsverityChunkedFileReader<ChunkedFileReader, ChunkedFileReader>;

pub enum FileConfig {
    LocalVerifiedFile(FileBackedFsverityChunkedFileReader, u64),
    LocalUnverifiedFile(ChunkedFileReader, u64),
    RemoteVerifiedFile(RemoteFsverityChunkedFileReader, u64),
    RemoteUnverifiedFile(RemoteChunkedFileReader, u64),
}

struct AuthFs {
    /// Store `FileConfig`s using the `Inode` number as the search index.
    ///
    /// For further optimization to minimize the search cost, since Inode is integer, we may
    /// consider storing them in a Vec if we can guarantee that the numbers are small and
    /// consecutive.
    file_pool: BTreeMap<Inode, FileConfig>,

    /// Maximum bytes in the write transaction to the FUSE device. This limits the maximum size to
    /// a read request (including FUSE protocol overhead).
    max_write: u32,
}

impl AuthFs {
    pub fn new(file_pool: BTreeMap<Inode, FileConfig>, max_write: u32) -> AuthFs {
        AuthFs { file_pool, max_write }
    }

    fn get_file_config(&self, inode: &Inode) -> io::Result<&FileConfig> {
        self.file_pool.get(&inode).ok_or_else(|| io::Error::from_raw_os_error(libc::ENOENT))
    }
}

fn check_access_mode(flags: u32, mode: libc::c_int) -> io::Result<()> {
    if (flags & libc::O_ACCMODE as u32) == mode as u32 {
        Ok(())
    } else {
        Err(io::Error::from_raw_os_error(libc::EACCES))
    }
}

cfg_if::cfg_if! {
    if #[cfg(all(target_arch = "aarch64", target_pointer_width = "64"))] {
        fn blk_size() -> libc::c_int { BLOCK_SIZE as libc::c_int }
    } else {
        fn blk_size() -> libc::c_long { BLOCK_SIZE as libc::c_long }
    }
}

fn create_stat(ino: libc::ino_t, file_size: u64) -> io::Result<libc::stat64> {
    let mut st = unsafe { MaybeUninit::<libc::stat64>::zeroed().assume_init() };

    st.st_ino = ino;
    st.st_mode = libc::S_IFREG | libc::S_IRUSR | libc::S_IRGRP | libc::S_IROTH;
    st.st_dev = 0;
    st.st_nlink = 1;
    st.st_uid = 0;
    st.st_gid = 0;
    st.st_rdev = 0;
    st.st_size = libc::off64_t::try_from(file_size)
        .map_err(|_| io::Error::from_raw_os_error(libc::EFBIG))?;
    st.st_blksize = blk_size();
    // Per man stat(2), st_blocks is "Number of 512B blocks allocated".
    st.st_blocks = libc::c_longlong::try_from(divide_roundup(file_size, 512))
        .map_err(|_| io::Error::from_raw_os_error(libc::EFBIG))?;
    Ok(st)
}

/// An iterator that generates (offset, size) for a chunked read operation, where offset is the
/// global file offset, and size is the amount of read from the offset.
struct ChunkReadIter {
    remaining: usize,
    offset: u64,
}

impl ChunkReadIter {
    pub fn new(remaining: usize, offset: u64) -> Self {
        ChunkReadIter { remaining, offset }
    }
}

impl Iterator for ChunkReadIter {
    type Item = (u64, usize);

    fn next(&mut self) -> Option<Self::Item> {
        if self.remaining == 0 {
            return None;
        }
        let chunk_data_size =
            std::cmp::min(self.remaining, BLOCK_SIZE - (self.offset % BLOCK_SIZE as u64) as usize);
        let retval = (self.offset, chunk_data_size);
        self.offset += chunk_data_size as u64;
        self.remaining = self.remaining.saturating_sub(chunk_data_size);
        Some(retval)
    }
}

fn offset_to_chunk_index(offset: u64) -> u64 {
    offset / BLOCK_SIZE as u64
}

fn read_chunks<W: io::Write, T: ReadOnlyDataByChunk>(
    mut w: W,
    file: &T,
    file_size: u64,
    offset: u64,
    size: u32,
) -> io::Result<usize> {
    let remaining = file_size.saturating_sub(offset);
    let size_to_read = std::cmp::min(size as usize, remaining as usize);
    let total = ChunkReadIter::new(size_to_read, offset).try_fold(
        0,
        |total, (current_offset, planned_data_size)| {
            // TODO(victorhsieh): There might be a non-trivial way to avoid this copy. For example,
            // instead of accepting a buffer, the writer could expose the final destination buffer
            // for the reader to write to. It might not be generally applicable though, e.g. with
            // virtio transport, the buffer may not be continuous.
            let mut buf = [0u8; BLOCK_SIZE];
            let read_size = file.read_chunk(offset_to_chunk_index(current_offset), &mut buf)?;
            if read_size < planned_data_size {
                return Err(io::Error::from_raw_os_error(libc::ENODATA));
            }

            let begin = (current_offset % BLOCK_SIZE as u64) as usize;
            let end = begin + planned_data_size;
            let s = w.write(&buf[begin..end])?;
            if s != planned_data_size {
                return Err(io::Error::from_raw_os_error(libc::EIO));
            }
            Ok(total + s)
        },
    )?;

    Ok(total)
}

// No need to support enumerating directory entries.
struct EmptyDirectoryIterator {}

impl DirectoryIterator for EmptyDirectoryIterator {
    fn next(&mut self) -> Option<DirEntry> {
        None
    }
}

impl FileSystem for AuthFs {
    type Inode = Inode;
    type Handle = Handle;
    type DirIter = EmptyDirectoryIterator;

    fn max_buffer_size(&self) -> u32 {
        self.max_write
    }

    fn lookup(&self, _ctx: Context, _parent: Inode, name: &CStr) -> io::Result<Entry> {
        // Only accept file name that looks like an integrer. Files in the pool are simply exposed
        // by their inode number. Also, there is currently no directory structure.
        let num = name.to_str().map_err(|_| io::Error::from_raw_os_error(libc::EINVAL))?;
        // Normally, `lookup` is required to increase a reference count for the inode (while
        // `forget` will decrease it). It is not necessary here since the files are configured to
        // be static.
        let inode = num.parse::<Inode>().map_err(|_| io::Error::from_raw_os_error(libc::ENOENT))?;
        let st = match self.get_file_config(&inode)? {
            FileConfig::LocalVerifiedFile(_, file_size)
            | FileConfig::LocalUnverifiedFile(_, file_size)
            | FileConfig::RemoteUnverifiedFile(_, file_size)
            | FileConfig::RemoteVerifiedFile(_, file_size) => create_stat(inode, *file_size)?,
        };
        Ok(Entry {
            inode,
            generation: 0,
            attr: st,
            entry_timeout: DEFAULT_METADATA_TIMEOUT,
            attr_timeout: DEFAULT_METADATA_TIMEOUT,
        })
    }

    fn getattr(
        &self,
        _ctx: Context,
        inode: Inode,
        _handle: Option<Handle>,
    ) -> io::Result<(libc::stat64, Duration)> {
        Ok((
            match self.get_file_config(&inode)? {
                FileConfig::LocalVerifiedFile(_, file_size)
                | FileConfig::LocalUnverifiedFile(_, file_size)
                | FileConfig::RemoteUnverifiedFile(_, file_size)
                | FileConfig::RemoteVerifiedFile(_, file_size) => create_stat(inode, *file_size)?,
            },
            DEFAULT_METADATA_TIMEOUT,
        ))
    }

    fn open(
        &self,
        _ctx: Context,
        inode: Self::Inode,
        flags: u32,
    ) -> io::Result<(Option<Self::Handle>, fuse::sys::OpenOptions)> {
        // Since file handle is not really used in later operations (which use Inode directly),
        // return None as the handle..
        match self.get_file_config(&inode)? {
            FileConfig::LocalVerifiedFile(_, _) | FileConfig::RemoteVerifiedFile(_, _) => {
                check_access_mode(flags, libc::O_RDONLY)?;
                // Once verified, and only if verified, the file content can be cached. This is not
                // really needed for a local file, but is the behavior of RemoteVerifiedFile later.
                Ok((None, fuse::sys::OpenOptions::KEEP_CACHE))
            }
            FileConfig::LocalUnverifiedFile(_, _) | FileConfig::RemoteUnverifiedFile(_, _) => {
                check_access_mode(flags, libc::O_RDONLY)?;
                // Do not cache the content. This type of file is supposed to be verified using
                // dm-verity. The filesystem mount over dm-verity already is already cached, so use
                // direct I/O here to avoid double cache.
                Ok((None, fuse::sys::OpenOptions::DIRECT_IO))
            }
        }
    }

    fn read<W: io::Write + ZeroCopyWriter>(
        &self,
        _ctx: Context,
        inode: Inode,
        _handle: Handle,
        w: W,
        size: u32,
        offset: u64,
        _lock_owner: Option<u64>,
        _flags: u32,
    ) -> io::Result<usize> {
        match self.get_file_config(&inode)? {
            FileConfig::LocalVerifiedFile(file, file_size) => {
                read_chunks(w, file, *file_size, offset, size)
            }
            FileConfig::LocalUnverifiedFile(file, file_size) => {
                read_chunks(w, file, *file_size, offset, size)
            }
            FileConfig::RemoteVerifiedFile(file, file_size) => {
                read_chunks(w, file, *file_size, offset, size)
            }
            FileConfig::RemoteUnverifiedFile(file, file_size) => {
                read_chunks(w, file, *file_size, offset, size)
            }
        }
    }
}

/// Mount and start the FUSE instance. This requires CAP_SYS_ADMIN.
pub fn loop_forever(
    file_pool: BTreeMap<Inode, FileConfig>,
    mountpoint: &Path,
) -> Result<(), fuse::Error> {
    let max_read: u32 = 65536;
    let max_write: u32 = 65536;
    let dev_fuse = OpenOptions::new()
        .read(true)
        .write(true)
        .open("/dev/fuse")
        .expect("Failed to open /dev/fuse");

    fuse::mount(
        mountpoint,
        "authfs",
        libc::MS_NOSUID | libc::MS_NODEV,
        &[
            MountOption::FD(dev_fuse.as_raw_fd()),
            MountOption::RootMode(libc::S_IFDIR | libc::S_IXUSR | libc::S_IXGRP | libc::S_IXOTH),
            MountOption::AllowOther,
            MountOption::UserId(0),
            MountOption::GroupId(0),
            MountOption::MaxRead(max_read),
        ],
    )
    .expect("Failed to mount fuse");

    fuse::worker::start_message_loop(
        dev_fuse,
        max_write,
        max_read,
        AuthFs::new(file_pool, max_write),
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    fn collect_chunk_read_iter(remaining: usize, offset: u64) -> Vec<(u64, usize)> {
        ChunkReadIter::new(remaining, offset).collect::<Vec<_>>()
    }

    #[test]
    fn test_chunk_read_iter() {
        assert_eq!(collect_chunk_read_iter(4096, 0), [(0, 4096)]);
        assert_eq!(collect_chunk_read_iter(8192, 0), [(0, 4096), (4096, 4096)]);
        assert_eq!(collect_chunk_read_iter(8192, 4096), [(4096, 4096), (8192, 4096)]);

        assert_eq!(
            collect_chunk_read_iter(16384, 1),
            [(1, 4095), (4096, 4096), (8192, 4096), (12288, 4096), (16384, 1)]
        );

        assert_eq!(collect_chunk_read_iter(0, 0), []);
        assert_eq!(collect_chunk_read_iter(0, 100), []);
    }
}
