// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fs-management/mount.h>

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
#include <fs/client.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/fdio/limits.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/vfs.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>
#include <zircon/compiler.h>
#include <zircon/device/block.h>
#include <zircon/device/vfs.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <utility>

namespace {

using fbl::unique_fd;

zx_status_t MountFs(int fd, zx_handle_t root) {
    zx_status_t status;
    fzl::FdioCaller caller{fbl::unique_fd(fd)};
    zx_status_t io_status = fuchsia_io_DirectoryAdminMount(caller.borrow_channel(),
                                                           root, &status);
    caller.release().release();
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

void UnmountHandle(zx_handle_t root, bool wait_until_ready) {
    // We've entered a failure case where the filesystem process (which may or may not be alive)
    // had a *chance* to be spawned, but cannot be attached to a vnode (for whatever reason).
    // Rather than abandoning the filesystem process (maybe causing dirty bits to be set), give it a
    // chance to shutdown properly.
    //
    // The unmount process is a little atypical, since we're just sending a signal over a handle,
    // rather than detaching the mounted filesystem from the "parent" filesystem.
    vfs_unmount_handle(root, wait_until_ready ? ZX_TIME_INFINITE : 0);
}

// Performs the actual work of mounting a volume.
class Mounter {
public:
    // The mount point is either a path (to be created) or an existing fd.
    explicit Mounter(int fd) : path_(nullptr), fd_(fd) {}
    explicit Mounter(const char* path) : path_(path), fd_(-1) {}
    ~Mounter() {}

    // Mounts the given device.
    zx_status_t Mount(unique_fd device, disk_format_t format, const mount_options_t& options,
                      LaunchCallback cb);

    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Mounter);

private:
    zx_status_t PrepareHandles(unique_fd device);
    zx_status_t MakeDirAndMount(const mount_options_t& options);
    zx_status_t LaunchAndMount(LaunchCallback cb, const mount_options_t& options, const char** argv,
                               int argc);
    zx_status_t MountNativeFs(const char* binary, unique_fd device, const mount_options_t& options,
                              LaunchCallback cb);
    zx_status_t MountFat(unique_fd device, const mount_options_t& options, LaunchCallback cb);

    zx_handle_t root_ = ZX_HANDLE_INVALID;
    const char* path_;
    int fd_;
    uint32_t flags_ = 0; // Currently not used.
    size_t num_handles_ = 0;
    zx_handle_t handles_[2];
    uint32_t ids_[2];
};

// Initializes 'handles_' and 'ids_' with the root handle and block device handle.
zx_status_t Mounter::PrepareHandles(unique_fd device) {
    zx_handle_t mountee_handle;
    zx_status_t status = zx_channel_create(0, &mountee_handle, &root_);
    if (status != ZX_OK) {
        return status;
    }
    handles_[0] = mountee_handle;
    ids_[0] = PA_USER0;
    num_handles_ = 1;

    int device_fd = device.release();
    status = fdio_fd_transfer(device_fd, &handles_[1]);
    if (status != ZX_OK) {
        fprintf(stderr, "Failed to access device handle\n");
        zx_handle_close(mountee_handle);
        zx_handle_close(root_);
        device.reset(device_fd);
        return status;
    }
    ids_[1] = PA_HND(PA_FD, FS_FD_BLOCKDEVICE);
    num_handles_ = 2;
    return ZX_OK;
}

zx_status_t Mounter::MakeDirAndMount(const mount_options_t& options) {
    auto cleanup =
        fbl::MakeAutoCall([this, options]() { UnmountHandle(root_, options.wait_until_ready); });

    // Open the parent path as O_ADMIN, and sent the mkdir+mount command
    // to that directory.
    char parent_path[PATH_MAX];
    const char* name;
    strcpy(parent_path, path_);
    char* last_slash = strrchr(parent_path, '/');
    if (last_slash == NULL) {
        strcpy(parent_path, ".");
        name = path_;
    } else {
        *last_slash = '\0';
        name = last_slash + 1;
        if (*name == '\0') {
            return ZX_ERR_INVALID_ARGS;
        }
    }

    unique_fd parent(open(parent_path, O_RDONLY | O_DIRECTORY | O_ADMIN));
    if (!parent) {
        return ZX_ERR_IO;
    }

    cleanup.cancel();

    zx_status_t status;
    fzl::FdioCaller caller(std::move(parent));
    zx_status_t io_status = fuchsia_io_DirectoryAdminMountAndCreate(
            caller.borrow_channel(), root_, name, strlen(name), flags_, &status);
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

// Calls the 'launch callback' and mounts the remote handle to the target vnode, if successful.
zx_status_t Mounter::LaunchAndMount(LaunchCallback cb, const mount_options_t& options,
                                    const char** argv, int argc) {
    auto cleanup =
        fbl::MakeAutoCall([this, options]() { UnmountHandle(root_, options.wait_until_ready); });

    zx_status_t status = cb(argc, argv, handles_, ids_, num_handles_);
    if (status != ZX_OK) {
        return status;
    }

    if (options.wait_until_ready) {
        // Wait until the filesystem is ready to take incoming requests
        zx_signals_t observed;
        status = zx_object_wait_one(root_, ZX_USER_SIGNAL_0 | ZX_CHANNEL_PEER_CLOSED,
                                    ZX_TIME_INFINITE, &observed);
        if ((status != ZX_OK) || (observed & ZX_CHANNEL_PEER_CLOSED)) {
            status = (status != ZX_OK) ? status : ZX_ERR_BAD_STATE;
            return status;
        }
    }
    cleanup.cancel();

    // Install remote handle.
    if (options.create_mountpoint) {
        return MakeDirAndMount(options);
    }
    return MountFs(fd_, root_);
}

zx_status_t Mounter::MountNativeFs(const char* binary, unique_fd device,
                                   const mount_options_t& options, LaunchCallback cb) {
    zx_status_t status = PrepareHandles(std::move(device));
    if (status != ZX_OK) {
        return status;
    }

    if (options.verbose_mount) {
        printf("fs_mount: Launching %s\n", binary);
    }

    // 1. binary
    // 2. (optional) readonly
    // 3. (optional) verbose
    // 4. (optional) metrics
    // 5. command
    fbl::Vector<const char*> argv;
    argv.push_back(binary);
    if (options.readonly) {
        argv.push_back("--readonly");
    }
    if (options.verbose_mount) {
        argv.push_back("--verbose");
    }
    if (options.collect_metrics) {
        argv.push_back("--metrics");
    }
    if (options.enable_journal) {
        argv.push_back("--journal");
    }
    argv.push_back("mount");
    argv.push_back(nullptr);
    return LaunchAndMount(cb, options, argv.get(), static_cast<int>(argv.size() - 1));
}

zx_status_t Mounter::MountFat(unique_fd device, const mount_options_t& options, LaunchCallback cb) {
    zx_status_t status = PrepareHandles(std::move(device));
    if (status != ZX_OK) {
        return status;
    }

    if (options.verbose_mount) {
        printf("fs_mount: FAT not presently supported\n");
    }

    return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t Mounter::Mount(unique_fd device, disk_format_t format, const mount_options_t& options,
                           LaunchCallback cb) {
    switch (format) {
    case DISK_FORMAT_MINFS:
        return MountNativeFs("/boot/bin/minfs", std::move(device), options, cb);
    case DISK_FORMAT_BLOBFS:
        return MountNativeFs("/boot/bin/blobfs", std::move(device), options, cb);
    case DISK_FORMAT_FAT:
        return MountFat(std::move(device), options, cb);
    default:
        return ZX_ERR_NOT_SUPPORTED;
    }
}

} // namespace

const mount_options_t default_mount_options = {
    .readonly = false,
    .verbose_mount = false,
    .collect_metrics = false,
    .wait_until_ready = true,
    .create_mountpoint = false,
    .enable_journal = false,
};

const mkfs_options_t default_mkfs_options = {
    .fvm_data_slices = 1,
    .verbose = false,
};

const fsck_options_t default_fsck_options = {
    .verbose = false,
    .never_modify = false,
    .always_modify = false,
    .force = false,
    .apply_journal = false,
};

disk_format_t detect_disk_format(int fd) {
    if (lseek(fd, 0, SEEK_SET) != 0) {
        fprintf(stderr, "detect_disk_format: Cannot seek to start of device.\n");
        return DISK_FORMAT_UNKNOWN;
    }

    fuchsia_hardware_block_BlockInfo info;
    fzl::UnownedFdioCaller caller(fd);
    zx_status_t status;
    zx_status_t io_status = fuchsia_hardware_block_BlockGetInfo(caller.borrow_channel(), &status,
                                                                &info);
    if (io_status != ZX_OK || status != ZX_OK) {
        fprintf(stderr, "detect_disk_format: Could not acquire block device info\n");
        return DISK_FORMAT_UNKNOWN;
    }

    // We expect to read HEADER_SIZE bytes, but we may need to read
    // extra to read a multiple of the underlying block size.
    const size_t buffer_size = fbl::round_up(static_cast<size_t>(HEADER_SIZE),
                                             static_cast<size_t>(info.block_size));

    uint8_t data[buffer_size];
    if (read(fd, data, buffer_size) != static_cast<ssize_t>(buffer_size)) {
        fprintf(stderr, "detect_disk_format: Error reading block device.\n");
        return DISK_FORMAT_UNKNOWN;
    }

    if (!memcmp(data, fvm_magic, sizeof(fvm_magic))) {
        return DISK_FORMAT_FVM;
    }

    if (!memcmp(data, zxcrypt_magic, sizeof(zxcrypt_magic))) {
        return DISK_FORMAT_ZXCRYPT;
    }

    if (!memcmp(data + 0x200, gpt_magic, sizeof(gpt_magic))) {
        return DISK_FORMAT_GPT;
    }

    if (!memcmp(data, minfs_magic, sizeof(minfs_magic))) {
        return DISK_FORMAT_MINFS;
    }

    if (!memcmp(data, blobfs_magic, sizeof(blobfs_magic))) {
        return DISK_FORMAT_BLOBFS;
    }

    if ((data[510] == 0x55 && data[511] == 0xAA)) {
        if ((data[38] == 0x29 || data[66] == 0x29)) {
            // 0x55AA are always placed at offset 510 and 511 for FAT filesystems.
            // 0x29 is the Boot Signature, but it is placed at either offset 38 or
            // 66 (depending on FAT type).
            return DISK_FORMAT_FAT;
        }
        return DISK_FORMAT_MBR;
    }
    return DISK_FORMAT_UNKNOWN;
}

zx_status_t fmount(int device_fd, int mount_fd, disk_format_t df, const mount_options_t* options,
                   LaunchCallback cb) {
    Mounter mounter(mount_fd);
    return mounter.Mount(unique_fd(device_fd), df, *options, cb);
}

zx_status_t mount(int device_fd, const char* mount_path, disk_format_t df,
                  const mount_options_t* options, LaunchCallback cb) {
    if (!options->create_mountpoint) {
        // Open mountpoint; use it directly.
        unique_fd mount_point(open(mount_path, O_RDONLY | O_DIRECTORY | O_ADMIN));
        if (!mount_point) {
            return ZX_ERR_BAD_STATE;
        }
        return fmount(device_fd, mount_point.get(), df, options, cb);
    }

    Mounter mounter(mount_path);
    return mounter.Mount(unique_fd(device_fd), df, *options, cb);
}

zx_status_t fumount(int mount_fd) {
    zx_handle_t h;
    zx_status_t status;
    fzl::FdioCaller caller{fbl::unique_fd(mount_fd)};
    zx_status_t io_status = fuchsia_io_DirectoryAdminUnmountNode(caller.borrow_channel(),
                                                                 &status, &h);
    caller.release().release();
    if (io_status != ZX_OK) {
        return io_status;
    }
    zx::channel c(h);
    if (status != ZX_OK) {
        return status;
    }
    return vfs_unmount_handle(c.release(), ZX_TIME_INFINITE);
}

zx_status_t umount(const char* mount_path) {
    unique_fd fd(open(mount_path, O_DIRECTORY | O_NOREMOTE | O_ADMIN));
    if (!fd) {
        fprintf(stderr, "Could not open directory: %s\n", strerror(errno));
        return ZX_ERR_BAD_STATE;
    }
    zx_status_t status = fumount(fd.get());
    return status;
}
