// Copyright 2017, 2018 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <thread>
#include <unistd.h>
#include <vector>

#include <digest/digest.h>
#include <digest/merkle-tree.h>
#include <fbl/alloc_checker.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>

namespace {

using digest::Digest;
using digest::MerkleTree;

struct FileEntry {
    std::string filename;
    char digest[Digest::kLength * 2 + 1]{};
};

void usage(char** argv) {
    fprintf(stderr, "Usage: %s [-o OUTPUT | -m MANIFEST] FILE...\n", argv[0]);
    fprintf(stderr, "\n\
With -o, OUTPUT gets the same format normally written to stdout: HASH - FILE.\n\
With -m, MANIFEST gets \"manifest file\" format: HASH=FILE.\n\
Any argument may be \"@RSPFILE\" to be replaced with the contents of RSPFILE.\n\
");
    exit(1);
}

int handle_argument(char** argv, const char* arg,
                    std::vector<FileEntry>* entries) {
    if (arg[0] == '@') {
        FILE* rspfile = fopen(&arg[1], "r");
        if (!rspfile) {
            perror(&arg[1]);
            return 1;
        }
        while (!feof(rspfile) && !ferror(rspfile)) {
            // 2018 macOS hasn't caught up with C99 yet, so can't use %ms here.
            char filename[4096];
            if (fscanf(rspfile, " %4095s", filename) == 1) {
                handle_argument(argv, filename, entries);
            }
        }
        int result = ferror(rspfile);
        if (result) {
            perror(&arg[1]);
        }
        fclose(rspfile);
        return result;
    } else {
        entries->push_back({arg});
        return 0;
    }
}

void handle_entry(FileEntry* entry) {
    fbl::unique_fd fd{open(entry->filename.c_str(), O_RDONLY)};
    if (!fd) {
        perror(entry->filename.c_str());
        exit(1);
    }

    struct stat info;
    if (fstat(fd.get(), &info) < 0) {
        perror("fstat");
        exit(1);
    }
    if (!S_ISREG(info.st_mode)) {
        return;
    }

    // Buffer one intermediate node's worth at a time.
    fbl::unique_ptr<uint8_t[]> tree;
    Digest digest;
    size_t len = MerkleTree::GetTreeLength(info.st_size);
    fbl::AllocChecker ac;
    tree.reset(new (&ac) uint8_t[len]);
    if (!ac.check()) {
        perror("cannot allocate");
        exit(1);
    }
    void* data = nullptr;
    if (info.st_size != 0) {
        data = mmap(NULL, info.st_size, PROT_READ, MAP_SHARED, fd.get(), 0);
    }
    if (info.st_size != 0 && data == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }
    zx_status_t rc =
        MerkleTree::Create(data, info.st_size, tree.get(), len, &digest);
    if (info.st_size != 0 && munmap(data, info.st_size) != 0) {
        perror("munmap");
        exit(1);
    }
    if (rc != ZX_OK) {
        fprintf(stderr, "%s: Merkle tree creation failed: %d\n",
                entry->filename.c_str(), rc);
        exit(1);
    }
    rc = digest.ToString(entry->digest, sizeof(entry->digest));
    if (rc != ZX_OK) {
        fprintf(stderr, "%s: Unable to print Merkle tree root: %d\n",
                entry->filename.c_str(), rc);
        exit(1);
    }
}

} // namespace

int main(int argc, char** argv) {
    FILE* outf = stdout;
    if (argc < 2) {
        usage(argv);
    }

    int argi = 1;
    bool manifest = !strcmp(argv[1], "-m");
    if (manifest || !strcmp(argv[1], "-o")) {
        if (argc < 4) {
            usage(argv);
        }
        argi = 3;
        outf = fopen(argv[2], "w");
        if (!outf) {
            perror(argv[2]);
            return 1;
        }
    }

    std::vector<FileEntry> entries;
    for (; argi < argc; ++argi) {
        if (handle_argument(argv, argv[argi], &entries))
            return 1;
    }

    std::vector<std::thread> threads;
    std::mutex mtx;
    size_t next_entry = 0;
    size_t n_threads = std::thread::hardware_concurrency();
    if (!n_threads) {
        n_threads = 4;
    }
    if (n_threads > entries.size()) {
        n_threads = entries.size();
    }
    for (size_t i = n_threads; i > 0; --i) {
        threads.push_back(std::thread([&] {
            while (true) {
                mtx.lock();
                auto j = next_entry++;
                mtx.unlock();
                if (j >= entries.size()) {
                    return;
                }
                handle_entry(&entries[j]);
            }
        }));
    }
    for (unsigned i = 0; i < threads.size(); ++i) {
        threads[i].join();
    }

    for (const auto& entry : entries) {
        fprintf(outf, "%s%s%s\n",
                entry.digest, manifest ? "=" : " - ", entry.filename.c_str());
    }

    return 0;
}
