// 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 <fuchsia/kernel/c/fidl.h>
#include <inttypes.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/zx/channel.h>
#include <lib/zx/handle.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <task-utils/walker.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 processes under this job
  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 child;
    status = zx_object_get_child(process, koids->entries[n], ZX_RIGHT_SAME_RIGHTS,
                                 child.reset_and_get_address());
    if (status == ZX_OK) {
      // call the thread_callback if supplied
      if (ctx->thread_callback) {
        status = (ctx->thread_callback)(ctx->callback_context, depth, child.get(),
                                        koids->entries[n], process_koid);
        // abort on failure
        if (status != ZX_OK) {
          return status;
        }
      }
    } 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 child;
    status = zx_object_get_child(job, koids->entries[n], ZX_RIGHT_SAME_RIGHTS,
                                 child.reset_and_get_address());
    if (status == ZX_OK) {
      // call the process_callback if supplied
      if (ctx->process_callback) {
        status = (ctx->process_callback)(ctx->callback_context, depth, child.get(),
                                         koids->entries[n], job_koid);
        // abort on failure
        if (status != ZX_OK) {
          return status;
        }
      }

      if (ctx->thread_callback) {
        status = do_threads(ctx, child.get(), koids->entries[n], depth + 1);
        // abort on failure
        if (status != ZX_OK) {
          return status;
        }
      }
    } 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 child;
    status = zx_object_get_child(job, koids->entries[n], ZX_RIGHT_SAME_RIGHTS,
                                 child.reset_and_get_address());
    if (status == ZX_OK) {
      // call the job_callback if supplied
      if (ctx->job_callback) {
        status = (ctx->job_callback)(ctx->callback_context, depth, child.get(), 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.get(), koids->entries[n], depth + 1);
      // abort on failure
      if (status != ZX_OK) {
        return status;
      }
    } 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) {
  zx::channel local, remote;
  zx_status_t status = zx::channel::create(0, &local, &remote);
  if (status != ZX_OK) {
    return status;
  }

  status = fdio_service_connect("/svc/fuchsia.kernel.RootJob", remote.release());
  if (status != ZX_OK) {
    fprintf(stderr, "task-utils/walker: cannot open fuchsia.kernel.RootJob: %s\n",
            zx_status_get_string(status));
    return status;
  }

  zx::handle root_job;
  zx_status_t fidl_status =
      fuchsia_kernel_RootJobGet(local.get(), root_job.reset_and_get_address());

  if (fidl_status != ZX_OK) {
    fprintf(stderr, "task-utils/walker: cannot obtain root job\n");
    return ZX_ERR_NOT_FOUND;
  }

  zx_status_t s =
      walk_job_tree(root_job.get(), job_callback, process_callback, thread_callback, context);
  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));
}
