mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-19 17:43:59 +00:00
Libraries (plugins) is going to be used for dumping and restoring external dependencies (e.g. dbus, systemd journal sockets, charecter devices, etc) A plugin can have the cr_plugin_init() and cr_plugin_fini functions for initialization and deinialization. criu-plugin.h contains all things, which can be used in plugins. v2: rename lib to plugin v3: add a default value for a plugin path. Signed-off-by: Andrey Vagin <avagin@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
139 lines
2.2 KiB
C
139 lines
2.2 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <dlfcn.h>
|
|
#include <unistd.h>
|
|
|
|
#include "cr_options.h"
|
|
#include "plugin.h"
|
|
#include "log.h"
|
|
#include "xmalloc.h"
|
|
|
|
struct cr_plugin_entry {
|
|
union {
|
|
cr_plugin_fini_t *cr_fini;
|
|
};
|
|
|
|
struct cr_plugin_entry *next;
|
|
};
|
|
|
|
struct cr_plugins {
|
|
struct cr_plugin_entry *cr_fini;
|
|
};
|
|
|
|
struct cr_plugins cr_plugins;
|
|
|
|
static int cr_lib_load(char *path)
|
|
{
|
|
struct cr_plugin_entry *ce;
|
|
cr_plugin_init_t *f_init;
|
|
cr_plugin_fini_t *f_fini;
|
|
void *h;
|
|
|
|
h = dlopen(path, RTLD_LAZY);
|
|
if (h == NULL) {
|
|
pr_err("Unable to load %s: %s", path, dlerror());
|
|
return -1;
|
|
}
|
|
|
|
ce = NULL;
|
|
f_fini = dlsym(h, "cr_plugin_fini");
|
|
if (f_fini) {
|
|
ce = xmalloc(sizeof(struct cr_plugin_entry));
|
|
if (ce == NULL)
|
|
return -1;
|
|
ce->cr_fini = f_fini;
|
|
}
|
|
|
|
f_init = dlsym(h, "cr_plugin_init");
|
|
if (f_init && f_init()) {
|
|
xfree(ce);
|
|
return -1;
|
|
}
|
|
|
|
if (ce) {
|
|
ce->next = cr_plugins.cr_fini;
|
|
cr_plugins.cr_fini = ce;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void cr_plugin_fini(void)
|
|
{
|
|
struct cr_plugin_entry *ce;
|
|
|
|
while (cr_plugins.cr_fini) {
|
|
ce = cr_plugins.cr_fini;
|
|
cr_plugins.cr_fini = cr_plugins.cr_fini->next;
|
|
|
|
ce->cr_fini();
|
|
xfree(ce);
|
|
}
|
|
}
|
|
|
|
int cr_plugin_init(void)
|
|
{
|
|
int exit_code = -1;
|
|
char *path;
|
|
DIR *d;
|
|
|
|
memset(&cr_plugins, 0, sizeof(cr_plugins));
|
|
|
|
if (opts.libdir == NULL) {
|
|
path = getenv("CRIU_LIBS_DIR");
|
|
if (path) {
|
|
opts.libdir = strdup(path);
|
|
} else {
|
|
if (access(CR_PLUGIN_DEFAULT, F_OK))
|
|
return 0;
|
|
opts.libdir = strdup(CR_PLUGIN_DEFAULT);
|
|
}
|
|
if (opts.libdir == NULL) {
|
|
pr_perror("Can't allocate memory");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
d = opendir(opts.libdir);
|
|
if (d == NULL) {
|
|
pr_perror("Unable to open directory %s", opts.libdir);
|
|
return -1;
|
|
}
|
|
|
|
while (1) {
|
|
char path[PATH_MAX];
|
|
struct dirent *de;
|
|
int len;
|
|
|
|
errno = 0;
|
|
de = readdir(d);
|
|
if (de == NULL) {
|
|
if (errno == 0)
|
|
break;
|
|
pr_perror("Unable to read the libraries directory");
|
|
goto err;
|
|
}
|
|
|
|
len = strlen(de->d_name);
|
|
|
|
if (len < 3 || strncmp(de->d_name + len - 3, ".so", 3))
|
|
continue;
|
|
|
|
snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name);
|
|
|
|
if (cr_lib_load(path))
|
|
goto err;
|
|
}
|
|
|
|
exit_code = 0;
|
|
err:
|
|
closedir(d);
|
|
|
|
if (exit_code)
|
|
cr_plugin_fini();
|
|
|
|
return exit_code;
|
|
}
|