Line data Source code
1 0 : GQuark bd_loop_error_quark (void) {
2 0 : return g_quark_from_static_string ("g-bd-loop-error-quark");
3 : }
4 :
5 : /**
6 : * BDLoopInfo:
7 : * @backing_file: backing file for the give loop device;
8 : * @offset: offset of the start of the device (in @backing_file);
9 : * @autoclear: whether the autoclear flag is set or not;
10 : * @direct_io: whether direct IO is enabled or not;
11 : * @part_scan: whether the partition scan is enforced or not;
12 : * @read_only: whether the device is read-only or not;
13 : */
14 : /**
15 : * bd_loop_info_free: (skip)
16 : * @info: (nullable): %BDLoopInfo to free
17 : *
18 : * Frees @info.
19 : */
20 10 : void bd_loop_info_free (BDLoopInfo *info) {
21 10 : if (info == NULL)
22 0 : return;
23 :
24 10 : g_free (info->backing_file);
25 10 : g_free (info);
26 : }
27 :
28 : /**
29 : * bd_loop_info_copy: (skip)
30 : * @info: (nullable): %BDLoopInfo to copy
31 : *
32 : * Creates a new copy of @info.
33 : */
34 0 : BDLoopInfo* bd_loop_info_copy (BDLoopInfo *info) {
35 0 : if (info == NULL)
36 0 : return NULL;
37 :
38 0 : BDLoopInfo *new_info = g_new0 (BDLoopInfo, 1);
39 :
40 0 : new_info->backing_file = g_strdup (info->backing_file);
41 0 : new_info->offset = info->offset;
42 0 : new_info->autoclear = info->autoclear;
43 0 : new_info->direct_io = info->direct_io;
44 0 : new_info->part_scan = info->part_scan;
45 0 : new_info->read_only = info->read_only;
46 :
47 0 : return new_info;
48 : }
49 :
50 18 : GType bd_loop_info_get_type () {
51 : static GType type = 0;
52 :
53 18 : if (G_UNLIKELY(type == 0)) {
54 1 : type = g_boxed_type_register_static("BDLoopInfo",
55 : (GBoxedCopyFunc) bd_loop_info_copy,
56 : (GBoxedFreeFunc) bd_loop_info_free);
57 : }
58 :
59 18 : return type;
60 : }
61 :
62 0 : static gboolean bd_loop_is_tech_avail_stub (BDLoopTech tech G_GNUC_UNUSED, guint64 mode G_GNUC_UNUSED, GError **error) {
63 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_is_tech_avail' called, but not implemented!");
64 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
65 : "The function 'bd_loop_is_tech_avail' called, but not implemented!");
66 0 : return FALSE;
67 : }
68 :
69 : static gboolean (*_bd_loop_is_tech_avail) (BDLoopTech tech, guint64 mode, GError **error) = bd_loop_is_tech_avail_stub;
70 :
71 : /**
72 : * bd_loop_is_tech_avail:
73 : * @tech: the queried tech
74 : * @mode: a bit mask of queried modes of operation (#BDLoopTechMode) for @tech
75 : * @error: (out) (optional): place to store error (details about why the @tech-@mode combination is not available)
76 : *
77 : * Returns: whether the @tech-@mode combination is available -- supported by the
78 : * plugin implementation and having all the runtime dependencies available
79 : */
80 0 : gboolean bd_loop_is_tech_avail (BDLoopTech tech, guint64 mode, GError **error) {
81 0 : return _bd_loop_is_tech_avail (tech, mode, error);
82 : }
83 :
84 :
85 0 : static BDLoopInfo* bd_loop_info_stub (const gchar *loop G_GNUC_UNUSED, GError **error) {
86 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_info' called, but not implemented!");
87 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
88 : "The function 'bd_loop_info' called, but not implemented!");
89 0 : return NULL;
90 : }
91 :
92 : static BDLoopInfo* (*_bd_loop_info) (const gchar *loop, GError **error) = bd_loop_info_stub;
93 :
94 : /**
95 : * bd_loop_info:
96 : * @loop: name of the loop device to get information about (e.g. "loop0")
97 : * @error: (out) (optional): place to store error (if any)
98 : *
99 : * Returns: (transfer full): information about the @loop device or %NULL in case of error
100 : *
101 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_QUERY
102 : */
103 10 : BDLoopInfo* bd_loop_info (const gchar *loop, GError **error) {
104 10 : return _bd_loop_info (loop, error);
105 : }
106 :
107 :
108 0 : static gchar* bd_loop_get_loop_name_stub (const gchar *file G_GNUC_UNUSED, GError **error) {
109 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_get_loop_name' called, but not implemented!");
110 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
111 : "The function 'bd_loop_get_loop_name' called, but not implemented!");
112 0 : return NULL;
113 : }
114 :
115 : static gchar* (*_bd_loop_get_loop_name) (const gchar *file, GError **error) = bd_loop_get_loop_name_stub;
116 :
117 : /**
118 : * bd_loop_get_loop_name:
119 : * @file: path of the backing file to get loop name for
120 : * @error: (out) (optional): place to store error (if any)
121 : *
122 : * Returns: (transfer full): name of the loop device associated with the given @file
123 : *
124 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_QUERY
125 : */
126 2 : gchar* bd_loop_get_loop_name (const gchar *file, GError **error) {
127 2 : return _bd_loop_get_loop_name (file, error);
128 : }
129 :
130 :
131 0 : static gboolean bd_loop_setup_stub (const gchar *file G_GNUC_UNUSED, guint64 offset G_GNUC_UNUSED, guint64 size G_GNUC_UNUSED, gboolean read_only G_GNUC_UNUSED, gboolean part_scan G_GNUC_UNUSED, guint64 sector_size G_GNUC_UNUSED, const gchar **loop_name G_GNUC_UNUSED, GError **error) {
132 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_setup' called, but not implemented!");
133 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
134 : "The function 'bd_loop_setup' called, but not implemented!");
135 0 : return FALSE;
136 : }
137 :
138 : static gboolean (*_bd_loop_setup) (const gchar *file, guint64 offset, guint64 size, gboolean read_only, gboolean part_scan, guint64 sector_size, const gchar **loop_name, GError **error) = bd_loop_setup_stub;
139 :
140 : /**
141 : * bd_loop_setup:
142 : * @file: file to setup as a loop device
143 : * @offset: offset of the start of the device (in @file)
144 : * @size: maximum size of the device (or 0 to leave unspecified)
145 : * @read_only: whether to setup as read-only (%TRUE) or read-write (%FALSE)
146 : * @part_scan: whether to enforce partition scan on the newly created device or not
147 : * @sector_size: logical sector size for the loop device in bytes (or 0 for default)
148 : * @loop_name: (optional) (out): if not %NULL, it is used to store the name of the loop device
149 : * @error: (out) (optional): place to store error (if any)
150 : *
151 : * Returns: whether the @file was successfully setup as a loop device or not
152 : *
153 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_CREATE
154 : */
155 30 : gboolean bd_loop_setup (const gchar *file, guint64 offset, guint64 size, gboolean read_only, gboolean part_scan, guint64 sector_size, const gchar **loop_name, GError **error) {
156 30 : return _bd_loop_setup (file, offset, size, read_only, part_scan, sector_size, loop_name, error);
157 : }
158 :
159 :
160 0 : static gboolean bd_loop_setup_from_fd_stub (gint fd G_GNUC_UNUSED, guint64 offset G_GNUC_UNUSED, guint64 size G_GNUC_UNUSED, gboolean read_only G_GNUC_UNUSED, gboolean part_scan G_GNUC_UNUSED, guint64 sector_size G_GNUC_UNUSED, const gchar **loop_name G_GNUC_UNUSED, GError **error) {
161 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_setup_from_fd' called, but not implemented!");
162 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
163 : "The function 'bd_loop_setup_from_fd' called, but not implemented!");
164 0 : return FALSE;
165 : }
166 :
167 : static gboolean (*_bd_loop_setup_from_fd) (gint fd, guint64 offset, guint64 size, gboolean read_only, gboolean part_scan, guint64 sector_size, const gchar **loop_name, GError **error) = bd_loop_setup_from_fd_stub;
168 :
169 : /**
170 : * bd_loop_setup_from_fd:
171 : * @fd: file descriptor for a file to setup as a new loop device
172 : * @offset: offset of the start of the device (in file given by @fd)
173 : * @size: maximum size of the device (or 0 to leave unspecified)
174 : * @read_only: whether to setup as read-only (%TRUE) or read-write (%FALSE)
175 : * @part_scan: whether to enforce partition scan on the newly created device or not
176 : * @sector_size: logical sector size for the loop device in bytes (or 0 for default)
177 : * @loop_name: (optional) (out): if not %NULL, it is used to store the name of the loop device
178 : * @error: (out) (optional): place to store error (if any)
179 : *
180 : * Returns: whether a new loop device was successfully setup for @fd or not
181 : *
182 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_CREATE
183 : */
184 30 : gboolean bd_loop_setup_from_fd (gint fd, guint64 offset, guint64 size, gboolean read_only, gboolean part_scan, guint64 sector_size, const gchar **loop_name, GError **error) {
185 30 : return _bd_loop_setup_from_fd (fd, offset, size, read_only, part_scan, sector_size, loop_name, error);
186 : }
187 :
188 :
189 0 : static gboolean bd_loop_teardown_stub (const gchar *loop G_GNUC_UNUSED, GError **error) {
190 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_teardown' called, but not implemented!");
191 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
192 : "The function 'bd_loop_teardown' called, but not implemented!");
193 0 : return FALSE;
194 : }
195 :
196 : static gboolean (*_bd_loop_teardown) (const gchar *loop, GError **error) = bd_loop_teardown_stub;
197 :
198 : /**
199 : * bd_loop_teardown:
200 : * @loop: path or name of the loop device to tear down
201 : * @error: (out) (optional): place to store error (if any)
202 : *
203 : * Returns: whether the @loop device was successfully torn down or not
204 : *
205 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_DESTROY
206 : */
207 34 : gboolean bd_loop_teardown (const gchar *loop, GError **error) {
208 34 : return _bd_loop_teardown (loop, error);
209 : }
210 :
211 :
212 0 : static gboolean bd_loop_set_autoclear_stub (const gchar *loop G_GNUC_UNUSED, gboolean autoclear G_GNUC_UNUSED, GError **error) {
213 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_set_autoclear' called, but not implemented!");
214 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
215 : "The function 'bd_loop_set_autoclear' called, but not implemented!");
216 0 : return FALSE;
217 : }
218 :
219 : static gboolean (*_bd_loop_set_autoclear) (const gchar *loop, gboolean autoclear, GError **error) = bd_loop_set_autoclear_stub;
220 :
221 : /**
222 : * bd_loop_set_autoclear:
223 : * @loop: path or name of the loop device
224 : * @autoclear: whether to set or unset the autoclear flag
225 : * @error: (out) (optional): place to store error (if any)
226 : *
227 : * Returns: whether the autoclear flag was successfully set on the @loop device or not
228 : *
229 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_MODIFY
230 : */
231 4 : gboolean bd_loop_set_autoclear (const gchar *loop, gboolean autoclear, GError **error) {
232 4 : return _bd_loop_set_autoclear (loop, autoclear, error);
233 : }
234 :
235 :
236 0 : static gboolean bd_loop_set_capacity_stub (const gchar *loop G_GNUC_UNUSED, GError **error) {
237 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_loop_set_capacity' called, but not implemented!");
238 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
239 : "The function 'bd_loop_set_capacity' called, but not implemented!");
240 0 : return FALSE;
241 : }
242 :
243 : static gboolean (*_bd_loop_set_capacity) (const gchar *loop, GError **error) = bd_loop_set_capacity_stub;
244 :
245 : /**
246 : * bd_loop_set_capacity:
247 : * @loop: path or name of the loop device
248 : * @error: (out) (optional): place to store error (if any)
249 : *
250 : * Force the loop driver to reread the size of the file associated with the
251 : * specified @loop device.
252 : *
253 : * Returns: whether the LOOP_SET_CAPACITY ioctl was successfully issued or not.
254 : *
255 : * Tech category: %BD_LOOP_TECH_LOOP-%BD_LOOP_TECH_MODE_MODIFY
256 : */
257 1 : gboolean bd_loop_set_capacity (const gchar *loop, GError **error) {
258 1 : return _bd_loop_set_capacity (loop, error);
259 : }
260 :
261 :
262 155 : static gpointer load_loop_from_plugin(const gchar *so_name) {
263 155 : void *handle = NULL;
264 155 : char *error = NULL;
265 155 : gboolean (*init_fn) (void) = NULL;
266 :
267 155 : handle = dlopen(so_name, RTLD_LAZY);
268 155 : if (!handle) {
269 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load module loop: %s", dlerror());
270 0 : return NULL;
271 : }
272 :
273 155 : dlerror();
274 155 : * (void**) (&init_fn) = dlsym(handle, "bd_loop_init");
275 155 : if ((error = dlerror()) != NULL)
276 0 : bd_utils_log_format (BD_UTILS_LOG_DEBUG, "failed to load the init() function for loop: %s", error);
277 : /* coverity[dead_error_condition] */
278 155 : if (init_fn && !init_fn()) {
279 0 : dlclose(handle);
280 0 : return NULL;
281 : }
282 155 : init_fn = NULL;
283 :
284 155 : dlerror();
285 155 : * (void**) (&_bd_loop_is_tech_avail) = dlsym(handle, "bd_loop_is_tech_avail");
286 155 : if ((error = dlerror()) != NULL)
287 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_is_tech_avail: %s", error);
288 :
289 155 : dlerror();
290 155 : * (void**) (&_bd_loop_info) = dlsym(handle, "bd_loop_info");
291 155 : if ((error = dlerror()) != NULL)
292 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_info: %s", error);
293 :
294 155 : dlerror();
295 155 : * (void**) (&_bd_loop_get_loop_name) = dlsym(handle, "bd_loop_get_loop_name");
296 155 : if ((error = dlerror()) != NULL)
297 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_get_loop_name: %s", error);
298 :
299 155 : dlerror();
300 155 : * (void**) (&_bd_loop_setup) = dlsym(handle, "bd_loop_setup");
301 155 : if ((error = dlerror()) != NULL)
302 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_setup: %s", error);
303 :
304 155 : dlerror();
305 155 : * (void**) (&_bd_loop_setup_from_fd) = dlsym(handle, "bd_loop_setup_from_fd");
306 155 : if ((error = dlerror()) != NULL)
307 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_setup_from_fd: %s", error);
308 :
309 155 : dlerror();
310 155 : * (void**) (&_bd_loop_teardown) = dlsym(handle, "bd_loop_teardown");
311 155 : if ((error = dlerror()) != NULL)
312 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_teardown: %s", error);
313 :
314 155 : dlerror();
315 155 : * (void**) (&_bd_loop_set_autoclear) = dlsym(handle, "bd_loop_set_autoclear");
316 155 : if ((error = dlerror()) != NULL)
317 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_set_autoclear: %s", error);
318 :
319 155 : dlerror();
320 155 : * (void**) (&_bd_loop_set_capacity) = dlsym(handle, "bd_loop_set_capacity");
321 155 : if ((error = dlerror()) != NULL)
322 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_set_capacity: %s", error);
323 :
324 155 : return handle;
325 : }
326 :
327 155 : static gboolean unload_loop (gpointer handle) {
328 155 : char *error = NULL;
329 155 : gboolean (*close_fn) (void) = NULL;
330 :
331 155 : _bd_loop_is_tech_avail = bd_loop_is_tech_avail_stub;
332 155 : _bd_loop_info = bd_loop_info_stub;
333 155 : _bd_loop_get_loop_name = bd_loop_get_loop_name_stub;
334 155 : _bd_loop_setup = bd_loop_setup_stub;
335 155 : _bd_loop_setup_from_fd = bd_loop_setup_from_fd_stub;
336 155 : _bd_loop_teardown = bd_loop_teardown_stub;
337 155 : _bd_loop_set_autoclear = bd_loop_set_autoclear_stub;
338 155 : _bd_loop_set_capacity = bd_loop_set_capacity_stub;
339 :
340 155 : dlerror();
341 155 : * (void**) (&close_fn) = dlsym(handle, "bd_loop_close");
342 155 : if (((error = dlerror()) != NULL) || !close_fn)
343 0 : bd_utils_log_format (BD_UTILS_LOG_DEBUG, "failed to load the close_plugin() function for loop: %s", error);
344 : /* coverity[dead_error_condition] */
345 155 : if (close_fn) {
346 155 : close_fn();
347 : }
348 :
349 155 : return dlclose(handle) == 0;
350 : }
351 :
|