/*
 * 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 <unistd.h>
#include <sys/utsname.h>
#include <uuid/uuid.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"
#include "common/KMUnixSocketServer.h"
#include "common/KMOverlay.h"

REGISTER_SUBCOMMAND_DYNCREATE(run, KMRunner)

class KMRunner::Private
{
public:
    int indexFlag = 0; // 0 代表默认值 1 代表true 2 代表false
    std::string appId;
    std::string appDir;
    std::string baseDir;
    std::string runtimeDir;
    std::string appDataPath;
    std::string optionCommand;
    std::string runCommands;
    std::string arch;
    std::string runDir;
    std::string containerId;
    std::string homeDir;
    std::string version;
    std::string sockPath;
    std::string pulseSocket;
    std::vector<std::string> commandArgs;
    std::vector<std::string> infoCommands;
    std::vector<std::string> envs;
    std::map<std::string, std::string> infoEnvs;
    std::unique_ptr<KMContainer> container;
    std::unique_ptr<KMRunnerOptions> options;
    Permissions perms;
    Annotations annotations;
    KMUnixSocketServer server;
};

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

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())
    {
        std::string completeArg = "\"" + arg + "\"";
        if (!d_ptr->options->isFileWarding())
        {
            d_ptr->commandArgs.emplace_back(completeArg);
            continue;
        }

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

        d_ptr->commandArgs.emplace_back(completeArg);
    }

    KMDebug("start app " + d_ptr->appId);

    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 (!setupInterTty())
    {
        KMError("setup inter tty failed");
        return false;
    }

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

    if (!assembleProcEnv())
    {
        KMError("assemble process env failed");
        return false;
    }

    // 试用模式处理
    if (isTrialMode())
    {
        std::string cmd = "/opt/kaiming-tools/bin/trialmode.sh " + d_ptr->appDir + " " + d_ptr->runtimeDir + " " + d_ptr->baseDir + " " + KMUtil::getLibraryDir() + " " + d_ptr->runCommands;
        int ret = system(cmd.c_str());
        if (ret != 0)
        {
            KMError("Failed to run trial mode");
            return false;
        }
        return true;
    }

    // 判断是否已经运行,若已经运行则进入已运行的容器环境内运行
    if (KMRunnerOnce::run(d_ptr->appId, d_ptr->runCommands, d_ptr->sockPath, d_ptr->envs))
    {
        return d_ptr->server.wait();
    }

    // 挂载base/runtime/app
    if (!mountLayers())
    {
        KMError("mount layers failed");
        return false;
    }

    // 挂载基础环境
    if (!mountBase())
    {
        KMError("mount others failed");
        return false;
    }

    // 挂载数据目录
    if (!mountData())
    {
        KMError("mount data failed");
        return false;
    }

    // 挂载gpu显卡驱动
    if (!mountGpu())
    {
        KMError("mount gpu failed");
        return false;
    }

    // 处理二进制依赖
    if (!mountDepandApps())
    {
        KMError("mount depend apps failed");
        return false;
    }

    // 权限管控
    if (!permissionControl())
    {
        KMError("permission control failed");
        return false;
    }

    // 处理运行参数
    if (!setProcessCmd())
    {
        KMError("set process failed");
        return false;
    }

    // 运行
    if (!run())
    {
        KMError("kaiming run failed");
        return false;
    }

    return true;
}

/**
 * @brief 设置交互tty
 * @return true 成功 false 失败
 */
bool KMRunner::setupInterTty()
{
    // wait(true阻塞等待，false不阻塞),与detach相反
    if (!d_ptr->options->isDetach())
    {
        d_ptr->container->setProcessTerminal(true);
        startUnixSocketServer();
    }

    return true;
}

/**
 * @brief 运行
 * @return true 成功 false 失败
 */
bool KMRunner::run()
{
    std::string runDir, containerId, crunDir, cmd;
    if (!d_ptr->container->preRun(runDir, containerId))
    {
        return false;
    }

    cmd = assembleRunCommand(containerId, runDir);
    if (!KMRunnerOnce::runCmd(cmd, d_ptr->appId, containerId))
    {
        d_ptr->server.stop();
        return false;
    }

    // 等待 socket server 完成
    return d_ptr->server.wait();
}

/**
 * @brief 构建run参数
 * @param containerId 容器ID
 * @param runDir 运行目录
 * @return 返回 std::string类型的cmd字符串
 */
std::string KMRunner::assembleRunCommand(const std::string &containerId, const std::string &runDir)
{
    std::string cmd;
    cmd.append("run --detach");
    if (!d_ptr->sockPath.empty())
    {
        cmd.append(" --console-socket=").append(d_ptr->sockPath);
    }
    cmd.append(" -b ").append(runDir).append(" ").append(containerId);
    return cmd;
}

/**
 * @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.getAppId(d_ptr->appId))
    {
        KMError("appid is empty");
        return false;
    }

    if (!ref.getArch(d_ptr->arch))
    {
        KMError("get arch 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.getVersion(d_ptr->version))
    {
        KMError("get version 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();

    KMDebug("app dir: " + d_ptr->appDir + ", base dir: " + d_ptr->baseDir + ", runtime dir: " + d_ptr->runtimeDir);

    return true;
}

bool KMRunner::isTrialMode()
{
    std::ifstream cmdline("/proc/cmdline");
    if (!cmdline.is_open())
    {
        KMError("failed to open /proc/cmdline");
        return false;
    }

    std::string line;
    std::getline(cmdline, line);
    return line.find("live") != std::string::npos;
}

/**
 * @brief 创建appdate子目录
 * @return true 成功 false 失败
 */
bool KMRunner::ensureAppDataDir()
{
    if (!isExistHomeDir())
    {
        KMError("home dir is empty");
        return false;
    }

    if (!getAppDataPath())
    {
        return false;
    }

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

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

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

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

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

    return true;
}

/**
 *@brief 获取appdata路径
 *@return true 成功 false 失败
 */
bool KMRunner::getAppDataPath()
{
    d_ptr->appDataPath = d_ptr->homeDir + string("/.var/app/") + d_ptr->appId;
    return true;
}

/**
 *@brief 设置容器annotation信息
 */
void KMRunner::setAnnotationInfo()
{
    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);
}

/**
 * @brief 挂载app,base,runtime目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountLayers()
{
    setAnnotationInfo();

    /* mount overlayfs /proc /sys /dev /run属于特殊的内存文件系统,不属于具体的硬件设备,无须叠加
        /media /cdrom /mnt /home /root 属于数据保存目录，无需叠加  */
    std::vector<std::string> ovlDir = { "/usr", "/lib", "/lib32", "/lib64", "/bin", "/sbin", "/etc" };
    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(ovlDir.begin(), ovlDir.end(), dir) != ovlDir.end())
        {
            overlayDir(dir);
        }
    }

    // 叠加share目录
    if (!overlayShare())
    {
        KMError("overlay share failed");
        return false;
    }
    // 创建usr子目录软连接
    createUsrSymlinkSubdir("share", "../share");
    createUsrSymlinkSubdir("lib", "../lib");
    createUsrSymlinkSubdir("lib32", "../lib32");
    createUsrSymlinkSubdir("lib64", "../lib64");
    createUsrSymlinkSubdir("bin", "../bin");
    createUsrSymlinkSubdir("sbin", "../sbin");

    std::error_code ec;
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string appDir = d_ptr->appDir + string("/files");
    if (fs::exists(appDir, ec))
    {
        // 使用app数据配置目录
        std::vector<std::string> dirs = { "/opt", "/var", "/srv" };
        for (auto dir : dirs)
        {
            std::string srcDir = appDir + dir;
            mountDir(srcDir, dir, type, options);
        }
        if (!d_ptr->annotations.sysapp)
        {
            // 按照标准规范绑定挂载目录
            std::string dstDir = "/opt/apps/" + d_ptr->appId + "/files";
            d_ptr->container->addMount(Mount{ .source = appDir, .destination = dstDir, .type = type, .options = options });
        }
    }

    // 持久化存储家目录
    PerStorageHome();

    return true;
}

/**
 * @brief 创建usr子目录软连接
 * @param link 软连接文件
 * @param target 软连接目标
 * @return true 成功 false 失败
 */
void KMRunner::createUsrSymlinkSubdir(const std::string &link, const std::string &target)
{
    // 创建挂载软连接
    std::error_code ec;
    std::string linkDir = d_ptr->appDataPath + "/upperdir/usr/" + link;
    if (fs::is_symlink(linkDir, ec))
    {
        return;
    }

    if (fs::is_directory(linkDir, ec))
    {
        fs::remove_all(linkDir, ec);
    }

    fs::create_symlink(target, linkDir, ec);
}

/**
 * @brief 持久化存储家目录信息
 * @return true 成功 false 失败
 */
bool KMRunner::PerStorageHome()
{
    // 持久化存储,每个app都需要家目录需创建一些必要的空目录,存放自己的配置文件等
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";
    uid_t uid = getuid();
    if (uid == 0)
    {
        // root级服务需要可以访问home,run目录
        mountDir("/home", "/home", type, options);
        mountDir(d_ptr->homeDir, d_ptr->homeDir, type, options);
        return true;
    }

    if (d_ptr->perms.all)
    {
        mountDir(d_ptr->homeDir, d_ptr->homeDir, type, options);
        return true;
    }

    std::error_code ec;
    std::string homedir = d_ptr->appDataPath + string("/hostcache") + d_ptr->homeDir;
    if (!fs::exists(homedir, ec))
    {
        std::vector<std::string> dirs = { ".config", ".local", ".log" };
        for (auto const &dir : dirs)
        {
            std::string src = homedir + string("/") + dir;
            if (!fs::exists(src, ec))
            {
                fs::create_directories(src, ec);
            }
        }
    }
    d_ptr->container->addMount(Mount{ .source = homedir, .destination = d_ptr->homeDir, .type = type, .options = options });

    // 绑定用户目录,服务级进程不需要绑定xdg规范目录
    if (d_ptr->perms.xdgUserDirs)
    {
        // 绑定userdir指定目录
        std::vector<std::string> userDirs = { "桌面", "视频", "音乐", "文档", "图片", "公共", "下载", "模板" };
        for (auto const &subdir : userDirs)
        {
            std::string userdir = d_ptr->homeDir + string("/") + subdir;
            if (fs::exists(userdir, ec))
            {
                d_ptr->container->addMount(Mount{ .source = userdir, .destination = userdir, .type = type, .options = options });
            }
        }
    }

    return true;
}

/**
 * @brief 设置process
 * @return true 成功 false 失败
 */
bool KMRunner::setProcessCmd()
{
    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::mountStartsh()
{
    string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string dst = "/opt/apps/kaiming/bin/" + d_ptr->appId;
    std::string src = "/opt/kaiming-tools/bin/start.sh";
    d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = options });
    return true;
}

/**
 * @brief 设置进程运行命令
 * @return true 成功 false 失败
 */
bool KMRunner::setProcessCmdArgs()
{
    std::string cwd;
    if (KMUtil::getCwdDir(cwd))
    {
        d_ptr->container->setProcessCwd(cwd);
    }
    else
    {
        d_ptr->container->setProcessCwd(d_ptr->homeDir);
    }

    if (d_ptr->runCommands.empty())
    {
        KMError("run command is empty");
        return false;
    }

    d_ptr->container->genRunDir(d_ptr->runDir, d_ptr->containerId);

    int polkit = 0;
    std::error_code ec;
    std::string polkitDir = d_ptr->appDir + "/entries/share/polkit-1/actions";
    if (d_ptr->annotations.polkit || (fs::exists(polkitDir, ec) && !fs::is_empty(polkitDir, ec)))
    {
        polkit = 1;
    }

    std::vector<string> args = { "/bin/bash", "-c" };
    std::string additionalCommand = "/opt/apps/kaiming/bin/" + d_ptr->appId + " " + d_ptr->appId + " " + std::to_string(polkit) + " " + d_ptr->runCommands;
    args.emplace_back(additionalCommand);
    d_ptr->container->setProcessArgs(args);

    return true;
}

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

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

    setProcessCap(allCap);

    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);

    if (d_ptr->annotations.privilege)
    {
        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;
}

/**
 * @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::error_code ec;
    std::map<std::string, std::string> newEnvs;
    auto sysAddress = getenv("DBUS_SYSTEM_BUS_ADDRESS");
    if (sysAddress != nullptr)
    {
        newEnvs["DBUS_SYSTEM_BUS_ADDRESS"] = string(sysAddress);
    }
    else if (fs::exists("/run/dbus/system_bus_socket", ec))
    {
        newEnvs["DBUS_SYSTEM_BUS_ADDRESS"] = string("unix:path=/run/dbus/system_bus_socket");
    }

    if (uid_t loginuid; getLoginUid(loginuid))
    {
        auto sessionAddress = getenv("DBUS_SESSION_BUS_ADDRESS");
        string session = (sessionAddress == nullptr) ? string("unix:path=") + string("/run/user/") + to_string(loginuid) + string("/bus") : string(sessionAddress);
        newEnvs["DBUS_SESSION_BUS_ADDRESS"] = session;

        newEnvs["XDG_RUNTIME_DIR"] = string("/run/user/") + to_string(loginuid);

        std::string pulseDir = string("/run/user/") + to_string(loginuid) + "/pulse";
        std::string pulseSocket = pulseDir + "/native";
        if (!fs::exists(pulseSocket, ec))
        {
            if (fs::exists("/var/run/pulse/native", ec))
            {
                pulseSocket = "/var/run/pulse/native";
            }
            else
            {
                pulseSocket = "";
            }
        }

        if (!pulseSocket.empty())
        {
            d_ptr->pulseSocket = pulseSocket;
            string configPath = KMFolder::getPulseRuntimePath() / "config";
            newEnvs["PULSE_SERVER"] = pulseSocket;
            newEnvs["PULSE_CLIENTCONFIG"] = configPath;
        }

        auto homeDir = d_ptr->homeDir;
        string xauthFile;
        auto pXauthFile = getenv("XAUTHORITY");
        if (pXauthFile != nullptr && fs::exists(pXauthFile, ec))
        {
            xauthFile = string(pXauthFile);
        }
        else
        {
            xauthFile = homeDir + string("/.Xauthority");
        }
        newEnvs["XAUTHORITY"] = xauthFile;

        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 (isatty(fileno(stdin)) == 1)
    {
        if (std::string appDesktopPath = string("/opt/kaiming/exports/share/applications/") + d_ptr->appId + ".desktop"; fs::exists(appDesktopPath, ec))
        {
            newEnvs["PANSHI_APP_DESKTOP"] = appDesktopPath;
        }
        else if (appDesktopPath = string("/opt/kaiming/share/applications/") + d_ptr->appId + ".desktop"; fs::exists(appDesktopPath, ec))
        {
            newEnvs["PANSHI_APP_DESKTOP"] = appDesktopPath;
        }
    }
    else
    {
        auto desktopFile = getenv("GIO_LAUNCHED_DESKTOP_FILE");
        if (desktopFile != nullptr)
        {
            newEnvs["PANSHI_APP_DESKTOP"] = string(desktopFile);
            newEnvs["GIO_LAUNCHED_DESKTOP_FILE"] = string(desktopFile);
        }
    }

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

    // 设置SessionManager环境变量
    auto sessionManagerEnv = getenv("SESSION_MANAGER");
    if (sessionManagerEnv != nullptr)
    {
        newEnvs["SESSION_MANAGER"] = std::string(sessionManagerEnv);
    }

    // 设置Version环境变量
    newEnvs["APP_VERSION"] = d_ptr->version;

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

    // 增加QT相关环境变量
    newEnvs["QML2_IMPORT_PATH"] = string("/lib64/qml:") + string("/lib/qml");
    std::string platLibDir = std::string("/usr/lib/") + KMUtil::getLibraryDir();
    std::string glExtendDir = string("/etc/egl/egl_external_platform.d:") + platLibDir + "/GL/egl/egl_external_platform.d:" + "/usr/share/egl/egl_external_platform.d";
    newEnvs["__EGL_EXTERNAL_PLATFORM_CONFIG_DIRS"] = glExtendDir;

    // 增加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");

    newEnvs["QT_ACCESSIBILITY"] = "1";
    newEnvs["QT_LINUX_ACCESSIBILITY_ALWAYS_ON"] = "1";

    // 增加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, "");
            }
        }
    }

    // 后续的PATH和LD_LIBRARY_PATH不能完全被用户设置的替换
    newEnvs.clear();

    // 设置PATH环境变量
    std::string valueOfpath;
    for (const auto &[k, v] : envs)
    {
        if (k == "PATH")
        {
            valueOfpath = v;
        }
    }
    std::string pathEnv = "/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/bin:/usr/local/sbin:/usr/libexec:/usr/games:/opt/kaiming/bin";
    std::string standardOptPath = string("/opt/apps/") + d_ptr->appId + string("/files/bin") + ":" + string("/opt/apps/") + d_ptr->appId + string("/files/local/bin:");
    std::string extendPath = valueOfpath.empty() ? "" : (valueOfpath + ":");
    newEnvs["PATH"] = extendPath + pathEnv;
    if (!d_ptr->annotations.sysapp)
    {
        newEnvs["PATH"] = standardOptPath + extendPath + pathEnv;
    }

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

    std::string defLibraryPath = "/usr/lib:/lib:/usr/local/lib:/usr/lib64:/usr/lib32:/lib64:/lib32";
    if (!valueOfldlibrarypath.empty())
    {
        defLibraryPath = valueOfldlibrarypath + ":" + defLibraryPath;
    }
    newEnvs["LD_LIBRARY_PATH"] = defLibraryPath;
    if (!d_ptr->annotations.sysapp)
    {
        std::string standard = string("/opt/apps/") + d_ptr->appId + string("/files/lib") + string(":") + string("/opt/apps/") + d_ptr->appId + string("/files/local/lib:");
        newEnvs["LD_LIBRARY_PATH"] = standard + defLibraryPath;
    }

    // 更新环境变量,主要修改PATH和LD_LIBRARY_PATH
    for (const auto &[k, v] : newEnvs)
    {
        envs[k] = v;
    }

    // 修改环境变量格式
    for (const auto &[k, v] : envs)
    {
        d_ptr->envs.emplace_back(k + "=" + v);
    }

    d_ptr->container->setProcessEnv(d_ptr->envs);

    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("bind");
    options = { "rbind", "rprivate" };
    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" };
    mountDir(src, dst, type, options);

    dst = string("/tmp");
    src = string("/tmp");
    type = string("bind");
    options = { "rbind", "rprivate" };
    mountDir(src, dst, type, options);

    dst = string("/sys");
    src = string("/sys");
    type = string("bind");
    options = { "rbind", "rprivate" };
    mountDir(src, dst, type, options);

    // 解决udev管控信息
    src = string("/run/udev");
    dst = string("/run/udev");
    options = { "rbind", "rprivate" };
    mountDir(src, dst, type, options);

    // 解决systemd信息
    src = string("/run/systemd");
    dst = string("/run/systemd");
    options = { "rbind", "rprivate" };
    mountDir(src, dst, type, options);

    // 挂载用户运行信息
    src = string("/run/user/") + std::to_string(getuid());
    dst = src;
    options = { "rbind", "rprivate" };
    mountDir(src, dst, type, options);

    return true;
}

/**
 * @brief 挂载var基础目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountVar()
{
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";

    // 挂载var临时目录
    mountDir("/var/tmp", "/var/tmp", type, options);

    // 挂载var缓存目录
    mountDir("/var/cache", "/var/cache", type, options);

    // 挂载var日志目录
    mountDir("/var/log", "/var/log", type, 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("/dev");
    type = string("bind");
    options = { "rbind", "rprivate" };
    mountDir(src, dst, type, options);

    if ((d_ptr->perms.all || d_ptr->perms.microphone) && (!mountPulseaudio() || !mountAlsa()))
    {
        KMError("mount audio config 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;
                    break;
                }
            }
            if (!isControlDevice)
            {
                continue;
            }

            permDev(dev);
        }
    }

    return true;
}

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

    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 ovl = d_ptr->appDataPath + "/upperdir" + dev;
        if (!fs::exists(ovl, ec))
        {
            std::ofstream(ovl, std::ios::trunc);
        }
        options = { "rbind", "rprivate" };
        d_ptr->container->addMount(Mount{ .source = ovl, .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 挂载overlay 
 * @param lowers目录
 * @param upper目录
 * @param merge目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountOverlay(const std::vector<std::string> &lowers, const std::string &upper, const std::string &merge)
{
    // 多个挂载不能使用同一upperdir,workdir,否则会导致未知风险问题
    std::error_code ec;
    std::string workdir = d_ptr->appDataPath + "/workdir" + upper;
    std::string upperdir = d_ptr->appDataPath + "/upperdir" + upper;
    if (!fs::exists(upperdir, ec) || !fs::exists(workdir, ec))
    {
        fs::create_directories(upperdir, ec);
        fs::create_directories(workdir, ec);
    }

    string upperOpt = string("upperdir=") + upperdir;
    string workOpt = string("workdir=") + workdir;
    string lowerOpt = "lowerdir=";

    for (auto const &dir : lowers)
    {
        appendLowerDir(lowerOpt, dir);
    }

    // 判断是否存在lower层
    if (lowerOpt == "lowerdir=")
    {
        return true;
    }

    std::vector<std::string> options = { lowerOpt, upperOpt, workOpt };

    if (KMOverlay::isOverlayFsIndexOff())
    {
        options.emplace_back("index=off");
    }

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

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

    return true;
}

/**
 * @brief 挂载share目录
 * @return true 成功 false 失败
 */
bool KMRunner::overlayShare()
{
    // 叠加share目录
    std::vector<std::string> shareDirs = {
        d_ptr->appDir + "/files/share",
        d_ptr->appDir + "/files/usr/share",
        d_ptr->appDir + "/depends/usr/share",
        d_ptr->appDir + "/depends/share",
        d_ptr->runDir + "/files/usr/share",
        d_ptr->baseDir + "/files/usr/share",
        "/opt/kaiming/exports/share",
        "/opt/kaiming/share",
        "/opt/system/resource",
        "/usr/share"
    };
    return mountOverlay(shareDirs, "/share", "/share");
}

/**
 * @brief 挂载share,包含字体,icon等
 * @return true 成功 false 失败
 */
bool KMRunner::mountShare()
{
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };

    // 挂载主题配置
    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);
    }

    // 挂载用户目录缓存
    if (!d_ptr->perms.all)
    {
        std::string cacheDir = d_ptr->homeDir + "/.cache";
        mountDir(cacheDir, cacheDir, 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 叠加目录
 * @param dir overlay目录路径
 * @param isHost 是否叠加宿主机目录
 */
void KMRunner::overlayDir(const std::string &dir)
{
    const std::vector<std::string> dirs = {
        d_ptr->appDir + string("/files") + dir,
        d_ptr->appDir + string("/files/usr") + dir,
        d_ptr->appDir + string("/depends") + dir,
        d_ptr->appDir + string("/depends/usr") + dir,
        d_ptr->runtimeDir + string("/files") + dir,
        d_ptr->runtimeDir + string("/files/usr") + dir,
        d_ptr->baseDir + string("/files") + dir,
        d_ptr->baseDir + string("/files/usr") + dir
    };
    std::vector<std::string> lowers;
    std::error_code ec;
    for (auto &dir : dirs)
    {
        if (!fs::is_symlink(dir, ec))
        {
            lowers.emplace_back(dir);
        }
    }

    if (!lowers.empty())
    {
        mountOverlay(lowers, dir, dir);
    }
}

/**
 * @brief 追加lowerdir
 * @param lowerdir lowerdir
 * @param dir 追加的目录
 */
void KMRunner::appendLowerDir(std::string &lowerdir, const std::string &dir) const
{
    std::error_code ec;
    if (!dir.empty() && fs::exists(dir, ec))
    {
        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";
    mountDir(gssproxy, gssproxy, type, options);
}

/**
 * @brief 挂载resolved配置
 */
void KMRunner::mountResolved()
{
    std::string resolved = "/run/systemd/resolve/io.systemd.Resolve";
    std::vector<string> options = { "rbind", "ro", "rprivate" };
    std::string type = "bind";
    mountDir(resolved, resolved, type, 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";
    mountDir(journalSocket, journalSocket, type, options);
    mountDir(journalStdout, journalStdout, type, options);
}

/**
 * @brief 挂载pulseaudio配置
 * @return true 成功 false 失败
 */
bool KMRunner::mountPulseaudio()
{
    if (!d_ptr->pulseSocket.empty())
    {
        // 设置挂载
        std::string parentDir = fs::path(d_ptr->pulseSocket).parent_path().string();
        std::string pulseConfig = "/opt/kaiming-tools/config/pulse-config";
        string configPath = parentDir + "/config";
        std::string type = "bind";
        std::vector<std::string> options = { "rbind", "rprivate" };
        mountDir(d_ptr->pulseSocket, d_ptr->pulseSocket, type, options);
        mountDir(pulseConfig, configPath, type, options);
    }

    return true;
}

/**
 * @brief 挂载alsa配置
 * @return true 成功 false 失败
 */
bool KMRunner::mountAlsa()
{
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    mountDir("/usr/share/alsa", "/usr/share/alsa", type, options);
    mountDir("/etc/alsa", "/etc/alsa", type, options);
    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
    uid_t uid = getuid();
    if (uid != 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
        {
            std::error_code ec;
            std::string session = "/run/user/" + std::to_string(uid) + "/bus";
            if (!fs::exists(session, ec))
            {
                KMInfo("DBUS_SESSION_BUS_ADDRESS not found");
            }
            else
            {
                mountDir(session, session, type, roOptions);
            }
        }
    }

    return true;
}

/**
 * @brief : 挂载x11
 * @return true 成功 false 失败
 */
bool KMRunner::mountX11()
{
    // 因为/tmp默认挂载,所以此挂载注释掉即可
    // 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;
    }

    std::vector<std::string> options = { "rbind", "ro", "rprivate" };
    mountDir(waylandSocker, waylandSocker, "bind", options);

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

    return true;
}

/**
 * @brief 挂载x11-wayland兼容层
 */
void KMRunner::mountX11Wayland()
{
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";
    std::string src = "/opt/kaiming-tools/bin/x11-ext.sh";
    std::string dst = "/opt/x11-wayland/x11-ext.sh";
    mountDir(src, dst, type, options);
}

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

    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;
    }

    if (!mountDependAppsDir())
    {
        // 非重要致命性挂载,即使失败也不应该返回
        KMError("mount depend apps directory failed");
    }

    if (!mountStartsh())
    {
        KMError("mount crun config dir failed");
        return false;
    }

    return true;
}

/**
 * @brief 挂载依赖应用目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountDependAppsDir()
{
    // 挂载依赖应用目录
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "ro", "rprivate" };
    std::string src = "/opt/kaiming/bin";
    mountDir(src, src, type, options);

    // 挂载dbus客户端
    std::string srcCli = "/opt/kaiming-tools/bin/dbus-cli.sh";
    std::string dst = "/opt/kaiming-tools/bin/kaiming";
    mountDir(srcCli, dst, type, options);

    return true;
}

/**
 * @brief 处理依赖应用问题
 * @return true 成功 false 失败
 */
bool KMRunner::mountDepandApps()
{
    // xdg-open 默认兼容
    d_ptr->annotations.dependApps.emplace_back("/usr/bin/xdg-open");

    // 挂载依赖
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";
    std::string proxyCli = "/opt/kaiming-tools/bin/dbus-cli.sh";
    for (auto &app : d_ptr->annotations.dependApps)
    {
        // 若不是绝对路径，则添加默认路径
        if (app.at(0) != '/')
        {
            app = std::string("/usr/bin/") + app;
        }

        mountDir(proxyCli, app, type, options);
    }

    return true;
}

/**
 * @brief 挂载共享目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountShareData()
{
    // 挂载用户数据目录
    std::error_code ec;
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    if (fs::exists("/data", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/data", .destination = "/data", .type = type, .options = options });
    }
    if (fs::exists("/srv", ec) && !fs::exists(d_ptr->appDir + "/files/srv", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/srv", .destination = "/srv", .type = type, .options = options });
    }

    // 处理移动存储设备
    d_ptr->container->setRootfsPropagation("shared"); // 设置/根挂载属性为从属,即只能接收传播,不能对外传播
    options = { "rbind", "rshared" };
    if (fs::exists("/cdrom", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/cdrom", .destination = "/cdrom", .type = type, .options = options });
    }
    if (fs::exists("/run/media", ec) && !fs::is_symlink("/run/media", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/run/media", .destination = "/run/media", .type = type, .options = options });
    }
    if (fs::exists("/media", ec) && !fs::is_symlink("/media", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/media", .destination = "/media", .type = type, .options = options });
    }
    if (fs::exists("/mnt", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/mnt", .destination = "/mnt", .type = type, .options = options });
    }

    return true;
}

/**
 * @brief 挂载许可
 * @return true 成功 false 失败
 */
bool KMRunner::mountXauthority()
{
    // 此配置不应该影响应用的正常启动
    if (getuid() == 0)
        return true;

    auto pXauthFile = getenv("XAUTHORITY");
    std::string xauthFile;
    if (pXauthFile == nullptr)
    {
        xauthFile = d_ptr->homeDir + string("/.Xauthority");
    }
    else
    {
        xauthFile = string(pXauthFile);
    }

    std::vector<std::string> options = { "rbind", "rprivate" };
    mountDir(xauthFile, xauthFile, "bind", options);

    return true;
}

/**
 * @brief 权限管控
 * @return true 成功 false 失败
 */
bool KMRunner::permissionControl()
{
    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()
{
    // 绑定指定路径挂载
    std::error_code ec;
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    for (auto &specdir : d_ptr->perms.filesystemDirs)
    {
        if (specdir[0] == '~')
        {
            if (specdir.length() > 1)
            {
                specdir = d_ptr->homeDir + specdir.substr(1);
            }
            else
            {
                specdir = d_ptr->homeDir;
            }
        }

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

        mountDir(specdir, specdir, type, 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";
    mountDir(etcAutoStart, etcAutoStart, type, options);
    std::string homeAutoStart = d_ptr->homeDir + "/.config/autostart";
    mountDir(homeAutoStart, homeAutoStart, type, options);

    return true;
}

/**
 * @brief 挂载dconf目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountDconf()
{
    std::string type = "bind";
    std::vector<std::string> options = { "rbind", "rprivate" };
    if (getuid() == 0)
    {
        return true;
    }

    // 挂载 dconf

    std::string dconf = d_ptr->homeDir + "/.config/dconf";
    std::error_code ec;
    if (fs::exists(dconf, ec))
    {
        d_ptr->container->addMount(Mount{ .source = dconf, .destination = dconf, .type = type, .options = options });
        std::string runDconf = std::string("/run/user/") + std::to_string(getuid()) + "/dconf";
        mountDir(runDconf, runDconf, type, options);

        string userDirs = d_ptr->homeDir + "/.config/user-dirs.dirs";
        mountDir(userDirs, userDirs, type, options);

        string userDirsLocale = d_ptr->homeDir + "/.config/user-dirs.locale";
        mountDir(userDirsLocale, userDirsLocale, type, options);
    }

    return true;
}

/**
 * @brief 挂载etc目录
 * @return true 成功 false 失败
 */
bool KMRunner::mountEtc()
{
    std::string type = "bind";
    std::vector<std::string> roOptions = { "rbind", "ro", "rprivate" };
    // 挂载账户信息
    mountDir("/etc/passwd", "/etc/passwd", type, roOptions);
    mountDir("/etc/group", "/etc/group", type, roOptions);

    std::error_code ec;
    if (!fs::exists(d_ptr->baseDir + "/files/pkcs11/pkcs11.conf", ec))
    {
        std::string pkcsconf = d_ptr->appDataPath + string("/hostcache") + string("/pkcs11.conf");
        if (!fs::exists(pkcsconf, ec))
        {
            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();
        }

        mountDir(pkcsconf, "/etc/pkcs11/pkcs11.conf", type, roOptions);
    }

    // 处理/etc/mtab
    std::string mtab = d_ptr->appDataPath + "/upperdir/etc/mtab";
    fs::create_symlink("../proc/self/mounts", mtab, ec);

    // 挂载文管配置
    mountDir("/etc/xdg/peony-data.conf", "/etc/xdg/peony-data.conf", type, roOptions);

    // 挂载机器ID
    mountDir("/etc/machine-id", "/etc/machine-id", type, roOptions);
    mountDir("/var/lib/dbus/machine-id", "/var/lib/dbus/machine-id", type, roOptions);

    // 挂载resolv路由
    mountDir("/etc/resolv.conf", "/etc/resolv.conf", type, roOptions);

    // 挂载host信息
    mountDir("/etc/host.conf", "/etc/host.conf", type, roOptions);
    mountDir("/etc/hosts", "/etc/hosts", type, roOptions);
    mountDir("/etc/hostname", "/etc/hostname", type, roOptions);

    // 挂载gai.conf
    mountDir("/etc/gai.conf", "/etc/gai.conf", type, roOptions);

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

    if (fs::exists("/usr/share/zoneinfo", ec))
    {
        d_ptr->container->addMount(Mount{ .source = "/usr/share/zoneinfo", .destination = "/usr/share/zoneinfo", .type = type, .options = roOptions });
        if (fs::exists(localtimeZone, ec))
        {
            std::string upperLocaltime = d_ptr->appDataPath + "/upperdir/etc";
            if (fs::exists(upperLocaltime, ec))
            {
                fs::create_symlink(localtimeZone, upperLocaltime + "/localtime", ec);
            }
        }
    }

    if (fs::exists("/etc/timezone, ec"))
    {
        d_ptr->container->addMount(Mount{ .source = "/etc/timezone", .destination = "/etc/timezone", .type = type, .options = roOptions });
    }
    else
    {
        std::string src = string("/var/db/zoneinfo");
        std::string dst = string("/etc/timezone");
        if (fs::exists(src, ec))
        {
            d_ptr->container->addMount(Mount{ .source = src, .destination = dst, .type = type, .options = roOptions });
        }
        else
        {
            // 挂载/etc/timezone
            std::string timezoneFile = d_ptr->appDataPath + "/hostcache" + "/timezone";
            if (!fs::exists(timezoneFile, ec))
            {
                std::ofstream ofs(timezoneFile, 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();
            }

            mountDir(timezoneFile, "/etc/timezone", type, 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 挂载指定目
 */
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;
    }

    std::error_code ec;
    if (fs::exists(hostDir, ec))
    {
        std::string dst = d_ptr->appDataPath + "/upperdir" + containDir;
        if (!fs::exists(dst, ec))
        {
            std::vector<std::string> ovls = { "/usr", "/lib", "/lib32", "/lib64", "/bin", "/sbin", "/etc" };
            size_t pos = containDir.find('/', 1);
            std::string dir = containDir;
            if (pos != std::string::npos)
            {
                dir = containDir.substr(0, pos);
            }
            if (std::find(ovls.begin(), ovls.end(), dir) != ovls.end())
            {
                // 创建overlay需要的upperdir目录
                if (fs::is_directory(hostDir, ec))
                {
                    fs::create_directories(dst, ec);
                }
                else
                {
                    fs::path parent = fs::path(dst).parent_path();
                    if (!fs::exists(parent, ec))
                    {
                        fs::create_directories(parent, ec);
                    }
                    std::ofstream(dst, std::ios::trunc);
                }
            }
        }
        d_ptr->container->addMount(Mount{ .source = hostDir, .destination = containDir, .type = type, .options = options });
    }
}

/**
 * @brief 家目录是否存在
 * @return true 存在 false 不存在
 */
bool KMRunner::isExistHomeDir()
{
    return KMUtil::getHomeDir(d_ptr->homeDir);
}

/**
 * @brief 启动Unix Socket服务器
 * @return true 存在 false 不存在
 */
bool KMRunner::startUnixSocketServer()
{
    if (!d_ptr->server.create())
        return false;

    d_ptr->sockPath = d_ptr->server.getPath();

    return d_ptr->server.run();
}

/**
 * @brief 获取登录用的uid
 * @param uid 用户ID
 * @return true 存在 false 不存在
 */
bool KMRunner::getLoginUid(uid_t &uid)
{
    uid = getuid();
    if (uid != 0)
    {
        return true;
    }
    else
    {
        const char *command = "loginctl list-sessions --no-legend | awk '/seat0/ {print $2}' | head -n 1";
        const auto ret = KMProcessUtils::execCmd(command);
        if (ret.first.empty())
        {
            KMError("Failed to get login session ID");
            return false;
        }
        else
        {
            uid = std::stoi(ret.first);
            if (uid < 1000)
            {
                return false;
            }
            return true;
        }
    }
}

/**
 * @brief 挂载GPU显卡驱动 
 * @return true 存在 false 不存在
 */
bool KMRunner::mountGpu()
{
    if (!d_ptr->annotations.gpu)
    {
        return true;
    }

    std::string archDir = KMUtil::getLibraryDir();
    std::vector<std::string> options = { "rbind", "rprivate" };
    std::string type = "bind";
    for (auto &gpu : gpus)
    {
        std::string dir = gpu;
        KMStringUtils::replace(dir, "myarch-linux-gnu", archDir);
        mountDir(dir, dir, type, options);
    }

    return true;
}
