[CRIU] [PATCH 1/5] crtools: preload libraries
Pavel Emelyanov
xemul at parallels.com
Thu Dec 5 10:28:36 PST 2013
> @@ -271,6 +275,13 @@ int main(int argc, char *argv[])
> case 54:
> opts.check_ms_kernel = true;
> break;
> + case 'L':
> + opts.libdir = strdup(optarg);
> + if (opts.libdir == NULL) {
> + pr_perror("Can't allocate memory");
> + return -1;
> + }
> + break;
> case 'V':
> pr_msg("Version: %s\n", CRIU_VERSION);
> if (strcmp(CRIU_GITID, "0"))
Help text missing.
> diff --git a/include/cr_options.h b/include/cr_options.h
> index b90b4e1..5a4676c 100644
> --- a/include/cr_options.h
> +++ b/include/cr_options.h
> @@ -29,6 +29,7 @@ struct cr_options {
> char *pidfile;
> struct list_head veth_pairs;
> struct list_head scripts;
> + char *libdir;
> bool use_page_server;
> unsigned short ps_port;
> char *addr;
> diff --git a/include/criu-plugin.h b/include/criu-plugin.h
> new file mode 100644
> index 0000000..44abb2a
> --- /dev/null
> +++ b/include/criu-plugin.h
> @@ -0,0 +1,26 @@
> +/*
> + This file defines types and macros for CRIU plugins.
> + Copyright (C) 2013 Parallels, Inc
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 2 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program; if not, write to the Free Software
> + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef __CRIU_PLUGIN_H__
> +#define __CRIU_PLUGIN_H__
> +
> +typedef int (cr_plugin_init_t)(void);
> +typedef void (cr_plugin_fini_t)(void);
> +
> +#endif
> diff --git a/include/plugin.h b/include/plugin.h
> new file mode 100644
> index 0000000..8653a5b
> --- /dev/null
> +++ b/include/plugin.h
> @@ -0,0 +1,22 @@
> +#ifndef __CR_PLUGIN_H__
> +#define __CR_PLUGIN_H__
> +
> +#include "criu-plugin.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;
> +};
> +
> +extern struct cr_plugins cr_plugins;
Why should this info be public?
> +
> +void cr_lib_fini(void);
> +int cr_lib_init(void);
> +#endif
> diff --git a/lib.c b/lib.c
> new file mode 100644
> index 0000000..387bb84
> --- /dev/null
> +++ b/lib.c
> @@ -0,0 +1,123 @@
> +#include <stdlib.h>
> +#include <string.h>
> +#include <dirent.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <dlfcn.h>
> +
> +#include "cr_options.h"
> +#include "plugin.h"
> +#include "log.h"
> +#include "xmalloc.h"
> +
> +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;
In patch #3 you use some fancy macro for this.
> + }
> +
> + 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_lib_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_lib_init(void)
> +{
> + int exit_code = -1;
> + DIR *d;
> +
> + memset(&cr_plugins, 0, sizeof(cr_plugins));
> +
> + if (opts.libdir == NULL) {
> + char *path;
> +
> + path = getenv("CRIU_LIBS_DIR");
> + if (path == NULL)
I think we should declare some default library for it.
> + return 0;
> +
> + opts.libdir = strdup(path);
Why strdup?
> + if (opts.libdir == NULL) {
> + pr_perror("Can't allocate memory");
> + return -1;
> + }
> + }
> +
> + d = opendir(opts.libdir);
> + if (d == 0) {
> + 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);
> +
> + cr_lib_fini();
> +
> + return exit_code;
> +}
>
More information about the CRIU
mailing list