#pragma once #include #include #include #include #include namespace qing { /* 子系统类 */ class Modules { public: /* 传入子系统的路径 然后验证是否存在 */ Modules(std::string& mods) { this->home = mods; if (!is_exist(this->home)) throw SubsystemNotExist(mods); } /* * 获取子系统下某个模块的启动脚本路径 * * NOTE: 防注入检查是必须的 */ std::string GetInitp(std::string name) { std::string ret = get_mod_init_path(name); if (is_exist(ret)) { return ret; } else { throw InitScriptNotExist(ret); } } /* * 列出子系统下的所有模块 * * 优化建议:做抽象层表示模块概念 */ std::vector ListAll() { std::vector folders; try { for (const auto& entry: std::filesystem::directory_iterator(this->home)) if (entry.is_directory()) folders.push_back(entry.path().filename().string()); } catch(const std::filesystem::filesystem_error& e) { ListModulesFailed(this->home, e.what()); } return folders; } /* 在该子系统下创建一个初始模块 */ void CrtMod(std::string &name) { crt_mod_dir(name); init_mod_dir(name); init_mod_man(name); grd_priv(name); } /* 删除子系统下一个模块 */ void DelMod(std::string &name) { std::string fullpath = get_mod_path(name); deleteDirectory(fullpath); } /* 子系统异常模块 */ class Mods_Exp: public std::runtime_error { public: explicit Mods_Exp(const std::string& msg): std::runtime_error(msg) { ; } }; /* 子系统不存在异常 */ class SubsystemNotExist: public Mods_Exp { public: explicit SubsystemNotExist(const std::string &name): Mods_Exp("Target subsystem " + name + " not exists.") { ; } }; /* 启动脚本不存在异常 */ class InitScriptNotExist: public Mods_Exp { public: explicit InitScriptNotExist(const std::string &name): Mods_Exp("Target init script " + name + " not exists") { ; } }; /* 列举模块失败异常 */ class ListModulesFailed: public Mods_Exp { public: explicit ListModulesFailed(const std::string &name, const std::string &reson): Mods_Exp("Error when read subsystem <" + name + "> , because " + reson) { ; } }; /* 要创建的路径已经存在 */ class AlreadyExist: public Mods_Exp { public: explicit AlreadyExist(const std::string &name): Mods_Exp(name) { ; } }; /* 创建失败 */ class CreateFailed: public Mods_Exp { public: explicit CreateFailed(const std::string &name): Mods_Exp(name) { ; } }; /* 提升权限失败 */ class GrandPrivilegesFailed: public Mods_Exp { public: explicit GrandPrivilegesFailed(const std::string &name): Mods_Exp(name) { ; } }; /* 删除失败 */ class DeleteFailed: public Mods_Exp { public: explicit DeleteFailed(const std::string &name): Mods_Exp(name) { ; } }; private: /* 子系统的模块目录 */ std::string home; /* 创建模块目录*/ void crt_mod_dir(std::string name) { std::string fullpath = get_mod_path(name); if (is_exist(fullpath)) { throw AlreadyExist(name); } else { std::filesystem::create_directory(fullpath); } } /* 初始化模块目录,创建启动脚本 */ void init_mod_dir(std::string name) { std::string fullpath = get_mod_init_path(name); if (is_exist(fullpath)) { throw AlreadyExist(name); } else { std::ofstream outFile = std::ofstream(fullpath); if (outFile) { outFile << "#!/bin/bash\n"; outFile << "cd \"$(dirname \"$0\")\" || exit\n\n"; outFile << "exec echo hello!"; } else { throw CreateFailed(name); } } } /* 初始化一个模块的手册(README.md)*/ void init_mod_man(std::string name) { std::string fullpath = get_mod_man_path(name); if(is_exist(fullpath)) { throw AlreadyExist(fullpath); } else { std::ofstream outFile = std::ofstream(fullpath); if (outFile) { outFile << "# "; outFile << name; outFile << "\n"; } else { throw CreateFailed(name); } } } /* 获取模块的路径 */ std::string get_mod_path(std::string &name) { return this->home + get_sep() + name; } /* 获取模块的启动脚本路径 */ std::string get_mod_init_path(std::string &name) { return get_mod_path(name) + get_sep()+ "_run.sh"; } /* 获取模块的手册路径 */ std::string get_mod_man_path(std::string &name) { return get_mod_path(name) + get_sep()+ "README.md"; } /* 赋予一个文件755权限 */ void grd_priv(std::string &name) { std::string fullpath = get_mod_init_path(name); if (chmod(fullpath.c_str(), 0755) == -1) { throw GrandPrivilegesFailed("path"); } } /* 获取当前可执行程序所在目录 */ static std::string get_curr() { return std::filesystem::canonical("/proc/self/exe").parent_path().string(); } /* 文件是否存在 */ static bool is_exist(std::string &path) { return std::filesystem::exists(path); } /* 获取文件系统分隔符号 */ static char get_sep() { return std::filesystem::path::preferred_separator; } /* 删除一整个文件夹 */ static void deleteDirectory(const std::filesystem::path& path) { try { /* 递归 */ std::filesystem::remove_all(path) > 0; } catch (const std::filesystem::filesystem_error& e) { throw DeleteFailed(e.what()); } } }; }