/**
@file     procfs_manager.c
@brief    Manager for procfs
@details  Copyright (c) 2025 Acronis International GmbH
@author   Denis Kopyrin (denis.kopyrin@acronis.com)
@since    $Id: $
*/

#include "procfs_manager.h"

#include "path_tools.h"
lru_hashtable_manager_t *global_procfs_manager;

// MARK: Procfs manager
int procfs_manager_init(void)
{
	return lru_hashtable_manager_init(&global_procfs_manager);
}

void procfs_manager_deinit(void)
{
	lru_hashtable_manager_deinit(global_procfs_manager);
}

void procfs_manager_activate(void)
{
	lru_hashtable_manager_activate(global_procfs_manager);
}

void procfs_manager_deactivate(void)
{
	lru_hashtable_manager_deactivate(global_procfs_manager);
}

static bool procfs_manager_key_exist(const lru_hashtable_key_t *key)
{
	return lru_hashtable_manager_key_exist(global_procfs_manager, key, LRU_HASHTABLE_KEY_TYPE_PROCFS);
}

bool procfs_should_send(task_info_t *caller_task_info, const struct path *target_path, lru_hashtable_key_t *out_key, task_info_t **target_task_info)
{
	SiProcfsAccessType access_type;
	uint64_t caller_pid_version = 0;
	uint64_t target_pid_version = 0;
	pid_t target_pid = 0;

	if(!READ_ONCE(global_procfs_manager->active))
		return false;
		
	if (!caller_task_info || !target_path || !out_key)
		return false;
	caller_pid_version = READ_ONCE(caller_task_info->pid_version);

	if(get_procfs_access_info(target_path, &target_pid, &access_type) == false)
		return false;

	*target_task_info = task_info_map_get_by_pid(target_pid, 0);
	if (!*target_task_info)
		return false;
	target_pid_version = READ_ONCE((*target_task_info)->pid_version);

	out_key->procfs_key.access_type = access_type;
	out_key->procfs_key.caller_pid_version = caller_pid_version;
	out_key->procfs_key.target_pid_version = target_pid_version;

	if (procfs_manager_key_exist(out_key))
	{
		return false;
	}

	return true;
}