-
-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathloader.cpp
More file actions
133 lines (109 loc) · 3.31 KB
/
loader.cpp
File metadata and controls
133 lines (109 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <modloader/loader.h>
#include "loader.h"
#include <cstring>
#include <unistd.h>
#include <dirent.h>
#include <dlfcn.h>
#include <modloader/log.h>
#include "elf_helper.h"
using namespace modloader;
static ModLoaderImpl loaderImpl;
extern "C" {
const char *modloader_version() {
return ModLoader::getVersion();
}
void modloader_add_lib_search_path(const char* path) {
loaderImpl.addLibSearchDir(path);
}
void *modloader_load_mod(const char* path) {
return loaderImpl.loadMod(path);
}
void modloader_load_mods_from_directory(const char* path) {
loaderImpl.loadModsFromDirectory(path);
}
void modloader_iterate_mods(modloader_foreach_fn cb, void* userdata) {
for (void* v : loaderImpl.mods)
cb(v, userdata);
}
}
const char *ModLoader::getVersion() {
return MODLOADER_VERSION;
}
void ModLoader::addLibSearchDir(std::string const &path) {
loaderImpl.addLibSearchDir(path);
}
void* ModLoader::loadMod(std::string const &path) {
return loaderImpl.loadMod(path);
}
void ModLoader::loadModsFromDirectory(std::string const &path) {
loaderImpl.loadModsFromDirectory(path);
}
void ModLoader::forEachMod(std::function<void(void *)> cb) {
for (void* v : loaderImpl.mods)
cb(v);
}
std::string ModLoaderImpl::findLib(std::string const &name) {
for (std::string const& dir : libDirs) {
std::string fullPath = dir;
fullPath += '/';
fullPath += name;
if (access(fullPath.c_str(), R_OK) == 0)
return fullPath;
}
return std::string();
}
void *ModLoaderImpl::loadLib(std::string const &path) {
auto e = knownLoadedLibs.find(path);
if (e != knownLoadedLibs.end())
return e->second;
auto iof = path.rfind('/');
std::string fullPath = path;
if (iof == std::string::npos)
fullPath = findLib(path);
if (!fullPath.empty()) {
Log::info("ModLoader", "Loading library: %s", fullPath.c_str());
auto deps = ElfHelper::getDependencies(fullPath);
for (std::string const& dep : deps)
loadLib(dep);
} else {
fullPath = path;
}
void* ret = dlopen(fullPath.c_str(), RTLD_NOW);
if (!ret) {
Log::error("ModLoader", "Failed loading library %s: %s", fullPath.c_str(), dlerror());
return nullptr;
}
std::string filename = iof != std::string::npos ? path.substr(iof + 1) : path;
knownLoadedLibs[filename] = ret;
return ret;
}
void *ModLoaderImpl::loadMod(std::string const &path) {
void* ret = loadLib(path);
mods.insert(ret);
return ret;
}
void ModLoaderImpl::loadModsFromDirectory(std::string const &path) {
Log::info("ModLoader", "Loading mods from directory: %s", path.c_str());
DIR* dir = opendir(path.c_str());
dirent* ent;
if (dir == nullptr) {
Log::info("ModLoader", "Directory does not exist");
return;
}
int errors = 0;
while ((ent = readdir(dir)) != nullptr) {
if (ent->d_name[0] == '.')
continue;
std::string fileName(ent->d_name);
size_t len = fileName.length();
if(loadMod(fileName) == nullptr){
errors++;
}
}
closedir(dir);
Log::info("ModLoader", "Loaded %li mods", mods.size() - errors);
if(errors > 0){
Log::error("ModLoader", "%d mods failed to load, aborting", errors);
exit(1);
}
}