[CRIU] [PATCH 1/5] crtools: preload libraries
Pavel Emelyanov
xemul at parallels.com
Fri Dec 6 00:42:45 PST 2013
>>> @@ -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?
>
> criu-plugin.h is public, this one isn't.
OK, s/public/criu-sources-visible/
Why?
>>
>>> +
>>> +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_fini is a special case.
>>
>>> + }
>>> +
>>> + 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;
>>> + }
>
> because it's added in the list here
Why?
>>> +
>>> + 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.
>
> I thought about this. I don't know which path can be default and we can
> add the default path in any moment.
Plz, declare the /var/lib/criu/ and use it.
>
>>
>>> + return 0;
>>> +
>>> + opts.libdir = strdup(path);
>>
>> Why strdup?
>
> becuase we need to copy the string, when we are parsing options,
> so we are going to call free(opts.libdir)
>
>>
>>> + 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