// 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 <memory>

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <fbl/auto_call.h>
#include <fbl/string.h>
#include <fbl/string_printf.h>
#include <fbl/unique_fd.h>
#include <fuchsia/device/c/fidl.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <fuchsia/hardware/ramdisk/c/fidl.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/watcher.h>
#include <lib/fzl/fdio.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <lib/zx/vmo.h>
#include <zircon/boot/image.h>
#include <zircon/device/block.h>
#include <zircon/device/vfs.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <ramdevice-client/ramdisk.h>

#define RAMCTL_DEV_PATH "/dev"
#define RAMCTL_PATH "misc/ramctl"
#define BLOCK_EXTENSION "block"

static zx_status_t driver_watcher_cb(int dirfd, int event, const char* fn, void* cookie) {
    char* wanted = static_cast<char*>(cookie);
    if (event == WATCH_EVENT_ADD_FILE && strcmp(fn, wanted) == 0) {
        return ZX_ERR_STOP;
    }
    return ZX_OK;
}

static zx_status_t wait_for_device_impl(int dir_fd, char* path, const zx::time& deadline) {
    zx_status_t rc;

    // Peel off last path segment
    char* sep = strrchr(path, '/');
    if (path[0] == '\0' || (!sep)) {
        fprintf(stderr, "invalid device path '%s'\n", path);
        return ZX_ERR_BAD_PATH;
    }
    char* last = sep + 1;

    *sep = '\0';
    auto restore_path = fbl::MakeAutoCall([sep] { *sep = '/'; });

    // Recursively check the path up to this point
    struct stat buf;
    if (fstatat(dir_fd, path, &buf, 0) != 0 &&
        (rc = wait_for_device_impl(dir_fd, path, deadline)) != ZX_OK) {
        fprintf(stderr, "failed to bind '%s': %s\n", path, zx_status_get_string(rc));
        return rc;
    }

    // Early exit if this segment is empty
    if (last[0] == '\0') {
        return ZX_OK;
    }

    // Open the parent directory
    fbl::unique_fd parent_dir(openat(dir_fd, path, O_RDONLY | O_DIRECTORY));
    if (!parent_dir) {
        fprintf(stderr, "unable to open '%s'\n", path);
        return ZX_ERR_NOT_FOUND;
    }

    // Wait for the next path segment to show up
    rc = fdio_watch_directory(parent_dir.get(), driver_watcher_cb, deadline.get(), last);
    if (rc != ZX_ERR_STOP) {
        fprintf(stderr, "error when waiting for '%s': %s\n", last, zx_status_get_string(rc));
        return rc;
    }

    return ZX_OK;
}

zx_status_t wait_for_device_at(int dirfd, const char* path, zx_duration_t timeout) {
    if (!path || timeout == 0) {
        fprintf(stderr, "invalid args: path='%s', timeout=%" PRIu64 "\n", path, timeout);
        return ZX_ERR_INVALID_ARGS;
    }

    // Make a mutable copy
    char tmp[PATH_MAX];
    snprintf(tmp, sizeof(tmp), "%s", path);
    zx::time deadline = zx::deadline_after(zx::duration(timeout));
    return wait_for_device_impl(dirfd, tmp, deadline);
}

struct ramdisk_client {
public:
    DISALLOW_COPY_ASSIGN_AND_MOVE(ramdisk_client);

    static zx_status_t Create(int dev_root_fd, const char* instance_name,
                              zx::duration duration,
                              std::unique_ptr<ramdisk_client>* out) {
        fbl::String ramdisk_path = fbl::StringPrintf("%s/%s", RAMCTL_PATH, instance_name);
        fbl::String block_path = fbl::String::Concat({ramdisk_path, "/", BLOCK_EXTENSION});
        fbl::String path;
        fbl::unique_fd dirfd;
        if (dev_root_fd > -1) {
            dirfd.reset(dup(dev_root_fd));
            path = block_path;
        } else {
            dirfd.reset(open(RAMCTL_DEV_PATH, O_RDONLY | O_DIRECTORY));
            path = fbl::String::Concat({RAMCTL_DEV_PATH, "/", block_path});
        }
        if (!dirfd) {
            return ZX_ERR_BAD_STATE;
        }
        fbl::unique_fd ramdisk_fd(openat(dirfd.get(), ramdisk_path.c_str(), O_RDWR));
        if (!ramdisk_fd) {
            return ZX_ERR_BAD_STATE;
        }
        zx_handle_t ramdisk_interface_raw;
        zx_status_t status = fdio_get_service_handle(ramdisk_fd.release(), &ramdisk_interface_raw);
        if (status != ZX_OK) {
            return status;
        }
        zx::channel ramdisk_interface(ramdisk_interface_raw);

        // If binding to the block interface fails, ensure we still try to tear down the
        // ramdisk driver.
        auto cleanup = fbl::MakeAutoCall([&ramdisk_interface]() {
            ramdisk_client::DestroyByHandle(std::move(ramdisk_interface));
        });

        status = wait_for_device_at(dirfd.get(), block_path.c_str(), duration.get());
        if (status != ZX_OK) {
            return status;
        }
        fbl::unique_fd block_fd(openat(dirfd.get(), block_path.c_str(), O_RDWR));
        if (!block_fd) {
            return ZX_ERR_BAD_STATE;
        }
        cleanup.cancel();
        *out = std::unique_ptr<ramdisk_client>(
            new ramdisk_client(std::move(path), std::move(block_path),
                               std::move(ramdisk_interface), std::move(dirfd),
                               std::move(block_fd)));
        return ZX_OK;
    }

    zx_status_t Rebind() {
        fzl::FdioCaller disk_client(std::move(block_fd_));
        zx_status_t io_status, status;
        io_status = fuchsia_hardware_block_BlockRebindDevice(disk_client.borrow_channel(),
                                                             &status);
        if (io_status != ZX_OK) {
            return io_status;
        } else if (status != ZX_OK) {
            return status;
        }
        ramdisk_interface_.reset();

        // Ramdisk paths have the form: /dev/.../ramctl/ramdisk-xxx/block.
        // To rebind successfully, first, we rebind the "ramdisk-xxx" path,
        // and then we wait for "block" to rebind.

        // Wait for the "ramdisk-xxx" path to rebind.
        const char* sep = strrchr(relative_path_.c_str(), '/');
        char ramdisk_path[PATH_MAX];
        strlcpy(ramdisk_path, relative_path_.c_str(), sep - relative_path_.c_str() + 1);
        status = wait_for_device_impl(dev_root_fd_.get(), ramdisk_path,
                                      zx::deadline_after(zx::sec(3)));
        if (status != ZX_OK) {
            return status;
        }

        fbl::unique_fd ramdisk_fd(openat(dev_root_fd_.get(), ramdisk_path, O_RDWR));
        if (!ramdisk_fd) {
            return ZX_ERR_BAD_STATE;
        }

        zx_handle_t ramdisk_interface;
        status = fdio_get_service_handle(ramdisk_fd.release(), &ramdisk_interface);
        if (status != ZX_OK) {
            return status;
        }
        ramdisk_interface_.reset(ramdisk_interface);

        // Wait for the "block" path to rebind.
        strlcpy(ramdisk_path, relative_path_.c_str(), sizeof(ramdisk_path));
        status = wait_for_device_impl(dev_root_fd_.get(), ramdisk_path,
                                      zx::deadline_after(zx::sec(3)));
        if (status != ZX_OK) {
            return status;
        }
        block_fd_.reset(openat(dev_root_fd_.get(), relative_path_.c_str(), O_RDWR));
        if (!block_fd_) {
            return ZX_ERR_BAD_STATE;
        }
        return ZX_OK;
    }

    zx_status_t Destroy() {
        if (!ramdisk_interface_) {
            return ZX_ERR_BAD_STATE;
        }

        zx_status_t status = DestroyByHandle(std::move(ramdisk_interface_));
        if (status != ZX_OK) {
            return status;
        }
        block_fd_.reset();
        return ZX_OK;
    }

    const zx::channel& ramdisk_interface() const { return ramdisk_interface_; }

    const fbl::unique_fd& block_fd() const { return block_fd_; }

    const fbl::String& path() const { return path_; }

    ~ramdisk_client() { Destroy(); }

private:
    ramdisk_client(fbl::String path, fbl::String relative_path, zx::channel ramdisk_interface,
                   fbl::unique_fd dev_root_fd, fbl::unique_fd block_fd)
        : path_(std::move(path)), relative_path_(relative_path),
          ramdisk_interface_(std::move(ramdisk_interface)), dev_root_fd_(std::move(dev_root_fd)),
          block_fd_(std::move(block_fd)) {}

    static zx_status_t DestroyByHandle(zx::channel ramdisk) {
        zx_status_t call_status;
        zx_status_t status = fuchsia_device_ControllerUnbind(ramdisk.get(), &call_status);
        if (status != ZX_OK) {
            return status;
        }
        return call_status;
    }

    // The fully qualified path.
    fbl::String path_;
    // The path relative to dev_root_fd_.
    fbl::String relative_path_;
    zx::channel ramdisk_interface_;
    fbl::unique_fd dev_root_fd_;
    fbl::unique_fd block_fd_;
};

// TODO(aarongreen): This is more generic than just fs-management, or even block devices.  Move this
// (and its tests) out of ramdisk and to somewhere else?
zx_status_t wait_for_device(const char* path, zx_duration_t timeout) {
    return wait_for_device_at(/*dirfd=*/-1, path, timeout);
}

static zx_status_t open_ramctl(int dev_root_fd, zx::channel* out_ramctl) {
    fbl::unique_fd dirfd;
    if (dev_root_fd > -1) {
        dirfd.reset(dup(dev_root_fd));
    } else {
        dirfd.reset(open(RAMCTL_DEV_PATH, O_RDONLY | O_DIRECTORY));
    }
    if (!dirfd) {
        return ZX_ERR_BAD_STATE;
    }
    fbl::unique_fd fd(openat(dirfd.get(), RAMCTL_PATH, O_RDWR));
    if (!fd) {
        return ZX_ERR_BAD_STATE;
    }

    zx_handle_t ramctl_interface_raw;
    zx_status_t status = fdio_get_service_handle(fd.release(), &ramctl_interface_raw);
    if (status != ZX_OK) {
        return status;
    }

    out_ramctl->reset(ramctl_interface_raw);
    return ZX_OK;
}

static const fuchsia_hardware_ramdisk_GUID* fidl_guid(const uint8_t* type_guid) {
    static_assert(sizeof(fuchsia_hardware_ramdisk_GUID) == ZBI_PARTITION_GUID_LEN,
                  "Byte array cannot be reinterpreted as FIDL GUID");
    return reinterpret_cast<const fuchsia_hardware_ramdisk_GUID*>(type_guid);
}

static zx_status_t ramdisk_create_with_guid_internal(int dev_root_fd, uint64_t blk_size,
                                                     uint64_t blk_count, const uint8_t* type_guid,
                                                     ramdisk_client** out) {
    zx::channel ramctl;
    zx_status_t status = open_ramctl(dev_root_fd, &ramctl);
    if (status != ZX_OK) {
        return status;
    }

    char name[fuchsia_hardware_ramdisk_MAX_NAME_LENGTH + 1];
    size_t name_len = 0;
    zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskControllerCreate(
        ramctl.get(), blk_size, blk_count, fidl_guid(type_guid), &status, name, sizeof(name) - 1,
        &name_len);
    if (io_status != ZX_OK) {
        return io_status;
    } else if (status != ZX_OK) {
        return status;
    }

    // Always force 'name' to be null-terminated.
    name[name_len] = '\0';

    std::unique_ptr<ramdisk_client> client;
    status = ramdisk_client::Create(dev_root_fd, name, zx::sec(3), &client);
    if (status != ZX_OK) {
        return status;
    }
    *out = client.release();
    return ZX_OK;
}

zx_status_t ramdisk_create_at(int dev_root_fd, uint64_t blk_size, uint64_t blk_count,
                              ramdisk_client** out) {
    return ramdisk_create_with_guid_internal(dev_root_fd, blk_size, blk_count, nullptr, out);
}

zx_status_t ramdisk_create(uint64_t blk_size, uint64_t blk_count, ramdisk_client** out) {
    return ramdisk_create_at(/*dev_root_fd=*/-1, blk_size, blk_count, out);
}

zx_status_t ramdisk_create_with_guid(uint64_t blk_size, uint64_t blk_count,
                                     const uint8_t* type_guid, size_t guid_len,
                                     ramdisk_client** out) {
    return ramdisk_create_at_with_guid(/*dev_root_fd=*/-1, blk_size, blk_count, type_guid, guid_len, out);
}

zx_status_t ramdisk_create_at_with_guid(int dev_root_fd, uint64_t blk_size, uint64_t blk_count,
                                        const uint8_t* type_guid, size_t guid_len,
                                        ramdisk_client** out) {
    if (type_guid == nullptr || guid_len < ZBI_PARTITION_GUID_LEN) {
        return ZX_ERR_INVALID_ARGS;
    }
    return ramdisk_create_with_guid_internal(dev_root_fd, blk_size, blk_count, type_guid, out);
}

zx_status_t ramdisk_create_from_vmo(zx_handle_t raw_vmo, ramdisk_client** out) {
    return ramdisk_create_at_from_vmo(/*dev_root_fd=*/-1, raw_vmo, out);
}

zx_status_t ramdisk_create_at_from_vmo(int dev_root_fd, zx_handle_t raw_vmo, ramdisk_client** out) {
    zx::vmo vmo(raw_vmo);
    zx::channel ramctl;
    zx_status_t status = open_ramctl(dev_root_fd, &ramctl);
    if (status != ZX_OK) {
        return status;
    }

    char name[fuchsia_hardware_ramdisk_MAX_NAME_LENGTH + 1];
    size_t name_len = 0;
    zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskControllerCreateFromVmo(
        ramctl.get(), vmo.release(), &status, name, sizeof(name) - 1, &name_len);
    if (io_status != ZX_OK) {
        return io_status;
    } else if (status != ZX_OK) {
        return status;
    }

    // Always force 'name' to be null-terminated.
    name[name_len] = '\0';

    std::unique_ptr<ramdisk_client> client;
    status = ramdisk_client::Create(dev_root_fd, name, zx::sec(3), &client);
    if (status != ZX_OK) {
        return status;
    }
    *out = client.release();
    return ZX_OK;
}

int ramdisk_get_block_fd(const ramdisk_client_t* client) {
    return client->block_fd().get();
}

const char* ramdisk_get_path(const ramdisk_client_t* client) {
    return client->path().c_str();
}

zx_status_t ramdisk_sleep_after(const ramdisk_client* client, uint64_t block_count) {
    zx_status_t status;
    zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskSleepAfter(
        client->ramdisk_interface().get(), block_count, &status);
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

zx_status_t ramdisk_wake(const ramdisk_client* client) {
    zx_status_t status;
    zx_status_t io_status =
        fuchsia_hardware_ramdisk_RamdiskWake(client->ramdisk_interface().get(), &status);
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

zx_status_t ramdisk_grow(const ramdisk_client* client, uint64_t required_size) {
    zx_status_t status;
    zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskGrow(
        client->ramdisk_interface().get(), required_size, &status);
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

zx_status_t ramdisk_set_flags(const ramdisk_client* client, uint32_t flags) {
    zx_status_t status;
    zx_status_t io_status =
        fuchsia_hardware_ramdisk_RamdiskSetFlags(client->ramdisk_interface().get(), flags, &status);
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

zx_status_t ramdisk_get_block_counts(const ramdisk_client* client,
                                     ramdisk_block_write_counts_t* out_counts) {
    static_assert(sizeof(ramdisk_block_write_counts_t) ==
                      sizeof(fuchsia_hardware_ramdisk_BlockWriteCounts),
                  "Cannot convert between C library / FIDL block counts");

    zx_status_t status;
    zx_status_t io_status = fuchsia_hardware_ramdisk_RamdiskGetBlockCounts(
        client->ramdisk_interface().get(), &status,
        reinterpret_cast<fuchsia_hardware_ramdisk_BlockWriteCounts*>(out_counts));
    if (io_status != ZX_OK) {
        return io_status;
    }
    return status;
}

zx_status_t ramdisk_rebind(ramdisk_client_t* client) {
    return client->Rebind();
}

zx_status_t ramdisk_destroy(ramdisk_client* client) {
    zx_status_t status = client->Destroy();
    delete client;
    return status;
}
