// 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 <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>

#include <bootdata/decompress.h>
#include <fbl/unique_fd.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/watcher.h>
#include <lib/fit/defer.h>
#include <lib/zx/channel.h>
#include <lib/zx/event.h>
#include <loader-service/loader-service.h>
#include <ramdevice-client/ramdisk.h>
#include <zircon/device/vfs.h>
#include <zircon/dlfcn.h>
#include <zircon/processargs.h>
#include <zircon/status.h>

#include "../shared/env.h"

#include "block-watcher.h"
#include "fs-manager.h"

namespace devmgr {
namespace {

zx_status_t MiscDeviceAdded(int dirfd, int event, const char* fn, void* cookie) {
    if (event != WATCH_EVENT_ADD_FILE || strcmp(fn, "ramctl") != 0) {
        return ZX_OK;
    }

    zx::vmo ramdisk_vmo = std::move(*static_cast<zx::vmo*>(cookie));
    size_t size;
    zx_status_t status = ramdisk_vmo.get_size(&size);
    if (status != ZX_OK) {
        return ZX_ERR_STOP;
    }

    const char* errmsg;
    zx::vmo vmo;
    status = decompress_bootdata(zx_vmar_root_self(), ramdisk_vmo.get(), 0, size,
                                 vmo.reset_and_get_address(), &errmsg);
    if (status != ZX_OK) {
        printf("fshost: failed to decompress ramdisk: %s\n", errmsg);
        return ZX_ERR_STOP;
    }

    ramdisk_client* client;
    status = ramdisk_create_from_vmo(vmo.release(), &client);
    if (status != ZX_OK) {
        printf("fshost: failed to create ramdisk from BOOTDATA_RAMDISK\n");
    } else {
        printf("fshost: BOOTDATA_RAMDISK attached\n");
    }
    return ZX_ERR_STOP;
}

int RamctlWatcher(void* arg) {
    fbl::unique_fd dirfd(open("/dev/misc", O_DIRECTORY | O_RDONLY));
    if (!dirfd) {
        printf("fshost: failed to open /dev/misc: %s\n", strerror(errno));
        return -1;
    }
    fdio_watch_directory(dirfd.get(), &MiscDeviceAdded, ZX_TIME_INFINITE, arg);
    return 0;
}

// Setup the loader service to be used by all processes spawned by devmgr.
void setup_loader_service(zx::channel devmgr_loader) {
    loader_service_t* svc;
    zx_status_t status = loader_service_create_fs(nullptr, &svc);
    ;
    if (status != ZX_OK) {
        fprintf(stderr, "fshost: failed to create loader service %d\n", status);
    }
    auto defer = fit::defer([svc] { loader_service_release(svc); });
    status = loader_service_attach(svc, devmgr_loader.release());
    if (status != ZX_OK) {
        fprintf(stderr, "fshost: failed to attach to loader service: %d\n", status);
        return;
    }
    zx_handle_t fshost_loader;
    status = loader_service_connect(svc, &fshost_loader);
    if (status != ZX_OK) {
        fprintf(stderr, "fshost: failed to connect to loader service: %d\n", status);
        return;
    }
    zx_handle_close(dl_set_loader_service(fshost_loader));
}

// Initialize the fshost namespace.
//
// |fs_root_client| is mapped to "/fs", and represents the filesystem of devmgr.
zx_status_t BindNamespace(zx::channel fs_root_client) {
    fdio_ns_t* ns;
    zx_status_t status;
    if ((status = fdio_ns_get_installed(&ns)) != ZX_OK) {
        printf("fshost: cannot get namespace: %d\n", status);
        return status;
    }

    // Bind "/fs".
    if ((status = fdio_ns_bind(ns, "/fs", fs_root_client.release())) != ZX_OK) {
        printf("fshost: cannot bind /fs to namespace: %d\n", status);
        return status;
    }

    // Bind "/system".
    {
        zx::channel client, server;
        if ((status = zx::channel::create(0, &client, &server)) != ZX_OK) {
            return status;
        }
        if ((status = fdio_open("/fs/system", ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_ADMIN,
                                server.release())) != ZX_OK) {
            printf("fshost: cannot open connection to /system: %d\n", status);
            return status;
        }
        if ((status = fdio_ns_bind(ns, "/system", client.release())) != ZX_OK) {
            printf("fshost: cannot bind /system to namespace: %d\n", status);
            return status;
        }
    }
    return ZX_OK;
}

} // namespace
} // namespace devmgr

int main(int argc, char** argv) {
    bool netboot = false;
    bool disable_block_watcher = false;

    enum {
        kNetboot,
        kDisableBlockWatcher,
    };
    option options[] = {
        {"netboot", no_argument, nullptr, kNetboot},
        {"disable-block-watcher", no_argument, nullptr, kDisableBlockWatcher},
    };

    int opt;
    while ((opt = getopt_long(argc, argv, "", options, nullptr)) != -1) {
        switch (opt) {
        case kNetboot:
            netboot = true;
            break;
        case kDisableBlockWatcher:
            disable_block_watcher = true;
            break;
        }
    }

    zx::channel fs_root_server(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
    zx::channel devmgr_loader(zx_take_startup_handle(PA_HND(PA_USER0, 2)));
    zx::channel fshost_export_server(zx_take_startup_handle(PA_HND(PA_USER0, 3)));
    zx::event fshost_event(zx_take_startup_handle(PA_HND(PA_USER1, 0)));

    // First, initialize the local filesystem in isolation.
    fbl::unique_ptr<devmgr::FsManager> fs_manager;
    zx_status_t status = devmgr::FsManager::Create(std::move(fshost_event), &fs_manager);
    if (status != ZX_OK) {
        printf("fshost: Cannot create FsManager\n");
        return status;
    }

    // First, begin serving the "fs_root" on behalf of devmgr.
    status = fs_manager->ServeRoot(std::move(fs_root_server));
    if (status != ZX_OK) {
        printf("fshost: Cannot serve devmgr's root filesystem\n");
        return status;
    }
    status = fs_manager->ServeFshostRoot(std::move(fshost_export_server));
    if (status != ZX_OK) {
        printf("fshost: Cannot serve export directory\n");
        return status;
    }

    // Now that we are serving the fs_root, acquire a new connection
    // to place in our own namespace.
    zx::channel fs_root_client;
    status = zx::channel::create(0, &fs_root_client, &fs_root_server);
    if (status != ZX_OK) {
        return ZX_OK;
    }
    status = fs_manager->ServeRoot(std::move(fs_root_server));
    if (status != ZX_OK) {
        printf("fshost: Cannot serve devmgr's root filesystem\n");
        return status;
    }


    // Initialize namespace, and begin monitoring the |fshost_event| for a termination event.
    status = devmgr::BindNamespace(std::move(fs_root_client));
    if (status != ZX_OK) {
        printf("fshost: cannot bind namespace\n");
        return status;
    }
    fs_manager->WatchExit();

    // Setup the devmgr loader service.
    devmgr::setup_loader_service(std::move(devmgr_loader));

    // If there is a ramdisk, setup the ramctl filesystems.
    zx::vmo ramdisk_vmo(zx_take_startup_handle(PA_HND(PA_VMO_BOOTDATA, 0)));
    if (ramdisk_vmo.is_valid()) {
        thrd_t t;
        int err = thrd_create_with_name(&t, &devmgr::RamctlWatcher, &ramdisk_vmo, "ramctl-filesystems");
        if (err != thrd_success) {
            printf("fshost: failed to start ramctl-filesystems: %d\n", err);
        }
        thrd_detach(t);
    }

    if (!disable_block_watcher) {
        bool check_filesystems = devmgr::getenv_bool("zircon.system.filesystem-check", false);
        BlockDeviceWatcher(std::move(fs_manager), netboot, check_filesystems);
    } else {
        // Keep the process alive so that the loader service continues to be supplied
        // to the devmgr. Otherwise the devmgr will segfault.
        zx::nanosleep(zx::time::infinite());
    }
    printf("fshost: terminating (block device filesystems finished?)\n");
    return 0;
}
