diff options
-rw-r--r-- | include/CMakeLists.txt | 3 | ||||
-rw-r--r-- | include/modules.h | 20 | ||||
-rw-r--r-- | include/version.cpp | 123 | ||||
-rw-r--r-- | src/misc.cpp | 7 | ||||
-rw-r--r-- | src/modulemanager.cpp | 86 | ||||
-rw-r--r-- | src/version.sh | 6 |
6 files changed, 166 insertions, 79 deletions
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 6170cde27..1a96d7111 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -7,7 +7,7 @@ get_target_property(version_BINARY version LOCATION) # Modify version.h from the above executable, with dependencies to version.cpp # and all of the source files in the main build add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_build - COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h + COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h DEPENDS version ${SRC_SRCS} ) # Add version to list of files for CPack to ignore @@ -15,6 +15,7 @@ get_filename_component(version_BINARY ${version_BINARY} NAME) add_to_cpack_ignored_files("${version_BINARY}$" TRUE) if(NOT WIN32) add_to_cpack_ignored_files("version.h$" TRUE) + add_to_cpack_ignored_files("build.h$" TRUE) endif(NOT WIN32) set(PCH_SOURCES_GCH "") diff --git a/include/modules.h b/include/modules.h index 5ea35c888..0c10caa7b 100644 --- a/include/modules.h +++ b/include/modules.h @@ -20,6 +20,7 @@ #include "timers.h" #include "logger.h" #include "extensible.h" +#include "version.h" /** This definition is used as shorthand for the various classes * and functions needed to make a module loadable by the OS. @@ -40,6 +41,10 @@ extern "C" void AnopeFini(x *m) \ { \ delete m; \ + } \ + extern "C" DllExport ModuleVersion AnopeVersion() \ + { \ + return ModuleVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); \ } #else # define MODULE_INIT(x) \ @@ -50,6 +55,10 @@ extern "C" DllExport void AnopeFini(x *m) \ { \ delete m; \ + } \ + extern "C" DllExport ModuleVersion AnopeVersion() \ + { \ + return ModuleVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); \ } #endif @@ -279,12 +288,6 @@ class CoreExport Module : public Extensible */ void SetAuthor(const Anope::string &author); - /** Get the version of Anope this module was - * compiled against - * @return The version - */ - ModuleVersion GetVersion() const; - virtual void Prioritize(); /* Everything below here are events. Modules must ModuleManager::Attach to these events @@ -1206,6 +1209,11 @@ class CoreExport ModuleManager * @return MOD_ERR_OK on success, anything else on fail */ static ModuleReturn DeleteModule(Module *m); + + /** Get the version of Anope the module was compiled against + * @return The version + */ + static ModuleVersion GetVersion(void *handle); }; #endif // MODULES_H diff --git a/include/version.cpp b/include/version.cpp index b0ea0423d..119403e13 100644 --- a/include/version.cpp +++ b/include/version.cpp @@ -13,7 +13,7 @@ #include <iostream> #include <fstream> #include <sstream> -#include <list> +#include <map> static std::string get_git_hash(const std::string &git_dir) { @@ -45,29 +45,16 @@ static std::string get_git_hash(const std::string &git_dir) return "g" + filebuf.substr(0, 7); } -int main(int argc, char *argv[]) +static bool read_version_sh(const std::string &version_sh, std::map<std::string, std::string> &versions) { - if (argc < 3) - { - std::cerr << "Syntax: " << argv[0] << " <base> <version.h>" << std::endl; - return 1; - } - - std::string version_sh = std::string(argv[1]) + "/src/version.sh"; - std::string git_dir = std::string(argv[1]) + "/.git"; - - std::fstream fd; - - fd.clear(); - fd.open(version_sh.c_str(), std::ios::in); + std::fstream fd(version_sh.c_str(), std::ios::in); if (!fd.is_open()) { std::cerr << "Error: Unable to open src/version.sh for reading: " << version_sh << std::endl; - return 1; + return false; } std::string filebuf; - std::list<std::pair<std::string, std::string> > versions; while (getline(fd, filebuf)) { if (!filebuf.find("VERSION_")) @@ -75,24 +62,25 @@ int main(int argc, char *argv[]) size_t eq = filebuf.find('='); std::string type = filebuf.substr(0, eq); - std::string value = filebuf.substr(eq + 2, filebuf.length() - eq - 3); - versions.push_back(std::make_pair(type, value)); + std::string value = filebuf.substr(eq + 1); + + versions[type] = value; } } fd.close(); - std::string git_version = get_git_hash(git_dir); - if (!git_version.empty()) - versions.push_back(std::make_pair("VERSION_GIT", git_version)); + return true; +} - fd.clear(); - fd.open(argv[2], std::ios::in); +static bool write_build_h(const std::string &buildh) +{ + std::fstream fd(buildh.c_str(), std::ios::in); std::string build = "#define BUILD 1"; if (fd.is_open()) { - while (getline(fd, filebuf)) + for (std::string filebuf; getline(fd, filebuf);) { if (!filebuf.find("#define BUILD")) { @@ -110,27 +98,92 @@ int main(int argc, char *argv[]) } fd.clear(); - fd.open(argv[2], std::ios::out); - + fd.open(buildh.c_str(), std::ios::out); if (!fd.is_open()) { - std::cerr << "Error: Unable to include/version.h for writing: " << argv[2] << std::endl; - return 1; + std::cerr << "Error: Unable to open build.h for writing: " << buildh << std::endl; + return false; } fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl; + fd << build << std::endl; + fd.close(); + + return true; +} - for (std::list<std::pair<std::string, std::string> >::iterator it = versions.begin(), it_end = versions.end(); it != it_end; ++it) +static void read_version_h(const std::string &versionh, std::map<std::string, std::string> &versions) +{ + std::fstream fd(versionh.c_str(), std::ios::in); + + if (!fd.is_open()) + return; + + for (std::string filebuf; getline(fd, filebuf);) { - if (it->first == "VERSION_EXTRA" || it->first == "VERSION_GIT") - fd << "#define " << it->first << " \"" << it->second << "\"" << std::endl; - else - fd << "#define " << it->first << " " << it->second << std::endl; + if (!filebuf.find("#define VERSION_")) + { + size_t space = filebuf.substr(8).find(' '); + + std::string name = filebuf.substr(8).substr(0, space), + version = filebuf.substr(8).substr(space + 1); + + versions[name] = version; + } } - fd << build << std::endl; + fd.close(); +} + +static bool write_version_h(const std::string &versionh, const std::map<std::string, std::string> &versions) +{ + std::fstream fd(versionh.c_str(), std::ios::out); + + if (!fd.is_open()) + return false; + + for (std::map<std::string, std::string>::const_iterator it = versions.begin(); it != versions.end(); ++it) + { + fd << "#define " << it->first << " " << it->second << std::endl; + } fd.close(); + return true; +} + +int main(int argc, char *argv[]) +{ + if (argc < 4) + { + std::cerr << "Syntax: " << argv[0] << " <base> <version.h> <build.h>" << std::endl; + return 1; + } + + std::string version_sh = std::string(argv[1]) + "/src/version.sh"; + std::string git_dir = std::string(argv[1]) + "/.git"; + std::string versionh = argv[2]; + std::string buildh = argv[3]; + + std::map<std::string, std::string> versions, old_versions; + + if (!read_version_sh(version_sh, versions)) + return -1; + + std::string git_version = get_git_hash(git_dir); + if (!git_version.empty()) + versions["VERSION_GIT"] = '"' + git_version + '"'; + + if (!write_build_h(buildh)) + return -1; + + read_version_h(versionh, old_versions); + + if (versions == old_versions) + return 0; + + if (!write_version_h(versionh, versions)) + return -1; + return 0; } diff --git a/src/misc.cpp b/src/misc.cpp index 57314c53b..a6addbc3f 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -11,7 +11,7 @@ */ #include "services.h" -#include "version.h" +#include "build.h" #include "modules.h" #include "lists.h" #include "config.h" @@ -617,11 +617,6 @@ const Anope::string Anope::LastError() #endif } -ModuleVersion Module::GetVersion() const -{ - return ModuleVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); -} - Anope::string Anope::Version() { #ifdef VERSION_GIT diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index 2e7c624cd..98342b08e 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -166,6 +166,46 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u) return MOD_ERR_NOLOAD; } + try + { + ModuleVersion v = GetVersion(handle); + + if (v.GetMajor() < Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() < Anope::VersionMinor())) + { + Log() << "Module " << modname << " is compiled against an older version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort(); + dlclose(handle); + return MOD_ERR_VERSION; + } + else if (v.GetMajor() > Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() > Anope::VersionMinor())) + { + Log() << "Module " << modname << " is compiled against a newer version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort(); + dlclose(handle); + return MOD_ERR_VERSION; + } + else if (v.GetPatch() < Anope::VersionPatch()) + { + Log() << "Module " << modname << " is compiled against an older version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort(); + dlclose(handle); + return MOD_ERR_VERSION; + } + else if (v.GetPatch() > Anope::VersionPatch()) + { + Log() << "Module " << modname << " is compiled against a newer version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort(); + dlclose(handle); + return MOD_ERR_VERSION; + } + else + { + Log(LOG_DEBUG_2) << "Module " << modname << " is compiled against current version of Anope " << Anope::VersionShort(); + } + } + catch (const ModuleException &ex) + { + /* this error has already been logged */ + dlclose(handle); + return MOD_ERR_NOLOAD; + } + dlerror(); Module *(*func)(const Anope::string &, const Anope::string &) = function_cast<Module *(*)(const Anope::string &, const Anope::string &)>(dlsym(handle, "AnopeInit")); err = dlerror(); @@ -206,34 +246,6 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u) m->filename = pbuf; m->handle = handle; - ModuleVersion v = m->GetVersion(); - if (v.GetMajor() < Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() < Anope::VersionMinor())) - { - Log() << "Module " << modname << " is compiled against an older version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort(); - DeleteModule(m); - return MOD_ERR_VERSION; - } - else if (v.GetMajor() > Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() > Anope::VersionMinor())) - { - Log() << "Module " << modname << " is compiled against a newer version of Anope " << v.GetMajor() << "." << v.GetMinor() << ", this is " << Anope::VersionShort(); - DeleteModule(m); - return MOD_ERR_VERSION; - } - else if (v.GetPatch() < Anope::VersionPatch()) - { - Log() << "Module " << modname << " is compiled against an older version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort(); - DeleteModule(m); - return MOD_ERR_VERSION; - } - else if (v.GetPatch() > Anope::VersionPatch()) - { - Log() << "Module " << modname << " is compiled against a newer version of Anope, " << v.GetMajor() << "." << v.GetMinor() << "." << v.GetPatch() << ", this is " << Anope::VersionShort(); - DeleteModule(m); - return MOD_ERR_VERSION; - } - else - Log(LOG_DEBUG_2) << "Module " << modname << " is compiled against current version of Anope " << Anope::VersionShort(); - /* Initialize config */ try { @@ -272,6 +284,24 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u) return MOD_ERR_OK; } +ModuleVersion ModuleManager::GetVersion(void *handle) +{ + dlerror(); + ModuleVersion (*func)() = function_cast<ModuleVersion (*)()>(dlsym(handle, "AnopeVersion"));; + if (!func) + { + Log() << "No version function found, not an Anope module"; + + const char *err = dlerror(); + if (err && *err) + Log(LOG_DEBUG) << err; + + throw ModuleException("No version"); + } + + return func(); +} + ModuleReturn ModuleManager::UnloadModule(Module *m, User *u) { if (!m) diff --git a/src/version.sh b/src/version.sh index a7046fa72..198556b24 100644 --- a/src/version.sh +++ b/src/version.sh @@ -1,7 +1,7 @@ #!/bin/sh -VERSION_MAJOR="2" -VERSION_MINOR="0" -VERSION_PATCH="2" +VERSION_MAJOR=2 +VERSION_MINOR=0 +VERSION_PATCH=2 VERSION_EXTRA="-git" |