// Copyright 2017 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 <dirent.h>
#include <fcntl.h>
#include <getopt.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include <blobfs/blobfs.h>
#include <blobfs/fsck.h>
#include <fbl/auto_call.h>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <fbl/vector.h>
#include <fs/vfs.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>
#include <trace-provider/provider.h>
#include <zircon/process.h>
#include <zircon/processargs.h>

#include <utility>

namespace {

int Mount(fbl::unique_fd fd, blobfs::MountOptions* options) {
    if (options->writability == blobfs::Writability::Writable) {
        fzl::UnownedFdioCaller caller(fd.get());

        fuchsia_hardware_block_BlockInfo block_info;
        zx_status_t status;
        zx_status_t io_status = fuchsia_hardware_block_BlockGetInfo(caller.borrow_channel(),
                                                                    &status, &block_info);
        if (io_status != ZX_OK) {
            status = io_status;
        }
        if (status != ZX_OK) {
            FS_TRACE_ERROR("blobfs: Unable to query block device, fd: %d status: 0x%x\n",
                           fd.get(), status);
            return -1;
        }
        if (block_info.flags & BLOCK_FLAG_READONLY) {
            FS_TRACE_WARN("blobfs: Mounting as read-only. WARNING: Journal will not be applied\n");
            options->writability = blobfs::Writability::ReadOnlyDisk;
        }
    }

    zx::channel root = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
    if (!root.is_valid()) {
        FS_TRACE_ERROR("blobfs: Could not access startup handle to mount point\n");
        return -1;
    }

    async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
    trace::TraceProvider provider(loop.dispatcher());
    auto loop_quit = [&loop]() {
        loop.Quit();
        FS_TRACE_WARN("blobfs: Unmounted\n");
    };
    if (blobfs::Mount(loop.dispatcher(), std::move(fd), *options, std::move(root),
                      std::move(loop_quit)) != ZX_OK) {
        return -1;
    }
    loop.Run();
    return ZX_OK;
}

int Mkfs(fbl::unique_fd fd, blobfs::MountOptions* options) {
    uint64_t block_count;
    if (blobfs::GetBlockCount(fd.get(), &block_count)) {
        fprintf(stderr, "blobfs: cannot find end of underlying device\n");
        return -1;
    }

    return blobfs::Mkfs(fd.get(), block_count);
}

int Fsck(fbl::unique_fd fd, blobfs::MountOptions* options) {
    fbl::unique_ptr<blobfs::Blobfs> blobfs;
    if (blobfs::Initialize(std::move(fd), *options, &blobfs) != ZX_OK) {
        return -1;
    }

    return blobfs::Fsck(std::move(blobfs), options->journal);
}

typedef int (*CommandFunction)(fbl::unique_fd fd, blobfs::MountOptions* options);

const struct {
    const char* name;
    CommandFunction func;
    const char* help;
} kCmds[] = {
    {"create", Mkfs, "initialize filesystem"},
    {"mkfs", Mkfs, "initialize filesystem"},
    {"check", Fsck, "check filesystem integrity"},
    {"fsck", Fsck, "check filesystem integrity"},
    {"mount", Mount, "mount filesystem"},
};

int usage() {
    fprintf(stderr,
            "usage: blobfs [ <options>* ] <command> [ <arg>* ]\n"
            "\n"
            "options: -r|--readonly  Mount filesystem read-only\n"
            "         -m|--metrics   Collect filesystem metrics\n"
            "         -j|--journal   Utilize the blobfs journal\n"
            "                        For fsck, the journal is replayed before verification\n"
            "         -h|--help      Display this message\n"
            "\n"
            "On Fuchsia, blobfs takes the block device argument by handle.\n"
            "This can make 'blobfs' commands hard to invoke from command line.\n"
            "Try using the [mkfs,fsck,mount,umount] commands instead\n"
            "\n");
    for (unsigned n = 0; n < (sizeof(kCmds) / sizeof(kCmds[0])); n++) {
        fprintf(stderr, "%9s %-10s %s\n", n ? "" : "commands:",
                kCmds[n].name, kCmds[n].help);
    }
    fprintf(stderr, "\n");
    return -1;
}

// Process options/commands and return open fd to device
int ProcessArgs(int argc, char** argv, CommandFunction* func, blobfs::MountOptions* options) {
    while (1) {
        static struct option opts[] = {
            {"readonly", no_argument, nullptr, 'r'},
            {"metrics", no_argument, nullptr, 'm'},
            {"journal", no_argument, nullptr, 'j'},
            {"help", no_argument, nullptr, 'h'},
            {nullptr, 0, nullptr, 0},
        };
        int opt_index;
        int c = getopt_long(argc, argv, "rmjh", opts, &opt_index);
        if (c < 0) {
            break;
        }
        switch (c) {
        case 'r':
            options->writability = blobfs::Writability::ReadOnlyFilesystem;
            break;
        case 'm':
            options->metrics = true;
            break;
        case 'j':
            options->journal = true;
            break;
        case 'h':
        default:
            return usage();
        }
    }

    argc -= optind;
    argv += optind;

    if (argc < 1) {
        return usage();
    }
    const char* command = argv[0];

    // Validate command
    for (unsigned i = 0; i < sizeof(kCmds) / sizeof(kCmds[0]); i++) {
        if (!strcmp(command, kCmds[i].name)) {
            *func = kCmds[i].func;
        }
    }

    if (*func == nullptr) {
        fprintf(stderr, "Unknown command: %s\n", command);
        return usage();
    }

    // Block device passed by handle
    return FS_FD_BLOCKDEVICE;
}
} // namespace

int main(int argc, char** argv) {
    CommandFunction func = nullptr;
    blobfs::MountOptions options;
    fbl::unique_fd fd(ProcessArgs(argc, argv, &func, &options));

    if (!fd) {
        return -1;
    }

    return func(std::move(fd), &options);
}
