// Copyright 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 <dirent.h>
#include <errno.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include <fbl/ref_ptr.h>
#include <fbl/unique_ptr.h>
#include <fuzz-utils/path.h>
#include <lib/fdio/debug.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#define ZXDEBUG 0

namespace fuzzing {

// Public methods

Path::Path() {
    fbl::AllocChecker ac;
    path_ = AdoptRef(new (&ac) PathBuffer());
    ZX_ASSERT(ac.check());
    Reset();
}

Path::Path(fbl::RefPtr<PathBuffer> path) : path_(path), length_(path->buffer_.length()) {}

Path::Path(const Path& other) : path_(other.path_), length_(other.length_) {}

Path::~Path() {}

fbl::String Path::Join(const char* relpath) const {
    ZX_DEBUG_ASSERT(relpath);

    fbl::StringBuffer<PATH_MAX> abspath;
    abspath.Append(c_str(), length_ - 1);

    // Add each path segment
    const char* p = relpath;
    const char* sep;
    while (p && (sep = strchr(p, '/'))) {
        // Skip repeated slashes
        if (p != sep) {
            abspath.Append('/');
            abspath.Append(p, sep - p);
        }
        p = sep + 1;
    }
    if (*p) {
        abspath.Append('/');
        abspath.Append(p);
    }

    return fbl::move(abspath);
}

zx_status_t Path::GetSize(const char* relpath, size_t* out) const {
    fbl::String abspath = Join(relpath);
    struct stat buf;
    if (stat(abspath.c_str(), &buf) != 0) {
        xprintf("Failed to get status for '%s': %s\n", abspath.c_str(), strerror(errno));
        return ZX_ERR_IO;
    }
    *out = buf.st_size;
    return ZX_OK;
}

fbl::unique_ptr<StringList> Path::List() const {
    fbl::AllocChecker ac;
    fbl::unique_ptr<StringList> list(new (&ac) StringList());
    ZX_ASSERT(ac.check());

    DIR* dir = opendir(c_str());
    if (!dir) {
        return fbl::move(list);
    }
    auto close_dir = fbl::MakeAutoCall([&dir]() { closedir(dir); });

    struct dirent* ent;
    while ((ent = readdir(dir))) {
        if (strcmp(".", ent->d_name) != 0) {
            list->push_back(ent->d_name);
        }
    }
    return fbl::move(list);
}

zx_status_t Path::Ensure(const char* relpath) {
    ZX_DEBUG_ASSERT(relpath);
    zx_status_t rc;

    // First check if already exists
    fbl::String abspath = fbl::move(Join(relpath));
    struct stat buf;
    if (stat(abspath.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode)) {
        return ZX_OK;
    }

    // Now recursively create the parent directories
    const char* sep = strrchr(relpath, '/');
    if (sep) {
        fbl::String prefix(relpath, sep - relpath);
        if ((rc = Ensure(prefix.c_str())) != ZX_OK) {
            xprintf("Failed to ensure parent directory: %s\n", zx_status_get_string(rc));
            return rc;
        }
    }

    // Finally, create the last directory
    if (mkdir(abspath.c_str(), 0777) != 0) {
        xprintf("Failed to make directory '%s': %s.\n", abspath.c_str(), strerror(errno));
        return ZX_ERR_IO;
    }
    return ZX_OK;
}

zx_status_t Path::Push(const char* relpath) {
    ZX_DEBUG_ASSERT(relpath);
    if (*relpath == '\0') {
        xprintf("Can't push empty path.\n");
        return ZX_ERR_INVALID_ARGS;
    }
    fbl::String abspath = fbl::move(Join(relpath));
    struct stat buf;
    if (stat(abspath.c_str(), &buf) != 0) {
        xprintf("Failed to get status for '%s': %s\n", abspath.c_str(), strerror(errno));
        return ZX_ERR_IO;
    }
    if (!S_ISDIR(buf.st_mode)) {
        xprintf("Not a directory: %s\n", abspath.c_str());
        return ZX_ERR_NOT_DIR;
    }

    fbl::AllocChecker ac;
    fbl::unique_ptr<Path> cloned(new (&ac) Path(path_));
    ZX_ASSERT(ac.check());

    cloned->parent_.swap(parent_);
    parent_.swap(cloned);
    path_->buffer_.Clear();
    path_->buffer_.Append(abspath);
    path_->buffer_.Append('/');
    length_ = path_->buffer_.length();

    return ZX_OK;
}

void Path::Pop() {
    if (!parent_) {
        return;
    }
    length_ = parent_->length_;
    path_->buffer_.Resize(length_);
    fbl::unique_ptr<Path> parent;
    parent.swap(parent_->parent_);
    parent_.swap(parent);
}

zx_status_t Path::Remove(const char* relpath) {
    ZX_DEBUG_ASSERT(relpath);
    zx_status_t rc;

    fbl::String abspath = fbl::move(Join(relpath));
    struct stat buf;
    if (stat(abspath.c_str(), &buf) != 0) {
        // Ignore missing files
        if (errno != ENOENT) {
            xprintf("Failed to get status for '%s': %s\n", abspath.c_str(), strerror(errno));
            return ZX_ERR_IO;
        }

    } else if (S_ISDIR(buf.st_mode)) {
        // Recursively remove directories
        if ((rc = Push(relpath)) != ZX_OK) {
            xprintf("Failed to push subdirectory: %s\n", zx_status_get_string(rc));
            return rc;
        }
        auto pop = fbl::MakeAutoCall([this]() { Pop(); });

        auto names = List();
        for (const char* name = names->first(); name; name = names->next()) {
            if ((rc = Remove(name)) != ZX_OK) {
                xprintf("Failed to remove subdirectory: %s\n", zx_status_get_string(rc));
                return rc;
            }
        }
        if (rmdir(c_str()) != 0) {
            xprintf("Failed to remove directory '%s': %s\n", c_str(), strerror(errno));
            return ZX_ERR_IO;
        }
        return ZX_OK;

    } else {
        // Remove file
        if (unlink(abspath.c_str()) != 0) {
            xprintf("Failed to unlink '%s': %s\n", abspath.c_str(), strerror(errno));
            return ZX_ERR_IO;
        }
    }

    return ZX_OK;
}

zx_status_t Path::Rename(const char* old_relpath, const char* new_relpath) {
    fbl::String old_abspath = fbl::move(Join(old_relpath));
    fbl::String new_abspath = fbl::move(Join(new_relpath));
    if (rename(old_abspath.c_str(), new_abspath.c_str()) != 0) {
        xprintf("Failed to rename '%s' to '%s': %s.\n", old_abspath.c_str(), new_abspath.c_str(),
                strerror(errno));
        return ZX_ERR_IO;
    }
    return ZX_OK;
}

void Path::Reset() {
    parent_.reset();
    path_->buffer_.Clear();
    path_->buffer_.Append("/");
    length_ = path_->buffer_.length();
}

} // namespace fuzzing
