Branch data Line data Source code
1 : : #include <stdlib.h>
2 : : #include <string.h>
3 : : #include <dirent.h>
4 : : #include <errno.h>
5 : : #include <stdio.h>
6 : : #include <dlfcn.h>
7 : : #include <unistd.h>
8 : :
9 : : #include "cr_options.h"
10 : : #include "plugin.h"
11 : : #include "log.h"
12 : : #include "xmalloc.h"
13 : :
14 : : struct cr_plugin_entry {
15 : : union {
16 : : cr_plugin_fini_t *cr_fini;
17 : :
18 : : cr_plugin_dump_unix_sk_t *cr_plugin_dump_unix_sk;
19 : : cr_plugin_restore_unix_sk_t *cr_plugin_restore_unix_sk;
20 : : cr_plugin_dump_file_t *cr_plugin_dump_file;
21 : : cr_plugin_restore_file_t *cr_plugin_restore_file;
22 : : cr_plugin_dump_ext_mount_t *cr_plugin_dump_ext_mount;
23 : : cr_plugin_restore_ext_mount_t *cr_plugin_restore_ext_mount;
24 : : cr_plugin_dump_ext_link_t *cr_plugin_dump_ext_link;
25 : : };
26 : :
27 : : struct cr_plugin_entry *next;
28 : : };
29 : :
30 : : struct cr_plugins {
31 : : struct cr_plugin_entry *cr_fini;
32 : :
33 : : struct cr_plugin_entry *cr_plugin_dump_unix_sk;
34 : : struct cr_plugin_entry *cr_plugin_restore_unix_sk;
35 : : struct cr_plugin_entry *cr_plugin_dump_file;
36 : : struct cr_plugin_entry *cr_plugin_restore_file;
37 : : struct cr_plugin_entry *cr_plugin_dump_ext_mount;
38 : : struct cr_plugin_entry *cr_plugin_restore_ext_mount;
39 : : struct cr_plugin_entry *cr_plugin_dump_ext_link;
40 : : };
41 : :
42 : : struct cr_plugins cr_plugins;
43 : :
44 : : #define add_plugin_func(name) \
45 : : do { \
46 : : name ## _t *name; \
47 : : name = dlsym(h, #name); \
48 : : if (name) { \
49 : : struct cr_plugin_entry *__ce; \
50 : : __ce = xmalloc(sizeof(*__ce)); \
51 : : if (__ce == NULL) \
52 : : goto nomem; \
53 : : __ce->name = name; \
54 : : __ce->next = cr_plugins.name; \
55 : : cr_plugins.name = __ce; \
56 : : } \
57 : : } while (0)
58 : :
59 : : #define run_plugin_funcs(name, ...) ({ \
60 : : struct cr_plugin_entry *__ce = cr_plugins.name; \
61 : : int __ret = -ENOTSUP; \
62 : : \
63 : : while (__ce) { \
64 : : __ret = __ce->name(__VA_ARGS__); \
65 : : if (__ret == -ENOTSUP) { \
66 : : __ce = __ce->next; \
67 : : continue; \
68 : : } \
69 : : break; \
70 : : } \
71 : : \
72 : : __ret; \
73 : : }) \
74 : :
75 : 2 : int cr_plugin_dump_unix_sk(int fd, int id)
76 : : {
77 [ # # ][ - + ]: 2 : return run_plugin_funcs(cr_plugin_dump_unix_sk, fd, id);
78 : : }
79 : :
80 : 0 : int cr_plugin_restore_unix_sk(int id)
81 : : {
82 [ # # ][ # # ]: 0 : return run_plugin_funcs(cr_plugin_restore_unix_sk, id);
83 : : }
84 : :
85 : 4 : int cr_plugin_dump_file(int fd, int id)
86 : : {
87 [ - + ][ + - ]: 4 : return run_plugin_funcs(cr_plugin_dump_file, fd, id);
88 : : }
89 : :
90 : 2 : int cr_plugin_restore_file(int id)
91 : : {
92 [ - + ][ + - ]: 2 : return run_plugin_funcs(cr_plugin_restore_file, id);
93 : : }
94 : :
95 : 0 : int cr_plugin_dump_ext_mount(char *mountpoint, int id)
96 : : {
97 [ # # ][ # # ]: 0 : return run_plugin_funcs(cr_plugin_dump_ext_mount, mountpoint, id);
98 : : }
99 : :
100 : 0 : int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file)
101 : : {
102 [ # # ][ # # ]: 0 : return run_plugin_funcs(cr_plugin_restore_ext_mount, id, mountpoint, old_root, is_file);
103 : : }
104 : :
105 : 0 : int cr_plugin_dump_ext_link(int index, int type, char *kind)
106 : : {
107 [ # # ][ # # ]: 0 : return run_plugin_funcs(cr_plugin_dump_ext_link, index, type, kind);
108 : : }
109 : :
110 : 12 : static int cr_lib_load(char *path)
111 : : {
112 : : struct cr_plugin_entry *ce;
113 : : cr_plugin_init_t *f_init;
114 : : cr_plugin_fini_t *f_fini;
115 : : void *h;
116 : :
117 : 12 : h = dlopen(path, RTLD_LAZY);
118 [ - + ]: 12 : if (h == NULL) {
119 : 0 : pr_err("Unable to load %s: %s", path, dlerror());
120 : 0 : return -1;
121 : : }
122 : :
123 [ - + ][ # # ]: 12 : add_plugin_func(cr_plugin_dump_unix_sk);
[ # # ]
124 [ - + ][ # # ]: 12 : add_plugin_func(cr_plugin_restore_unix_sk);
[ # # ]
125 : :
126 [ + - ][ - + ]: 12 : add_plugin_func(cr_plugin_dump_file);
[ + - ]
127 [ + - ][ - + ]: 12 : add_plugin_func(cr_plugin_restore_file);
[ + - ]
128 : :
129 [ - + ][ # # ]: 12 : add_plugin_func(cr_plugin_dump_ext_mount);
[ # # ]
130 [ - + ][ # # ]: 12 : add_plugin_func(cr_plugin_restore_ext_mount);
[ # # ]
131 : :
132 [ - + ][ # # ]: 12 : add_plugin_func(cr_plugin_dump_ext_link);
[ # # ]
133 : :
134 : : ce = NULL;
135 : 12 : f_fini = dlsym(h, "cr_plugin_fini");
136 [ - + ]: 12 : if (f_fini) {
137 [ # # ]: 0 : ce = xmalloc(sizeof(*ce));
138 [ # # ]: 0 : if (ce == NULL)
139 : : goto nomem;
140 : 0 : ce->cr_fini = f_fini;
141 : : }
142 : :
143 : 12 : f_init = dlsym(h, "cr_plugin_init");
144 [ - + ][ # # ]: 12 : if (f_init && f_init()) {
145 [ # # ]: 0 : xfree(ce);
146 : : return -1;
147 : : }
148 : :
149 [ - + ]: 12 : if (ce) {
150 : 0 : ce->next = cr_plugins.cr_fini;
151 : 0 : cr_plugins.cr_fini = ce;
152 : : }
153 : :
154 : : return 0;
155 : :
156 : : nomem:
157 : : return -1;
158 : : }
159 : :
160 : : #define cr_plugin_free(name) do { \
161 : : while (cr_plugins.name) { \
162 : : ce = cr_plugins.name; \
163 : : cr_plugins.name = cr_plugins.name->next; \
164 : : xfree(ce); \
165 : : } \
166 : : } while (0) \
167 : :
168 : 896 : void cr_plugin_fini(void)
169 : : {
170 : : struct cr_plugin_entry *ce;
171 : :
172 [ # # ][ - + ]: 896 : cr_plugin_free(cr_plugin_dump_unix_sk);
173 [ # # ][ - + ]: 896 : cr_plugin_free(cr_plugin_restore_unix_sk);
174 : :
175 [ - + ][ + + ]: 904 : cr_plugin_free(cr_plugin_dump_file);
176 [ - + ][ + + ]: 904 : cr_plugin_free(cr_plugin_restore_file);
177 : :
178 [ - + ]: 896 : while (cr_plugins.cr_fini) {
179 : : ce = cr_plugins.cr_fini;
180 : 0 : cr_plugins.cr_fini = cr_plugins.cr_fini->next;
181 : :
182 : 0 : ce->cr_fini();
183 [ # # ]: 896 : xfree(ce);
184 : : }
185 : 896 : }
186 : :
187 : 1461 : int cr_plugin_init(void)
188 : : {
189 : : int exit_code = -1;
190 : : char *path;
191 : : DIR *d;
192 : :
193 : : memset(&cr_plugins, 0, sizeof(cr_plugins));
194 : :
195 [ + + ]: 1461 : if (opts.libdir == NULL) {
196 : 1449 : path = getenv("CRIU_LIBS_DIR");
197 [ - + ]: 1449 : if (path)
198 : 0 : opts.libdir = path;
199 : : else {
200 [ - + ]: 1449 : if (access(CR_PLUGIN_DEFAULT, F_OK))
201 : : return 0;
202 : :
203 : 0 : opts.libdir = CR_PLUGIN_DEFAULT;
204 : : }
205 : : }
206 : :
207 : 12 : d = opendir(opts.libdir);
208 [ + - ]: 12 : if (d == NULL) {
209 : 0 : pr_perror("Unable to open directory %s", opts.libdir);
210 : 36 : return -1;
211 : : }
212 : :
213 : : while (1) {
214 : : char path[PATH_MAX];
215 : : struct dirent *de;
216 : : int len;
217 : :
218 : 48 : errno = 0;
219 : 48 : de = readdir(d);
220 [ + + ]: 48 : if (de == NULL) {
221 [ - + ]: 12 : if (errno == 0)
222 : : break;
223 : 0 : pr_perror("Unable to read the libraries directory");
224 : 0 : goto err;
225 : : }
226 : :
227 : 36 : len = strlen(de->d_name);
228 : :
229 [ + + ][ - + ]: 36 : if (len < 3 || strncmp(de->d_name + len - 3, ".so", 3))
230 : 24 : continue;
231 : :
232 : 12 : snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name);
233 : :
234 [ + - ]: 24 : if (cr_lib_load(path))
235 : : goto err;
236 : : }
237 : :
238 : : exit_code = 0;
239 : : err:
240 : 12 : closedir(d);
241 : :
242 [ - + ]: 12 : if (exit_code)
243 : 0 : cr_plugin_fini();
244 : :
245 : 12 : return exit_code;
246 : : }
|