/*
 * Copyright (c) KylinSoft  Co., Ltd. 2024. All rights reserved.
 *
 * kaiming is licensed under the GPL v2.0+.
 *
 * See the LICENSE file for more details.
 */

#include "KMRunner.h"

#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <unordered_set>
#include <type_traits>
#include <sys/mount.h>
#include <sys/utsname.h>

#include "KMReference.h"
#include "KMRunnerOptions.h"
#include "KMCapability.h"
#include "KMRunnerOnce.h"
#include "common/KMConfigData.h"
#include "common/KMContainer.h"
#include "common/KMLogger.h"
#include "common/KMUtil.h"

REGISTER_SUBCOMMAND_DYNCREATE(run, KMRunner)

class KMRunner::Private
{
public:
    std::string appId;
    std::string appDir;
    std::string baseDir;
    std::string runtimeDir;
    std::string appDataPath;
    std::string optionCommand;
    std::string runCommands;
    std::vector<std::string> commandArgs;
    std::vector<std::string> infoCommands;
    std::map<std::string, std::string> infoEnvs;
    std::unique_ptr<KMContainer> container;
    std::unique_ptr<KMRunnerOptions> options;
    Permissions perms;
    Annotations annotations;
};

static const std::vector<int> defCap = {
    CAP_CHOWN,
    CAP_DAC_OVERRIDE,
    CAP_FSETID,
    CAP_FOWNER,
    CAP_MKNOD,
    CAP_NET_RAW,
    CAP_SETGID,
    CAP_SETUID,
    CAP_SETFCAP,
    CAP_SETPCAP,
    CAP_NET_BIND_SERVICE,
    CAP_SYS_CHROOT,
    CAP_SYS_ADMIN,
    CAP_KILL
};

static const std::vector<int> allCap = {
    CAP_CHOWN,
    CAP_DAC_OVERRIDE,
    CAP_DAC_READ_SEARCH,
    CAP_FOWNER,
    CAP_FSETID,
    CAP_KILL,
    CAP_SETGID,
    CAP_SETUID,
    CAP_SETPCAP,
    CAP_LINUX_IMMUTABLE,
    CAP_NET_BIND_SERVICE,
    CAP_NET_BROADCAST,
    CAP_NET_ADMIN,
    CAP_NET_RAW,
    CAP_IPC_LOCK,
    CAP_IPC_OWNER,
    CAP_SYS_MODULE,
    CAP_SYS_RAWIO,
    CAP_SYS_CHROOT,
    CAP_SYS_PTRACE,
    CAP_SYS_PACCT,
    CAP_SYS_ADMIN,
    CAP_SYS_BOOT,
    CAP_SYS_NICE,
    CAP_SYS_RESOURCE,
    CAP_SYS_TIME,
    CAP_SYS_TTY_CONFIG,
    CAP_MKNOD,
    CAP_LEASE,
    CAP_AUDIT_WRITE,
    CAP_AUDIT_CONTROL,
    CAP_SETFCAP,
    CAP_MAC_OVERRIDE,
    CAP_MAC_ADMIN,
    CAP_SYSLOG,
    CAP_WAKE_ALARM,
    CAP_BLOCK_SUSPEND,
    CAP_AUDIT_READ,
    CAP_PERFMON,
    CAP_BPF,
    CAP_CHECKPOINT_RESTORE
};

/**
 * @brief 构造函数
 */
KMRunner::KMRunner()
    : d_ptr(std::make_shared<KMRunner::Private>())
{
    d_ptr->container = std::make_unique<KMContainer>();
    d_ptr->options = std::make_unique<KMRunnerOptions>();
}

/**
 * @brief 开明子命令运行
 * @param argc 参数个数
 * @param argv 参数列表
 * @return 0 成功 非0 失败
 */
int KMRunner::dispose(int argc, char **argv)
{
    if (!parseArgs(argc, argv))
    {
        return false;
    }

    return start() ? EXIT_SUCCESS : -1;
}

/**
 * @brief 解析命令行参数
 * @param argc 参数个数
 * @param argv 参数列表
 * @return true 成功 false 失败
 */
bool KMRunner::parseArgs(int argc, char **argv)
{
    // 参数解析
    d_ptr->options->parseCommandLine(argc, argv);

    d_ptr->appId = d_ptr->options->getAppId();
    if (d_ptr->appId.empty())
    {
        KMError("app id is empty");
        return false;
    }

    d_ptr->optionCommand = d_ptr->options->getCommand();

    for (auto &arg : d_ptr->options->getArgs())
    {
        if (!d_ptr->options->isFileWarding())
        {
            d_ptr->commandArgs.emplace_back(arg);
            continue;
        }

        if (arg == string("@@") || arg == string("@@u"))
        {
            continue;
        }

        d_ptr->commandArgs.emplace_back(arg);
    }

    kmlogger.info("start app %s", d_ptr->appId.c_str());

    return true;
}

/**
 * @brief 开始运行
 * @return true 成功 false 失败
 */
bool KMRunner::start()
{
    if (!getLayersDirs())
    {
        KMError("get layers dirs failed");
        return false;
    }

    if (!ensureAppDataDir())
    {
        KMError("create app data directory failed");
        return false;
    }

    if (!assembleCommand())
    {
        KMError("assemble command failed");
        return false;
    }

    // 判断是否已经运行,若已经运行则进入已运行的容器环境内运行
    if (std::string containerID; KMRunnerOnce::isAlreadyRun(d_ptr->appId, containerID) && KMRunnerOnce::runOnce(containerID, d_ptr->runCommands))
    {
        return true;
    }

    if (!mountLayers())
    {
        KMError("mount layers failed");
        return false;
    }

    if (!mountBase())
    {
        KMError("mount others failed");
        return false;
    }

    if (!mountData())
    {
        KMError("mount data failed");
        return false;
    }

    if (!permissionControl())
    {
        KMError("permission control failed");
        return false;
    }

    if (!genLdsocache())
    {
        KMError("mount ldsocache failed");
        return false;
    }

    if (!setProcessCmd())
    {
        KMError("set process failed");
        return false;
    }

    if (!d_ptr->container->run(false))
    {
        KMError("run container failed");
        return false;
    }

    return true;
}

/**
 * @brief 获取app,base,runtime目录
 * @return true 成功 false 失败
 */
bool KMRunner::getLayersDirs()
{
    KMReference ref;
    if (!ref.getLayerDir(d_ptr->appId, d_ptr->options->isDevel()))
    {
        KMError("get layer dir failed");
        return false;
    }

    if (!ref.getAppDir(d_ptr->appDir))
    {
        KMError("get app dir failed");
        return false;
    }

    if (!ref.getBaseDir(d_ptr->baseDir))
    {
        KMError("get base dir failed");
        return false;
    }

    if (!ref.getRuntimeDir(d_ptr->runtimeDir))
    {
        KMError("get runtime dir failed");
        return false;
    }

    if (!ref.getCommands(d_ptr->infoCommands))
    {
        KMError("get commands failed");
        return false;
    }

    if (!ref.getEnvs(d_ptr->infoEnvs))
    {
        KMError("get envs failed");
        return false;
    }

    // 获取权限信息，且权限管控可以是空
    d_ptr->perms = ref.getPermissions();
    // 获取自定义字段
    d_ptr->annotations = ref.getAnnotations();

    kmlogger.info("app dir [%s], base dir: [%s], runtime dir: [%s]", d_ptr->appDir.c_str(), d_ptr->baseDir.c_str(), d_ptr->runtimeDir.c_str());
    return true;
}

/**
 * @brief 创建appdate子目录
 * @return true 成功 false 失败
 */
bool KMRunner::ensureAppDataDir()
{
    if (!getAppDataPath())
    {
        return false;
    }

    std::error_code ec;
    fs::path appDataPath(d_ptr->appDataPath);

    if (!fs::exists(appDataPath) && !fs::create_directories(appDataPath, ec))
        return false;

    if (!fs::exists(appDataPath / "hostcache") && !fs::create_directories(appDataPath / "hostcache", ec))
        return false;

    if (!fs::exists(appDataPath / "upperdir") && !fs::create_directories(appDataPath / "upperdir", ec))
        return false;

    if (!fs::exists(appDataPath / "workdir") && !fs::create_directories(appDataPath / "workdir", ec))
        return false;

    return true;
}

/**
 *@brief 获取appdata路径
 *@return true 成功 false 失败
 */
bool KMRunner::getAppDataPath()
{
    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("get home failed");
        return false;
    }

    d_ptr->appDataPath = std::string(home) + string("/.var/app/") + d_ptr->appId;

    return true;
}

/**
 * @brief 挂载app,base,runtime目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountLayers()
{
    d_ptr->container->setAppID(d_ptr->appId);
    d_ptr->container->setBaseDir(d_ptr->baseDir);
    d_ptr->container->addAnnotation("kaiming.app.id", d_ptr->appId);
    d_ptr->container->addAnnotation("kaiming.app.dir", d_ptr->appDir);
    d_ptr->container->addAnnotation("kaiming.base.dir", d_ptr->baseDir);
    d_ptr->container->addAnnotation("kaiming.runtime.dir", d_ptr->runtimeDir);

    // 多个挂载不能使用同一upperdir,workdir,否则会导致未知风险问题
    std::string upperdir = d_ptr->appDataPath + "/upperdir";
    std::string workdir = d_ptr->appDataPath + "/workdir";

    // mount overlayfs
    // proc sys dev 属于特殊的内存文件系统,不属于具体的硬件设备,无须叠加
    std::vector<std::string> ignoreDir = { "/proc", "/sys", "/tmp", "/run", "/dev", "/home", "/root" };
    for (auto &entry : fs::directory_iterator(d_ptr->baseDir + "/files"))
    {
        // 非目录不叠加
        if (!entry.is_directory())
        {
            continue;
        }
        string dir = string("/") + entry.path().filename().string();
        if (std::find(ignoreDir.begin(), ignoreDir.end(), dir) != ignoreDir.end())
        {
            continue;
        }
        // overlay叠加目录
        overlayDir(dir, false);
    }

    // 按照标准规范绑定挂载目录
    if (!d_ptr->annotations.sysapp)
    {
        std::string appDir = d_ptr->appDir + string("/files");
        std::string destinationDir = "/opt/apps/" + d_ptr->appId + "/files";
        std::vector<std::string> options = { "rbind", "rprivate" };
        std::string type = "bind";
        if (fs::exists(appDir))
        {
            d_ptr->container->addMount(Mount{ .source = appDir, .destination = destinationDir, .type = type, .options = options });
        }
    }

    // 持久化存储
    {
        auto home = getenv("HOME");
        if (home == nullptr)
        {
            KMError("Couldn't get HOME from env ");
            return false;
        }

        // 每个app都需要家目录需创建一些必要的空目录,存放自己的配置文件等
        std::string homedir = d_ptr->appDataPath + string("/hostcache") + string(home);
        if (!fs::exists(homedir))
        {
            std::vector<std::string> dirs = { ".config", ".local", ".log", ".cache" };
            for (auto const &dir : dirs)
            {
                std::string src = homedir + string("/") + dir;
                if (!fs::exists(src))
                {
                    std::error_code ec;
                    fs::create_directories(src, ec);
                }
            }
        }
        std::vector<std::string> options = { "rbind", "rprivate" };
        d_ptr->container->addMount(Mount{ .source = homedir, .destination = string(home), .type = "bind", .options = options });
    }

    return true;
}

/**
 * @brief 设置process
 * @return true 成功 false 失败
 */
bool KMRunner::setProcessCmd()
{
    if (!assembleProcEnv())
    {
        KMError("assemble process env failed");
        return false;
    }

    if (!setProcessCmdArgs())
    {
        KMError("set process command failed");
        return false;
    }

    if (!setProcessCap(defCap))
    {
        KMError("set default capability failed");
        return false;
    }

    if (!privileged())
    {
        KMError("privilege failed");
    }

    return true;
}

/**
 * @brief 设置进程运行命令
 * @return true 成功 false 失败
 */
bool KMRunner::setProcessCmdArgs()
{
    if (d_ptr->runCommands.empty())
    {
        KMError("run command is empty");
        return false;
    }
    std::vector<string> args = { "/bin/bash", "--login", "-e", "-c" };
    std::string additionalCommand = "while true; do num=$(ps aux | grep -v sleep | wc -l); if [ $num -gt 3 ]; then sleep 1; else exit 0;  fi; done";
    std::string fullCommand = d_ptr->runCommands + "; " + additionalCommand;
    args.emplace_back(fullCommand);
    d_ptr->container->setProcessArgs(args);

    auto home = getenv("HOME");
    if (home != nullptr)
    {
        d_ptr->container->setProcessCwd(home);
    }
    return true;
}

/**
 * @brief 提权
 * @return true 成功 false 失败
 */
bool KMRunner::privileged()
{
    // 是否提权
    if (!d_ptr->annotations.privilege)
    {
        return true;
    }

    if (getuid() != 0)
    {
        return true;
    }

    //去除user命名空间才能插入ko,fanotify等功能
    d_ptr->container->rmNameSpace("user");

    if (!setProcessCap(allCap))
    {
        KMError("privilege capability failed");
        return false;
    }

    return true;
}

/**
 * @brief 设置process的cap能力
 * @param cap 能力列表
 * @return true 成功 false 失败
 */
bool KMRunner::setProcessCap(const std::vector<int> &cap)
{
    d_ptr->container->setLinuxCapabilities(cap);
    d_ptr->container->setProcessBoundingCapabilities(cap);
    d_ptr->container->setProcessAmbientCapabilities(cap);
    d_ptr->container->setProcessEffectiveCapabilities(cap);
    d_ptr->container->setProcessInheritableCapabilities(cap);
    d_ptr->container->setProcessPermittedCapabilities(cap);

    return true;
}

/**
 * @brief 组装运行命令
 * @return true 成功 false 失败
 */
bool KMRunner::assembleCommand()
{
    // 优先级: 命令行参数option > info.json, 二选一
    std::string command;
    if (!d_ptr->optionCommand.empty())
    {
        command.append(d_ptr->optionCommand);
        for (const auto &arg : d_ptr->commandArgs)
        {
            command.append(" ").append(arg);
        }
    }
    else
    {
        for (const auto &arg : d_ptr->infoCommands)
        {
            command.append(" ").append(arg);
        }
    }
    if (command.empty())
    {
        KMError("command is empty");
        return false;
    }

    d_ptr->runCommands = command;
    return true;

    return true;
}

/**
 * @brief 组装运行环境变量
 * @return true 成功 false 失败
 */
bool KMRunner::assembleProcEnv()
{
    Process process = d_ptr->container->getProcess();
    // 获取系统环境变量
    std::map<std::string, std::string> envs;
    for (auto &env : process.env)
    {
        auto key = env.substr(0, env.find_first_of('='));
        auto value = env.substr(env.find_first_of('=') + 1);
        envs[key] = value;
    }

    // 设置开明需要的环境变量
    std::map<std::string, std::string> newEnvs;
    auto sessionAddress = getenv("DBUS_SESSION_BUS_ADDRESS");
    string session = (sessionAddress == nullptr) ? string("unix:path=") + string("/run/user/") + to_string(getuid()) + string("/bus") : string(sessionAddress);
    newEnvs["DBUS_SESSION_BUS_ADDRESS"] = session;

    auto sysAddress = getenv("DBUS_SYSTEM_BUS_ADDRESS");
    if (sysAddress != nullptr)
    {
        newEnvs["DBUS_SYSTEM_BUS_ADDRESS"] = string(sysAddress);
    }
    else if (fs::exists(string("/run/dbus/system_bus_socket")))
    {
        newEnvs["DBUS_SYSTEM_BUS_ADDRESS"] = string("unix:path=/run/dbus/system_bus_socket");
    }

    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return false;
    }
    auto homeDir = string(home);
    string xauthFile;
    auto pXauthFile = getenv("XAUTHORITY");
    if (pXauthFile != nullptr && fs::exists(pXauthFile))
    {
        xauthFile = string(pXauthFile);
    }
    else
    {
        xauthFile = homeDir + string("/.Xauthority");
    }
    newEnvs["XAUTHORITY"] = xauthFile;
    newEnvs["XDG_RUNTIME_DIR"] = string("/run/user/") + to_string(getuid());
    auto pXdgDataHome = getenv("XDG_DATA_HOME");
    std::string XDGDataHome = pXdgDataHome == nullptr ? (homeDir + string("/.local/share")) : string(pXdgDataHome);
    newEnvs["XDG_DATA_HOME"] = XDGDataHome;
    newEnvs["XDG_CONFIG_HOME"] = homeDir + string("/.config");
    newEnvs["XDG_CACHE_HOME"] = homeDir + string("/.cache");
    newEnvs["XDG_STATE_HOME"] = homeDir + string("/.local/state");

    if (std::string appDesktopPath = "/opt/kaiming/share/applications/" + d_ptr->appId + ".desktop"; std::filesystem::exists(appDesktopPath))
    {
        newEnvs["PANSHI_APP_DESKTOP"] = appDesktopPath;
    }

    // 设置Display
    auto display = getenv("DISPLAY");
    if (display != nullptr)
    {
        newEnvs["DISPLAY"] = string(display);
    }
    else
    {
        newEnvs["DISPLAY"] = string(":0");
    }

    // 设置PATH
    auto path = getenv("PATH");
    if (path != nullptr)
    {
        newEnvs["PATH"] = string(path);
    }
    else
    {
        newEnvs["PATH"] = string("/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/bin:/usr/local/sbin");
    }

    // 主要编包环境变量
    newEnvs["KAIMING_ID"] = d_ptr->appId;

    // 增加QT相关环境变量
    newEnvs["QML2_IMPORT_PATH"] = string("/lib64/qml:") + string("/lib/qml");
    newEnvs["QT_PLUGIN_PATH"] = string("/lib64/plugins:") + string("/lib/plugins:") + string("/lib/x86_64-linux-gnu/qt5/plugins/");
    newEnvs["__EGL_EXTERNAL_PLATFORM_CONFIG_DIRS"] = string("/etc/egl/egl_external_platform.d:"
                                                            "/usr/lib/x86_64-linux-gnu/GL/egl/egl_external_platform.d:"
                                                            "/usr/share/egl/egl_external_platform.d");

    // 增加XDG相关环境变量
    std::string xdgConfig = string("/opt/apps/") + d_ptr->appId + string("/files/etc/xdg");
    std::string xdgData = string("/opt/apps/") + d_ptr->appId + string("/files/share");
    newEnvs["XDG_CONFIG_DIRS"] = xdgConfig + string(":/etc/xdg:/etc/xdg/xdg-ukui");
    newEnvs["XDG_DATA_DIRS"] = xdgData + string(":/usr/share:/usr/local/share:/usr/share/ukui:/share:/run/host/share:/run/host/local-share:/run/host/user-share");

    // 增加app应用中的环境变量
    std::map<std::string, std::string> infoEnvs = d_ptr->infoEnvs;

    // 合并处理环境变量
    KMReference ref;
    ref.appendEnvs(envs, newEnvs);
    ref.appendEnvs(envs, infoEnvs);

    // 处理环境变量中的变量引用
    for (auto &[k, v] : envs)
    {
        auto it = v.find(string("$") + k);
        if (it != string::npos)
        {
            if (v.find(string("$") + k + string(":")) != string::npos)
            {
                v.replace(it, k.length() + 2, "");
            }
            else
            {
                v.replace(it, k.length() + 1, "");
            }
        }
    }

    std::string valueOfpath;
    for (const auto &[k, v] : envs)
    {
        if (k == "PATH")
        {
            valueOfpath = v;
        }
    }

    // 设置LD_LIBRARY_PATH
    std::string valueOfldlibrarypath;
    for (const auto &[k, v] : envs)
    {
        if (k == "LD_LIBRARY_PATH")
        {
            valueOfldlibrarypath = v;
        }
    }

    if (!valueOfpath.empty())
    {
        newEnvs["PATH"] = string("/opt/apps/") + d_ptr->appId + string("/files/local/bin") + ":" + string("/opt/apps/") + d_ptr->appId + string("/files/bin") + ":" + valueOfpath + ":" + string(path);
    }
    else
    {
        newEnvs["PATH"] = string("/opt/apps/") + d_ptr->appId + string("/files/local/bin") + ":" + string("/opt/apps/") + d_ptr->appId + string("/files/bin") + ":" + string(path);
    }

    if (!valueOfldlibrarypath.empty())
    {
        newEnvs["LD_LIBRARY_PATH"] = string("/opt/apps/") + d_ptr->appId + string("/files/local/lib") + ":" + string("/opt/apps/") + d_ptr->appId + string("/files/lib") + ":" + valueOfldlibrarypath;
    }
    else
    {
        newEnvs["LD_LIBRARY_PATH"] = string("/opt/apps/") + d_ptr->appId + string("/files/local/lib") + ":" + string("/opt/apps/") + d_ptr->appId + string("/files/lib");
    }

    for (const auto &[k, v] : newEnvs)
    {
        envs[k] = v;
    }
    std::vector<string> dedupEnvs;
    for (const auto &[k, v] : envs)
    {
        dedupEnvs.emplace_back(k + "=" + v);
    }

    d_ptr->container->setProcessEnv(dedupEnvs);

    return true;
}

/**
 * @brief 生成ldso缓存
 * @return true 成功 false 失败
 */
bool KMRunner::genLdsocache()
{
    if (!genLdconfig())
    {
        KMDebug("generate ldconfig failed");
    }

    auto start = std::vector<Hook>{ Hook{ "/bin/bash", std::vector<std::string>{ "/bin/bash", "-c", "/sbin/ldconfig" } } };
    d_ptr->container->setStartContainer(start);

    return true;
}

/**
 * @brief 生成ldso配置文件
 * @return true 成功 false 失败
 */
bool KMRunner::genLdconfig()
{
    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return false;
    }

    std::string config = std::string(home) + string("/.var/app/config");
    if (!fs::exists(config))
    {
        std::error_code ec;
        fs::create_directories(config, ec);
        if (ec)
        {
            KMWarn("can not create dir: " + config);
            return false;
        }
    }

    std::string ldconfig = config + "/kaiming.conf";
    if (!fs::exists(ldconfig))
    {
        std::ofstream ofs(ldconfig);
        if (!ofs.is_open())
        {
            KMWarn("create kaiming.conf file failed ");
            return false;
        }

        ofs << "/lib64" << endl;
        ofs << "/usr/lib64" << endl;
        ofs.close();

        mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
        chmod(ldconfig.c_str(), mode);
    }

    std::string confd = d_ptr->appDataPath + std::string("/upperdir/etc/ld.so.conf.d");
    if (!fs::exists(confd))
    {
        std::error_code ec;
        fs::create_directories(confd, ec);
        if (ec)
        {
            KMWarn("can not create dir: " + confd);
            return false;
        }
    }

    std::string kmconf = confd + std::string("/kaiming.conf");
    if (!fs::exists(kmconf))
    {
        std::ofstream confofs(kmconf);
        if (!confofs.is_open())
        {
            KMWarn("create upper xdg-open file failed ");
            return false;
        }
        confofs.close();
    }

    std::string type = "bind";
    std::string src = ldconfig;
    std::string dst = "/etc/ld.so.conf.d/kaiming.conf";
    std::vector<std::string> options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });

    return true;
}

/**
 * @brief 挂载基础目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountBase()
{
    string dst, src, type;
    std::vector<std::string> options;

    dst = string("/proc");
    src = string("proc");
    type = string("proc");
    options = { "nosuid", "noexec", "nodev" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type });

    // tmp目录下的临时文件可能会需要执行，所以去掉noexec选项
    dst = string("/tmp");
    src = string("/tmp");
    type = string("bind");
    options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });

    dst = string("/sys");
    src = string("tmpfs");
    type = string("tmpfs");
    options = { "nodev", "nosuid", "noexec" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });

    dst = string("/sys");
    src = string("/sys");
    type = string("bind");
    options = { "rbind", "rprivate" };
    if (fs::exists(src))
    {
        d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
    }

    dst = string("/var/tmp");
    src = string("/var/tmp");
    type = string("bind");
    options = { "rbind", "rprivate" };
    if (fs::exists(src))
    {
        d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
    }

    dst = string("/sys/fs/cgroup");
    src = string("cgroup");
    type = string("cgroup");
    options = { "nodev", "nosuid", "noexec" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });

    dst = string("/proc/self/ns/user");
    src = string("/run/.userns");
    options = { "rbind", "ro", "rprivate" };
    if (fs::exists(src))
    {
        d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
    }

    dst = string("/etc/timezone");
    src = string("/var/db/zoneinfo");
    if (fs::exists(src))
    {
        d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
    }

    // 解决udev管控信息
    src = string("/run/udev");
    dst = string("/run/udev");
    options = { "rbind", "rprivate" };
    if (fs::exists(src))
    {
        d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
    }

    options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = d_ptr->appDir + string("/files"), .destination = "/app", .type = "bind", options });

    return true;
}

/**
 * @brief 挂载dev设备
 * @return true 成功 false 失败
 */
bool KMRunner::mountDev()
{
    std::string src, dst, type;
    std::vector<std::string> options;
    dst = string("/dev");
    src = string("tmpfs");
    type = string("tmpfs");
    options = { "nosuid", "strictatime", "mode=755", "size=65536k" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });

    // 挂载所有设备需要按需挂载
    dst = string("/dev");
    src = string("/dev");
    type = string("bind");
    options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });

    if ((d_ptr->perms.all || d_ptr->perms.microphone) && !mountPulseaudio())
    {
        KMError("mount pulseaudio failed");
        return false;
    }

    if (!d_ptr->perms.all)
    {
        // 去除管控不需要挂载的设备
        std::vector<std::string> controlDevice{};
        if (!d_ptr->perms.camera)
        {
            controlDevice.emplace_back("/dev/video");
        }
        if (!d_ptr->perms.serial)
        {
            controlDevice.emplace_back("/dev/ttyS");
            controlDevice.emplace_back("/dev/ttyUSB");
        }
        if (!d_ptr->perms.microphone)
        {
            controlDevice.emplace_back("/dev/snd");
        }

        for (auto const &entry : fs::directory_iterator{ "/dev" })
        {
            std::string dev = entry.path().string();
            bool isControlDevice = false;
            for (auto const &control : controlDevice)
            {
                if (dev.find(control) != string::npos)
                {
                    isControlDevice = true;
                }
            }
            if (!isControlDevice)
            {
                continue;
            }

            permDev(dev);
        }
    }

    return true;
}

/**
 * @brief 管控设备文件
 * @return true 成功 false 失败
 */
bool KMRunner::permDev(std::string const &dev)
{
    if (!fs::exists(d_ptr->appDataPath + string("/dev")))
    {
        std::error_code ec;
        fs::create_directories(d_ptr->appDataPath + string("/dev"), ec);
        if (ec)
        {
            KMError("create dev directory failed: " + ec.message());
        }
    }

    std::string overDir;
    std::vector<std::string> options;
    std::string type = "bind";
    if (fs::is_directory(dev))
    {
        options = { "nosuid", "strictatime", "mode=0777" };
        d_ptr->container->addMount(Mount{ .source = "tmpfs", .destination = dev, .type = "tmpfs", .options = options });
    }
    else
    {
        std::string overDir = d_ptr->appDataPath + dev;
        std::ofstream ofs(overDir, std::ios::out);
        ofs << "" << std::endl;
        ofs.close();
        options = { "rbind", "rprivate" };
        d_ptr->container->addMount(Mount{ .source = overDir, .destination = dev, .type = type, .options = options });
    }

    return true;
}

/**
 * @brief 挂载socket
 * @return true 成功 false 失败
 */
bool KMRunner::mountSocket()
{
    if (!mountX11())
    {
        KMError("mount x11 failed");
        return false;
    }

    if (!mountWayland())
    {
        KMError("mount wayland failed");
        return false;
    }

    mountGssproxy();
    mountResolved();
    mountJournal();

    if (!mountDbus())
    {
        KMError("mount dbus failed");
        return false;
    }

    return true;
}

/**
 * @brief 挂载share,包含字体,icon等
 * @return true 成功 false 失败
 */
bool KMRunner::mountShare()
{
    // 创建挂载目录
    std::error_code ec;
    std::string appLocalShareDir = d_ptr->appDataPath + std::string("/upperdir/usr/local/share");
    std::string appShareDir = d_ptr->appDataPath + std::string("/upperdir/usr/share");
    std::filesystem::create_directories(appLocalShareDir, ec);
    std::filesystem::create_directories(appShareDir, ec);

    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";

    // 挂载主题配置
    mountDir("/usr/share/themes", "/usr/share/themes", type, options);

    // 挂载字体配置
    mountDir("/etc/fonts", "/etc/fonts", type, options);
    mountDir("/usr/share/fontconfig", "/usr/share/fontconfig", type, options);

    // 挂载字体
    mountDir("/usr/share/fonts", "/usr/share/fonts", type, options);
    mountDir("/usr/local/share/fonts", "/usr/local/share/fonts", type, options);

    // 挂载图标
    mountDir("/usr/share/icons", "/usr/share/icons", type, options);

    // 挂载用户配置
    std::string userlocalShare = KMFolder::getUserDataPath();
    mountDir(userlocalShare, userlocalShare, type, options);

    std::string homeFontPath = KMFolder::getHomePath() / ".fonts";
    mountDir(homeFontPath, homeFontPath, type, options);

    // 挂载体缓存
    std::string homecache = KMFolder::getUserCachePath();
    std::string cacheFontsConfig = string("/var/cache/fontconfig:/usr/lib/fontconfig/cache:") + homecache + string("/fontconfig");
    for (auto const &config : KMUtil::split(cacheFontsConfig, ':'))
    {
        mountDir(config, config, type, options);
    }

    // 挂载主机配置到容器内,方便xdg桌面应用使用
    mountDir("/usr/share", "/run/host/share", type, options);
    mountDir("/usr/local/share", "/run/host/local-share", type, options);
    mountDir(userlocalShare, "/run/host/user-share", type, options);

    return true;
}

/**
 * @brief 检查内核配置文件中是否设置了 CONFIG_OVERLAY_FS_INDEX=y
 */
bool KMRunner::isOverlayFsIndexOff()
{
    struct utsname unameInfo;
    if (uname(&unameInfo) != 0)
    {
        KMError("Failed to get uname information");
        return false;
    }

    std::string configFilePath = "/boot/config-" + std::string(unameInfo.release);
    std::ifstream configFile(configFilePath);
    std::string line;

    if (!configFile.is_open())
    {
        KMError("Failed to open config file: " + configFilePath);
        return false;
    }

    while (std::getline(configFile, line))
    {
        if (line.find("CONFIG_OVERLAY_FS_INDEX=y") != std::string::npos)
        {
            return true;
        }
    }
    return false;
}

/**
 * @brief 叠加目录
 * @param dir overlay目录路径
 * @param isHost 是否叠加宿主机目录
 */
void KMRunner::overlayDir(const std::string &dir, bool isOverlayHost)
{
    std::string hostDir = isOverlayHost ? dir : "";
    std::string baseDir = d_ptr->baseDir + string("/files") + dir;
    std::string runtimeDir = d_ptr->runtimeDir + string("/files") + dir;
    std::string appDir = d_ptr->appDir + string("/files") + dir;
    std::string dependsDir = d_ptr->appDir + string("/depends") + dir;

    std::string workdir, upperdir;

    //overlay叠加目录创建，解决后续绑定挂载问题
    workdir = d_ptr->appDataPath + string("/workdir") + dir;
    upperdir = d_ptr->appDataPath + string("/upperdir") + dir;
    if (!fs::exists(upperdir) || !fs::exists(workdir))
    {
        fs::create_directories(upperdir);
        fs::create_directories(workdir);
    }

    // 主机目录叠加时不能和base,runtime,app等目录使用同一upperdir和workdir
    if (isOverlayHost)
    {
        workdir = d_ptr->appDataPath + string("/hostworkdir") + dir;
        upperdir = d_ptr->appDataPath + string("/hostupperdir") + dir;
    }
    if (!fs::exists(upperdir) || !fs::exists(workdir))
    {
        fs::create_directories(upperdir);
        fs::create_directories(workdir);
    }

    string upperDir = string("upperdir=") + upperdir;
    string workDir = string("workdir=") + workdir;

    // 叠加lowerdir目录
    string lowerDir = "lowerdir=";
    appendLowerDir(lowerDir, hostDir);
    // 系统app才需要叠加
    if (d_ptr->annotations.sysapp)
    {
        appendLowerDir(lowerDir, appDir);
    }
    appendLowerDir(lowerDir, dependsDir);
    appendLowerDir(lowerDir, runtimeDir);
    appendLowerDir(lowerDir, baseDir);

    std::vector<std::string> options = { lowerDir, upperDir, workDir };
    if (isOverlayFsIndexOff())
    {
        options.emplace_back("index=off");
    }

    // 判断内核版本，如果支持userxattr，则添加到options中
    if (supportsUserXAttr())
    {
        options.emplace_back("userxattr");
    }

    d_ptr->container->addMount(Mount{ .source = string("overlay"), .destination = dir, .type = string("overlay"), .options = options });
}

/**
 * @brief 追加lowerdir
 * @param lowerdir lowerdir
 * @param dir 追加的目录
 */
void KMRunner::appendLowerDir(std::string &lowerdir, const std::string &dir) const
{
    if (!dir.empty() && fs::exists(dir))
    {
        if (lowerdir.length() > strlen("lowerdir="))
        {
            lowerdir.append(":");
        }
        lowerdir.append(dir);
    }
}

/**
 * @brief 挂载GSSProxy配置
 */
void KMRunner::mountGssproxy()
{
    string gssproxy = KMFolder::getXdgRuntimePath() / "gssproxy";
    std::vector<string> options = { "rbind", "ro", "rprivate" };
    std::string type = "bind";
    if (fs::exists(gssproxy))
    {
        d_ptr->container->addMount(Mount{ .source = gssproxy, .destination = gssproxy, .type = type, .options = options });
    }
}

/**
 * @brief 挂载resolved配置
 */
void KMRunner::mountResolved()
{
    string resolved = "/run/systemd/resolve/io.systemd.Resolve";
    std::vector<string> options = { "rbind", "ro", "rprivate" };
    std::string type = "bind";
    if (fs::exists(resolved))
    {
        d_ptr->container->addMount(Mount{ .source = resolved, .destination = resolved, .type = type, .options = options });
    }
}

/**
 * @brief 挂载journal配置
 */
void KMRunner::mountJournal()
{
    string journalSocket = "/run/systemd/journal/socket";
    string journalStdout = "/run/systemd/journal/stdout";
    std::vector<string> options = { "rbind", "ro", "rprivate" };
    std::string type = "bind";
    if (fs::exists(journalSocket))
    {
        d_ptr->container->addMount(Mount{ .source = journalSocket, .destination = journalSocket, .type = type, .options = options });
    }
    if (fs::exists(journalStdout))
    {
        d_ptr->container->addMount(Mount{ .source = journalStdout, .destination = journalStdout, .type = type, .options = options });
    }
}

/**
 * @brief 挂载pulseaudio配置
 * @return true 成功 false 失败
 */
bool KMRunner::mountPulseaudio()
{
    std::string pulseSocket = KMFolder::getPulseRuntimePath() / "native";
    if (!fs::exists(pulseSocket))
    {
        if (fs::exists(string("/var/run/pulse/native")))
        {
            pulseSocket = string("/var/run/pulse/native");
        }
        else
        {
            pulseSocket = string("");
        }
    }

    if (!pulseSocket.empty())
    {
        string configPath = KMFolder::getPulseRuntimePath() / "config";
        string hostConfigPath = d_ptr->appDataPath + "/hostcache/config";

        ofstream ofs(hostConfigPath, std::ios::out | std::ios::trunc);
        if (!ofs.is_open())
        {
            ofs.close();
            KMError("create pulse config file failed");
            return false;
        }

        ofs << string("enable-shm=no") << std::endl;
        ofs.close();

        // 设置挂载
        d_ptr->container->addMount(Mount{ .source = pulseSocket, .destination = pulseSocket, .type = "bind", .options = { { "rbind", "rprivate" } } });
        d_ptr->container->addMount(Mount{ .source = hostConfigPath, .destination = configPath, .type = "bind", .options = { { "rbind", "ro", "rprivate" } } });

        // 设置环境变量
        Process process = d_ptr->container->getProcess();
        process.env.emplace_back(string("PULSE_SERVER=") + pulseSocket);
        process.env.emplace_back(string("PULSE_CLIENTCONFIG=") + configPath);
        d_ptr->container->setProcess(process);
    }

    return true;
}

/**
 * @brief 挂载dbus配置
 * @return true 成功 false 失败
 */
bool KMRunner::mountDbus()
{
    auto *systemBusEnv = getenv("DBUS_SYSTEM_BUS_ADDRESS");
    std::string systemBus = "/var/run/dbus/system_bus_socket";
    if (systemBusEnv != nullptr && std::filesystem::exists(systemBusEnv))
    {
        systemBus = systemBusEnv;
    }

    if (!std::filesystem::exists(systemBus))
    {
        KMError("dbus system bus socket not found at " + systemBus);
        return false;
    }

    std::string type = "bind";
    std::vector<std::string> roOptions = { "rbind", "ro", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = systemBus, .destination = "/run/dbus/system_bus_socket", .type = type, .options = roOptions });

    // 只有普通用户才能挂载session bus
    if (getuid() != 0)
    {
        // 挂载user session bus地址
        auto sessionAddress = getenv("DBUS_SESSION_BUS_ADDRESS");
        if (sessionAddress != nullptr)
        {
            std::string sessionAddrStr = std::string(sessionAddress);

            // 检查是否为抽象地址
            std::regex abstractRegex(R"(unix:abstract=(/?.+))");
            std::smatch match;
            if (!std::regex_search(sessionAddrStr, match, abstractRegex))
            {
                // 非抽象地址，解析为路径
                std::string sessionPath = pathFromAddress(sessionAddrStr);
                if (sessionPath.empty() || !std::filesystem::exists(sessionPath))
                {
                    KMError("DBus session bus path: " + sessionPath + " not found");
                    return false;
                }

                d_ptr->container->addMount(Mount{ .source = sessionPath, .destination = sessionPath, .type = type, .options = roOptions });
            }
        }
        else
        {
            KMInfo("DBUS_SESSION_BUS_ADDRESS not found");
        }
    }

    return true;
}

/**
 * @brief : 挂载x11
 * @return true 成功 false 失败
 */
bool KMRunner::mountX11()
{
    string x11Socket = "/tmp/.X11-unix";
    if (fs::exists(x11Socket))
    {
        d_ptr->container->addMount(Mount{ .source = x11Socket, .destination = x11Socket, .type = "bind", .options = { { "rbind", "rprivate" } } });
    }

    return true;
}

/**
 * @brief 挂载wayland
 * @return true 成功 false 失败
 */
bool KMRunner::mountWayland()
{
    auto display = getenv("WAYLAND_DISPLAY");
    if (display == nullptr)
    {
        return true;
    }

    string waylandDisplay = string(display);
    string waylandSocker;
    if (waylandDisplay.at(0) == '/')
    {
        waylandSocker = waylandDisplay;
    }
    else
    {
        waylandSocker = KMFolder::getXdgRuntimePath() / waylandDisplay;
    }

    if (fs::exists(waylandSocker))
    {
        d_ptr->container->addMount(Mount{ .source = waylandSocker, .destination = waylandSocker, .type = "bind", .options = { { "rbind", "ro", "rprivate" } } });
    }

    // 解决wayland兼容x11问题
    mountX11Wayland();

    return true;
}

/**
 * @brief 挂载x11-wayland兼容层
 */
void KMRunner::mountX11Wayland()
{
    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return;
    }

    std::string config = std::string(home) + string("/.var/app/config");
    if (!fs::exists(config))
    {
        std::error_code ec;
        fs::create_directories(config, ec);
        if (ec)
        {
            KMWarn("can not create dir: " + config);
            return;
        }
    }

    std::string x11ext = config + "/x11-ext.sh";
    if (!fs::exists(x11ext))
    {
        std::ofstream ofs(x11ext);
        if (!ofs.is_open())
        {
            KMWarn("create x11-ext.sh file failed ");
            return;
        }

        ofs << "#This is used for set environment to x11 and use default mesa libs" << endl;
        ofs << "export XDG_SESSION_TYPE=\"x11\"" << endl;
        ofs << "unset WAYLAND_DISPLAY" << endl;
        ofs.close();

        mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
        chmod(x11ext.c_str(), mode);
    }

    std::string type = "bind";
    std::string src = x11ext;
    std::string dst = "/opt/x11-wayland/x11-ext.sh";
    std::vector<std::string> options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
}

/**
 * @brief 挂载数据配置
 * @return true 成功 false 失败
 */
bool KMRunner::mountData()
{
    if (!mountEtc())
    {
        KMError("mount etc failed");
        return false;
    }

    if (!mountSocket())
    {
        KMError("mount socket failed");
        return false;
    }

    if (!mountShare())
    {
        KMError("mount share failed");
        return false;
    }

    if (!mountDconf())
    {
        KMError("mount dconf failed");
        return false;
    }

    if (!mountXauthority())
    {
        KMError("mount xauthority failed");
        return false;
    }

    if (!mountShareData())
    {
        KMError("mount share data directory failed");
        return false;
    }

    return true;
}

/**
 * @brief 挂载共享目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountShareData()
{
    // 非root用户不挂载数据目录
    if (getuid() == 0)
    {
        return true;
    }

    // 挂载用户数据目录
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    if (fs::exists("/data"))
    {
        d_ptr->container->addMount(Mount{ .source = "/data", .destination = "/data", .type = type, .options = options });
    }
    if (fs::exists("/media"))
    {
        d_ptr->container->addMount(Mount{ .source = "/media", .destination = "/media", .type = type, .options = options });
    }
    if (fs::exists("/cdrom"))
    {
        d_ptr->container->addMount(Mount{ .source = "/cdrom", .destination = "/cdrom", .type = type, .options = options });
    }

    return true;
}

/**
 * @brief 挂载许可
 * @return true 成功 false 失败
 */
bool KMRunner::mountXauthority()
{
    // 此配置不应该影响应用的正常启动
    auto pXauthFile = getenv("XAUTHORITY");
    std::string xauthFile;
    if (pXauthFile == nullptr)
    {
        auto home = getenv("HOME");
        if (home != nullptr)
        {
            xauthFile = string(home) + string("/.Xauthority");
        }
    }
    else
    {
        xauthFile = string(pXauthFile);
    }

    if (!fs::exists(xauthFile))
    {
        return true;
    }

    std::vector<std::string> options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = xauthFile, .destination = xauthFile, .type = "bind", .options = options });

    return true;
}

/**
 * @brief 权限管控
 * @return true 成功 false 失败
 */
bool KMRunner::permissionControl()
{
    // xdg-open创建失败不应影响应用启动
    mountXdgOpen();

    if (!mountFileSystem())
    {
        KMError("mount specified path failed");
        return false;
    }

    if (!mountAutoStart())
    {
        KMError("mount autostart failed");
        return false;
    }

    if (!setNetwork())
    {
        KMError("mount autostart failed");
        return false;
    }

    if (!mountDev())
    {
        KMError("mount dev failed");
        return false;
    }

    if (!bluetoothRestricted())
    {
        KMError("bluetooth control failed");
        return false;
    }
    return true;
}

bool KMRunner::bluetoothRestricted()
{
    if (d_ptr->perms.bluetooth)
    {
        Seccomp seccomp;
        seccomp.defaultAction = "SCMP_ACT_ALLOW";
        seccomp.architectures = { "SCMP_ARCH_X86_64", "SCMP_ARCH_ARM", "SCMP_ARCH_AARCH64" };

        Syscall syscall;
        syscall.names = { "socket" };
        syscall.action = "SCMP_ACT_ERRNO";
        syscall.errnoRet = 1;

        SyscallArg arg;
        arg.index = 0;
        arg.op = "SCMP_CMP_EQ";
        arg.value = 31;

        syscall.args.push_back(arg);
        seccomp.syscalls.push_back(syscall);
        d_ptr->container->setSeccomp(seccomp);
    }
    return true;
}

/**
 * @brief 设置网络访问权限
 * @return true 成功 false 失败
 */
bool KMRunner::setNetwork()
{
    if (!d_ptr->perms.all && !d_ptr->perms.network)
    {
        d_ptr->container->addNameSpace("network");
    }
    return true;
}

/**
 * @brief 挂载指定目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountFileSystem()
{
    // 绑定用户目录,服务级进程不需要绑定用户目录
    auto *home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return false;
    }

    // 绑定userdir指定目录
    if (getuid() != 0)
    {
        // 暂时权限管控部分注释以免影响现在编包测试情况，等以后测试时放开
        if (d_ptr->perms.all || d_ptr->perms.xdgUserDirs)
        {
            std::vector<std::string> options = { "rbind", "rprivate" };
            std::string type = "bind";
            if (fs::exists(string(home)))
            {
                std::vector<std::string> userDirs = { "桌面", "视频", "音乐", "文档", "图片", "公共", "下载", "模板" };
                for (auto const &subdir : userDirs)
                {
                    std::string userdir = string(home) + string("/") + subdir;
                    if (fs::exists(userdir))
                    {
                        d_ptr->container->addMount(Mount{ .source = userdir, .destination = userdir, .type = type, .options = options });
                    }
                }
            }
        }
    }

    //　绑定指定路径挂载
    for (auto &specdir : d_ptr->perms.filesystemDirs)
    {
        std::string type = "bind";
        std::vector<std::string> options = { "rbind", "rprivate" };

        if (specdir[0] == '~')
        {
            specdir = std::string(home) + specdir.substr(1);
        }

        if (!fs::exists(specdir))
        {
            continue;
        }

        std::string containerPath = d_ptr->appDataPath + "/upperdir" + specdir;
        if (!fs::exists(containerPath))
        {
            std::error_code ec;
            fs::create_directories(containerPath, ec);
            if (ec)
            {
                KMError("Failed to create directory: " + containerPath + ", error: " + ec.message());
                continue; // 如果创建失败，跳过这个路径
            }
        }
        d_ptr->container->addMount(Mount{ .source = specdir, .destination = specdir, .type = type, .options = options });
    }

    return true;
}

/**
 * @brief 挂载自动启动目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountAutoStart()
{
    if (!d_ptr->perms.all && !d_ptr->perms.autostart)
    {
        return true;
    }

    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";
    std::string etcAutoStart = "/etc/xdg/autostart";
    if (fs::exists(etcAutoStart))
    {
        d_ptr->container->addMount(Mount{ .source = etcAutoStart, .destination = etcAutoStart, .type = type, .options = options });
    }

    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return false;
    }

    std::string homeAutoStart = std::string(home) + string("/.config/autostart");
    if (fs::exists(homeAutoStart))
    {
        d_ptr->container->addMount(Mount{ .source = homeAutoStart, .destination = homeAutoStart, .type = type, .options = options });
    }

    return true;
}

/**
 * @brief 挂载xdg-open,解决xdg-open穿透问题
 * @return true 成功 false 失败
 */
void KMRunner::mountXdgOpen()
{
    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return;
    }

    std::string config = std::string(home) + string("/.var/app/config");
    if (!fs::exists(config))
    {
        std::error_code ec;
        fs::create_directories(config, ec);
        if (ec)
        {
            KMWarn("can not create dir: " + config);
            return;
        }
    }

    std::string xdg = config + "/xdg-open";
    if (!fs::exists(xdg))
    {
        std::ofstream ofs(xdg);
        if (!ofs.is_open())
        {
            KMWarn("create xdg-open file failed ");
            return;
        }

        ofs << "#!/bin/bash" << endl;
        ofs << "dbus-send --session --print-reply --dest=org.kylin.kaiming --type=method_call /org/kylin/kaiming org.kylin.kaiming.session.xdgOpen string:$1 >/dev/null" << endl;
        ofs.close();

        mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
        chmod(xdg.c_str(), mode);
    }

    std::string xdgdir = d_ptr->appDataPath + std::string("/upperdir/usr/bin");
    if (!fs::exists(xdgdir))
    {
        std::error_code ec;
        fs::create_directories(xdgdir, ec);
        if (ec)
        {
            KMWarn("can not create dir: " + xdgdir);
            return;
        }
    }

    std::string upperXdgOpen = xdgdir + std::string("/xdg-open");
    if (!fs::exists(upperXdgOpen))
    {
        std::ofstream xdgofs(upperXdgOpen);
        if (!xdgofs.is_open())
        {
            KMWarn("create upper xdg-open file failed ");
            return;
        }
        xdgofs.close();
    }

    std::string type = "bind";
    std::string src = xdg;
    std::string dst = "/usr/bin/xdg-open";
    std::vector<std::string> options = { "rbind", "rprivate" };
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
}

/**
 * @brief 挂载dconf目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountDconf()
{
    // 挂载 dconf
    auto home = getenv("HOME");
    if (home == nullptr)
    {
        KMError("Couldn't get HOME from env ");
        return false;
    }

    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    if (fs::exists(string(home) + "/.config/dconf/user"))
    {
        std::string dconf = string(home) + string("/.config/dconf/user");
        d_ptr->container->addMount(Mount{ .source = dconf, .destination = dconf, .type = type, .options = options });
        string userDirs = string(home) + string("/.config/user-dirs.dirs");
        if (fs::exists(userDirs))
        {
            d_ptr->container->addMount(Mount{ .source = userDirs, .destination = userDirs, .type = type, .options = options });
        }

        string userDirsLocale = string(home) + string("/.config/user-dirs.locale");
        if (fs::exists(userDirsLocale))
        {
            d_ptr->container->addMount(Mount{ .source = userDirsLocale, .destination = userDirsLocale, .type = type, .options = options });
        }
    }

    return true;
}

/**
 * @brief 挂载etc目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountEtc()
{
    std::string type = "bind";
    std::vector<std::string> roOptions = { "rbind", "ro", "rprivate" };
    if (fs::exists(string("/etc/passwd")))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/passwd", .destination = "/etc/passwd", .type = type, .options = roOptions });
    }

    if (fs::exists(string("/etc/group")))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/group", .destination = "/etc/group", .type = type, .options = roOptions });
    }

    // 挂载x window相关配置,奇安信浏览器需要此配置
    if (fs::exists(string("/etc/x-proj")))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/x-proj", .destination = "/etc/x-proj", .type = type, .options = roOptions });
    }

    if (!fs::exists(d_ptr->baseDir + string("/files/pkcs11/pkcs11.conf")))
    {
        std::string pkcsconf = d_ptr->appDataPath + string("/hostcache") + string("/pkcs11.conf");
        if (!fs::exists(pkcsconf))
        {
            std::ofstream ofs(pkcsconf, std::ios::out | std::ios::trunc);
            if (!ofs.is_open())
            {
                ofs.close();
                KMError("create pkcs11.conf file failed");
                return false;
            }
            ofs << string("# Disable user pkcs11 config, because the host modules don't work in the runtime\n") << std::endl;
            ofs << string("user-config: none") << std::endl;
            ofs.close();
        }

        d_ptr->container->addMount(Mount{ .source = pkcsconf, .destination = "/etc/pkcs11/pkcs11.conf", .type = type, .options = roOptions });
    }

    if (fs::exists("/etc/machine-id"))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/machine-id", .destination = "/etc/machine-id", .type = type, .options = roOptions });
    }
    else if (fs::exists("/var/lib/dbus/machine-id"))
    {
        d_ptr->container->addMount(Mount{ .source = "/var/lib/dbus/machine-id", .destination = "/var/lib/dbus/machine-id", .type = type, .options = roOptions });
    }

    if (fs::exists("/etc/resolv.conf"))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/resolv.conf", .destination = "/etc/resolv.conf", .type = type, .options = roOptions });
    }

    if (fs::exists("/etc/host.conf"))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/host.conf", .destination = "/etc/host.conf", .type = type, .options = roOptions });
    }

    if (fs::exists("/etc/hosts"))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/hosts", .destination = "/etc/hosts", .type = type, .options = roOptions });
    }

    if (fs::exists("/etc/gai.conf"))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/gai.conf", .destination = "/etc/gai.conf", .type = type, .options = roOptions });
    }

    // 设置系统时间挂载参数，如果系统的存在用系统的，系统的不存在，用 runtime/files 下的
    string rawTimeZone = KMUtil::kmGetTimeZone();
    string localtimeZone = string("/usr/share/zoneinfo/") + rawTimeZone;
    string runtimeTimezone = d_ptr->baseDir + string("/files/usr/share/zoneinfo");

    if (fs::exists(runtimeTimezone))
    {
        if (fs::exists("/usr/share/zoneinfo"))
        {
            d_ptr->container->addMount(Mount{ .source = "/usr/share/zoneinfo", .destination = "/usr/share/zoneinfo", .type = type, .options = roOptions });
            d_ptr->container->addMount(Mount{ .source = localtimeZone, .destination = "/etc/localtime", .type = type, .options = roOptions });
        }
        else if (fs::exists(runtimeTimezone + string("/") + rawTimeZone))
        {
            d_ptr->container->addMount(Mount{ .source = localtimeZone, .destination = "/etc/localtime", .type = type, .options = roOptions });
        }
    }

    // 挂载/etc/timezone
    {
        std::ofstream ofs(d_ptr->appDataPath + string("/hostcache") + "/timezone", std::ios::out | std::ios::trunc);
        if (!ofs.is_open())
        {
            ofs.close();
            KMError("create timezone file failed");
            return false;
        }

        ofs << rawTimeZone << std::endl;
        ofs.close();
        d_ptr->container->addMount(Mount{ .source = d_ptr->appDataPath + string("/hostcache") + "/timezone", .destination = "/etc/timezone", .type = type, .options = roOptions });
    }

    return true;
}

/**
 *@brief 解析dbus地址
 *@return string 路径
 */
string KMRunner::pathFromAddress(const string &address) const
{
    if (address.empty())
        return string();

    if (address.find("unix:") == string::npos)
        return string();

    if (address.find("path=") == string::npos)
        return string();

    std::string path = address.substr(address.find("path=") + strlen("path="), address.length() - address.find("path="));
    if (path.empty())
        return string();

    if (path.find(",") != string::npos)
        path = path.substr(0, path.find(","));

    return path;
}

/**
 *@brief 支持用户xattr
 *@return true 支持 false 不支持
 */
bool KMRunner::supportsUserXAttr()
{
    struct utsname uname_info;
    if (uname(&uname_info) == 0)
    {
        std::string kernel_version = uname_info.release;
        // 提取内核主版本号和次版本号
        int major_version = std::stoi(kernel_version.substr(0, kernel_version.find('.')));
        int minor_version = std::stoi(kernel_version.substr(kernel_version.find('.') + 1, kernel_version.find_last_of('.') - kernel_version.find('.') - 1));

        // 判断内核版本是否大于 5.4
        return (major_version > 5) || (major_version == 5 && minor_version > 4);
    }
    return false;
}

/**
 *@brief 挂载指定目
 */
void KMRunner::mountDir(const std::string &hostDir, const std::string &containDir, const std::string &type, std::vector<std::string> options)
{
    // 挂载指定目录
    if (hostDir.empty() || containDir.empty())
    {
        return;
    }

    if (fs::exists(hostDir))
    {
        d_ptr->container->addMount(Mount{ .source = hostDir, .destination = containDir, .type = type, .options = options });
    }
}
