// 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 <task-utils/walker.h>

#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <zircon/device/sysinfo.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

// Immutable state of a specific call to walk_job_tree, passed along
// to most helper functions.
typedef struct {
    task_callback_t* job_callback;
    task_callback_t* process_callback;
    task_callback_t* thread_callback;
    void* callback_context;
} walk_ctx_t;

// A dynamically-managed array of koids.
// TODO(dbort): Turn into a class now that this is a .cpp file.
typedef struct {
    zx_koid_t* entries;
    size_t num_entries;
    size_t capacity; // allocation size
} koid_table_t;

// best first guess at number of children
static const size_t kNumInitialKoids = 128;

// when reallocating koid buffer because we were too small add this much extra
// on top of what the kernel says is currently needed
static const size_t kNumExtraKoids = 10;

static zx_status_t walk_job_tree_internal(
    const walk_ctx_t* ctx, zx_handle_t job, zx_koid_t job_koid, int depth);

static size_t koid_table_byte_capacity(koid_table_t* table) {
    return table->capacity * sizeof(table->entries[0]);
}

static void realloc_koid_table(koid_table_t* table, size_t new_capacity) {
    table->entries = reinterpret_cast<zx_koid_t*>(
        realloc(table->entries, new_capacity * sizeof(table->entries[0])));
    table->capacity = new_capacity;
}

static koid_table_t* make_koid_table(void) {
    koid_table_t* table =
        reinterpret_cast<koid_table_t*>(malloc(sizeof(*table)));
    table->num_entries = 0;
    table->entries = nullptr;
    realloc_koid_table(table, kNumInitialKoids);
    return table;
}

static void free_koid_table(koid_table_t* table) {
    free(table->entries);
    free(table);
}

static zx_status_t fetch_children(zx_handle_t parent, zx_koid_t parent_koid,
                                  int children_kind, const char* kind_name,
                                  koid_table_t* koids) {

    size_t actual = 0;
    size_t avail = 0;
    zx_status_t status;

    // this is inherently racy, but we retry once with a bit of slop to try to
    // get a complete list
    for (int pass = 0; pass < 2; ++pass) {
        if (actual < avail) {
            realloc_koid_table(koids, avail + kNumExtraKoids);
        }
        status = zx_object_get_info(parent, children_kind,
                                    koids->entries,
                                    koid_table_byte_capacity(koids),
                                    &actual, &avail);
        if (status != ZX_OK) {
            fprintf(stderr,
                    "ERROR: zx_object_get_info(%" PRIu64 ", %s, ...) "
                    "failed: %s (%d)\n",
                    parent_koid, kind_name,
                    zx_status_get_string(status), status);
            return status;
        }
        if (actual == avail) {
            break;
        }
    }

    // if we're still too small at least warn the user
    if (actual < avail) {
        fprintf(stderr,
                "WARNING: zx_object_get_info(%" PRIu64 ", %s, ...) "
                "truncated %zu/%zu results\n",
                parent_koid, kind_name, avail - actual, avail);
    }

    koids->num_entries = actual;
    return ZX_OK;
}

static zx_status_t do_threads_worker(
    const walk_ctx_t* ctx, koid_table_t* koids,
    zx_handle_t process, zx_koid_t process_koid, int depth) {

    zx_status_t status;

    // get the list of threads under this process
    status = fetch_children(process, process_koid, ZX_INFO_PROCESS_THREADS,
                            "ZX_INFO_PROCESS_THREADS", koids);
    if (status != ZX_OK) {
        return status;
    }

    for (size_t n = 0; n < koids->num_entries; n++) {
        zx_handle_t child;
        status = zx_object_get_child(process, koids->entries[n],
                                     ZX_RIGHT_SAME_RIGHTS, &child);
        if (status == ZX_OK) {
            // call the thread_callback if supplied
            if (ctx->thread_callback) {
                status = (ctx->thread_callback)(
                    ctx->callback_context,
                    depth, child, koids->entries[n], process_koid);
                // abort on failure
                if (status != ZX_OK) {
                    return status;
                }
            }

            zx_handle_close(child);
        } else {
            fprintf(stderr,
                    "WARNING: zx_object_get_child(%" PRIu64 ", "
                    "(proc)%" PRIu64 ", ...) failed: %s (%d)\n",
                    process_koid, koids->entries[n],
                    zx_status_get_string(status), status);
        }
    }

    return ZX_OK;
}

static zx_status_t do_threads(
    const walk_ctx_t* ctx, zx_handle_t job, zx_koid_t job_koid, int depth) {

    koid_table_t* koids = make_koid_table();
    zx_status_t status = do_threads_worker(ctx, koids, job, job_koid, depth);
    free_koid_table(koids);
    return status;
}

static zx_status_t do_processes_worker(
    const walk_ctx_t* ctx, koid_table_t* koids,
    zx_handle_t job, zx_koid_t job_koid, int depth) {

    zx_status_t status;

    // get the list of processes under this job
    status = fetch_children(job, job_koid, ZX_INFO_JOB_PROCESSES,
                            "ZX_INFO_JOB_PROCESSES", koids);
    if (status != ZX_OK) {
        return status;
    }

    for (size_t n = 0; n < koids->num_entries; n++) {
        zx_handle_t child;
        status = zx_object_get_child(job, koids->entries[n],
                                     ZX_RIGHT_SAME_RIGHTS, &child);
        if (status == ZX_OK) {
            // call the process_callback if supplied
            if (ctx->process_callback) {
                status = (ctx->process_callback)(ctx->callback_context,
                                                 depth, child,
                                                 koids->entries[n], job_koid);
                // abort on failure
                if (status != ZX_OK) {
                    return status;
                }
            }

            if (ctx->thread_callback) {
                status = do_threads(ctx, child, koids->entries[n], depth + 1);
                // abort on failure
                if (status != ZX_OK) {
                    return status;
                }
            }

            zx_handle_close(child);
        } else {
            fprintf(stderr,
                    "WARNING: zx_object_get_child(%" PRIu64 ", "
                    "(proc)%" PRIu64 ", ...) failed: %s (%d)\n",
                    job_koid, koids->entries[n],
                    zx_status_get_string(status), status);
        }
    }

    return ZX_OK;
}

static zx_status_t do_processes(
    const walk_ctx_t* ctx, zx_handle_t job, zx_koid_t job_koid, int depth) {

    koid_table_t* koids = make_koid_table();
    zx_status_t status = do_processes_worker(ctx, koids, job, job_koid, depth);
    free_koid_table(koids);
    return status;
}

static zx_status_t do_jobs_worker(
    const walk_ctx_t* ctx, koid_table_t* koids,
    zx_handle_t job, zx_koid_t job_koid, int depth) {

    zx_status_t status;

    // get a list of child jobs for this job
    status = fetch_children(job, job_koid, ZX_INFO_JOB_CHILDREN,
                            "ZX_INFO_JOB_CHILDREN", koids);
    if (status != ZX_OK) {
        return status;
    }

    // drill down into the job tree
    for (size_t n = 0; n < koids->num_entries; n++) {
        zx_handle_t child;
        status = zx_object_get_child(job, koids->entries[n],
                                     ZX_RIGHT_SAME_RIGHTS, &child);
        if (status == ZX_OK) {
            // call the job_callback if supplied
            if (ctx->job_callback) {
                status = (ctx->job_callback)(ctx->callback_context,
                                             depth, child,
                                             koids->entries[n], job_koid);
                // abort on failure
                if (status != ZX_OK) {
                    return status;
                }
            }

            // recurse to its children
            status = walk_job_tree_internal(
                ctx, child, koids->entries[n], depth + 1);
            // abort on failure
            if (status != ZX_OK) {
                return status;
            }

            zx_handle_close(child);
        } else {
            fprintf(stderr,
                    "WARNING: zx_object_get_child(%" PRIu64 ", (job)%" PRIu64
                    ", ...) failed: %s (%d)\n",
                    job_koid, koids->entries[n],
                    zx_status_get_string(status), status);
        }
    }

    return ZX_OK;
}

static zx_status_t do_jobs(
    const walk_ctx_t* ctx, zx_handle_t job, zx_koid_t job_koid, int depth) {

    koid_table_t* koids = make_koid_table();
    zx_status_t status = do_jobs_worker(ctx, koids, job, job_koid, depth);
    free_koid_table(koids);
    return status;
}

static zx_status_t walk_job_tree_internal(
    const walk_ctx_t* ctx, zx_handle_t job, zx_koid_t job_koid, int depth) {

    if (ctx->process_callback != nullptr || ctx->thread_callback != nullptr) {
        zx_status_t status = do_processes(ctx, job, job_koid, depth);
        if (status != ZX_OK) {
            return status;
        }
    }

    return do_jobs(ctx, job, job_koid, depth);
}

zx_status_t walk_job_tree(zx_handle_t root_job,
                          task_callback_t job_callback,
                          task_callback_t process_callback,
                          task_callback_t thread_callback,
                          void* context) {
    zx_koid_t root_job_koid = 0;
    zx_info_handle_basic_t info;
    zx_status_t status = zx_object_get_info(
        root_job, ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
    if (status == ZX_OK) {
        root_job_koid = info.koid;
    }
    // Else keep going with a koid of zero.

    if (job_callback) {
        status =
            (job_callback)(context, /* depth */ 0, root_job, root_job_koid, 0);
        if (status != ZX_OK) {
            return status;
        }
    }
    walk_ctx_t ctx = {
        .job_callback = job_callback,
        .process_callback = process_callback,
        .thread_callback = thread_callback,
        .callback_context = context,
    };
    return walk_job_tree_internal(
        &ctx, root_job, root_job_koid, /* depth */ 1);
}

zx_status_t walk_root_job_tree(task_callback_t job_callback,
                               task_callback_t process_callback,
                               task_callback_t thread_callback,
                               void* context) {
    int fd = open("/dev/misc/sysinfo", O_RDWR);
    if (fd < 0) {
        fprintf(stderr, "task-utils/walker: cannot open sysinfo: %d\n", errno);
        return ZX_ERR_NOT_FOUND;
    }

    zx_handle_t root_job;
    size_t n = ioctl_sysinfo_get_root_job(fd, &root_job);
    close(fd);
    if (n != sizeof(root_job)) {
        fprintf(stderr, "task-utils/walker: cannot obtain root job\n");
        return ZX_ERR_NOT_FOUND;
    }

    zx_status_t s = walk_job_tree(
        root_job, job_callback, process_callback, thread_callback, context);
    zx_handle_close(root_job);
    return s;
}

// C++ interface

namespace {
static zx_status_t job_cpp_cb(void* ctx, int depth, zx_handle_t handle,
                              zx_koid_t koid, zx_koid_t parent_koid) {
    return reinterpret_cast<TaskEnumerator*>(ctx)->OnJob(
        depth, handle, koid, parent_koid);
}

static zx_status_t process_cpp_cb(void* ctx, int depth, zx_handle_t handle,
                                  zx_koid_t koid, zx_koid_t parent_koid) {
    return reinterpret_cast<TaskEnumerator*>(ctx)->OnProcess(
        depth, handle, koid, parent_koid);
}

static zx_status_t thread_cpp_cb(void* ctx, int depth, zx_handle_t handle,
                                 zx_koid_t koid, zx_koid_t parent_koid) {
    return reinterpret_cast<TaskEnumerator*>(ctx)->OnThread(
        depth, handle, koid, parent_koid);
}
} // namespace

zx_status_t TaskEnumerator::WalkJobTree(zx_handle_t root_job) {
    return walk_job_tree(root_job,
                         has_on_job() ? job_cpp_cb : nullptr,
                         has_on_process() ? process_cpp_cb : nullptr,
                         has_on_thread() ? thread_cpp_cb : nullptr,
                         reinterpret_cast<void*>(this));
}

zx_status_t TaskEnumerator::WalkRootJobTree() {
    return walk_root_job_tree(has_on_job() ? job_cpp_cb : nullptr,
                              has_on_process() ? process_cpp_cb : nullptr,
                              has_on_thread() ? thread_cpp_cb : nullptr,
                              reinterpret_cast<void*>(this));
}
