Line data Source code
1 132 : GQuark bd_smart_error_quark (void) {
2 132 : return g_quark_from_static_string ("g-bd-smart-error-quark");
3 : }
4 :
5 : /**
6 : * BDSmartATAAttribute:
7 : * @id: Attribute Identifier.
8 : * @name: A free-form representation of the attribute name, implementation-dependent (e.g. libatasmart internal strings or smartmontools' drivedb.h names).
9 : * @well_known_name: Translated well-known attribute name (in libatasmart style, e.g. 'raw-read-error-rate') or %NULL in case of unknown, untrusted or vendor-specific value.
10 : * @value: The normalized value or -1 if unknown.
11 : * @worst: The worst normalized value of -1 if unknown.
12 : * @threshold: The threshold of a normalized value or -1 if unknown.
13 : * @failed_past: Indicates a failure that happened in the past (the normalized worst value is below the threshold).
14 : * @failing_now: Indicates a failure that is happening now (the normalized value is below the threshold).
15 : * @value_raw: The raw value of the attribute.
16 : * @flags: Bitmask of attribute flags. See #BDSmartATAAttributeFlag.
17 : * @pretty_value: Numerical representation of the parsed raw value, presented in @pretty_value_unit units.
18 : * @pretty_value_unit: The unit of the parsed raw value.
19 : * @pretty_value_string: A free-form string representation of the raw value intended for user presentation or %NULL.
20 : */
21 : /**
22 : * bd_smart_ata_attribute_free: (skip)
23 : * @attr: (nullable): %BDSmartATAAttribute to free
24 : *
25 : * Frees @attr.
26 : */
27 1419 : void bd_smart_ata_attribute_free (BDSmartATAAttribute *attr) {
28 1419 : if (attr == NULL)
29 0 : return;
30 1419 : g_free (attr->name);
31 1419 : g_free (attr->well_known_name);
32 1419 : g_free (attr->pretty_value_string);
33 1419 : g_free (attr);
34 : }
35 :
36 : /**
37 : * bd_smart_ata_attribute_copy: (skip)
38 : * @attr: (nullable): %BDSmartATAAttribute to copy
39 : *
40 : * Creates a new copy of @attr.
41 : */
42 944 : BDSmartATAAttribute * bd_smart_ata_attribute_copy (BDSmartATAAttribute *attr) {
43 : BDSmartATAAttribute *new_attr;
44 :
45 944 : if (attr == NULL)
46 0 : return NULL;
47 :
48 944 : new_attr = g_new0 (BDSmartATAAttribute, 1);
49 944 : memcpy (new_attr, attr, sizeof (BDSmartATAAttribute));
50 944 : new_attr->name = g_strdup (attr->name);
51 944 : new_attr->well_known_name = g_strdup (attr->well_known_name);
52 944 : new_attr->pretty_value_string = g_strdup (attr->pretty_value_string);
53 :
54 944 : return new_attr;
55 : }
56 :
57 2362 : GType bd_smart_ata_attribute_get_type () {
58 : static GType type = 0;
59 :
60 2362 : if (G_UNLIKELY (type == 0)) {
61 1 : type = g_boxed_type_register_static ("BDSmartATAAttribute",
62 : (GBoxedCopyFunc) bd_smart_ata_attribute_copy,
63 : (GBoxedFreeFunc) bd_smart_ata_attribute_free);
64 : }
65 2362 : return type;
66 : }
67 :
68 : /**
69 : * BDSmartATA:
70 : * @smart_supported: Indicates that the device has SMART capability.
71 : * @smart_enabled: Indicates that the SMART support is enabled.
72 : * @overall_status_passed: %TRUE if the device SMART overall-health self-assessment test result has passed.
73 : * @offline_data_collection_status: The offline data collection status. See #BDSmartATAOfflineDataCollectionStatus.
74 : * @auto_offline_data_collection_enabled: %TRUE if Automatic Offline Data Collection is enabled. Only supported with the smartmontools plugin.
75 : * @offline_data_collection_completion: Total time in seconds to complete Offline data collection.
76 : * @offline_data_collection_capabilities: Bitmask of offline data collection capabilities, see #BDSmartATAOfflineDataCollectionCapabilities. Only supported with the smartmontools plugin.
77 : * @self_test_status: Self-test execution status. See #BDSmartATASelfTestStatus.
78 : * @self_test_percent_remaining: The percentage remaining of a running self-test.
79 : * @self_test_polling_short: Short self-test routine recommended polling time in minutes or 0 if not supported.
80 : * @self_test_polling_extended: Extended self-test routine recommended polling time in minutes or 0 if not supported.
81 : * @self_test_polling_conveyance: Conveyance self-test routine recommended polling time in minutes or 0 if not supported.
82 : * @smart_capabilities: Bitmask of device misc. SMART capabilities. See #BDSmartATACapabilities. Only supported with the smartmontools plugin.
83 : * @attributes: (array zero-terminated=1): A list of reported SMART attributes.
84 : * @power_on_time: The count of minutes in power-on state.
85 : * @power_cycle_count: The count of full hard disk power on/off cycles.
86 : * @temperature: The current drive temperature in Kelvin or 0 when temperature is not reported.
87 : */
88 : /**
89 : * bd_smart_ata_free: (skip)
90 : * @data: (nullable): %BDSmartATA to free
91 : *
92 : * Frees @data.
93 : */
94 30 : void bd_smart_ata_free (BDSmartATA *data) {
95 : BDSmartATAAttribute **attr;
96 :
97 30 : if (data == NULL)
98 0 : return;
99 :
100 505 : for (attr = data->attributes; attr && *attr; attr++)
101 475 : bd_smart_ata_attribute_free (*attr);
102 30 : g_free (data->attributes);
103 30 : g_free (data);
104 : }
105 :
106 : /**
107 : * bd_smart_ata_copy: (skip)
108 : * @data: (nullable): %BDSmartATA to copy
109 : *
110 : * Creates a new copy of @data.
111 : */
112 0 : BDSmartATA * bd_smart_ata_copy (BDSmartATA *data) {
113 : BDSmartATA *new_data;
114 : BDSmartATAAttribute **attr;
115 : GPtrArray *ptr_array;
116 :
117 0 : if (data == NULL)
118 0 : return NULL;
119 :
120 0 : new_data = g_new0 (BDSmartATA, 1);
121 0 : memcpy (new_data, data, sizeof (BDSmartATA));
122 :
123 0 : ptr_array = g_ptr_array_new ();
124 0 : for (attr = data->attributes; attr && *attr; attr++)
125 0 : g_ptr_array_add (ptr_array, bd_smart_ata_attribute_copy (*attr));
126 0 : g_ptr_array_add (ptr_array, NULL);
127 0 : new_data->attributes = (BDSmartATAAttribute **) g_ptr_array_free (ptr_array, FALSE);
128 :
129 0 : return new_data;
130 : }
131 :
132 228 : GType bd_smart_ata_get_type () {
133 : static GType type = 0;
134 :
135 228 : if (G_UNLIKELY (type == 0)) {
136 1 : type = g_boxed_type_register_static ("BDSmartATA",
137 : (GBoxedCopyFunc) bd_smart_ata_copy,
138 : (GBoxedFreeFunc) bd_smart_ata_free);
139 : }
140 228 : return type;
141 : }
142 :
143 : /**
144 : * BDSmartSCSI:
145 : * @smart_supported: Indicates that the device has SMART capability.
146 : * @smart_enabled: Indicates that the SMART support is enabled.
147 : * @overall_status_passed: %TRUE if the device SMART overall-health self-assessment test result has passed, %FALSE otherwise with @scsi_ie fields set.
148 : * @scsi_ie: The reported SCSI Informational Exception in a simplified form. See #BDSmartSCSIInformationalException.
149 : * @scsi_ie_asc: The reported SCSI Informational Exception ASC (Additional Sense Code) value (only values of 0xb - warnings and 0x5d - impending failures are taken in account).
150 : * @scsi_ie_ascq: The reported SCSI Informational Exception ASCQ (Additional Sense Code Qualifier) value.
151 : * @scsi_ie_string: String representation of the current SCSI Informational Exception.
152 : * @background_scan_status: Background scan status, see #BDSmartSCSIBackgroundScanStatus.
153 : * @background_scan_progress: Percent of a background scan progress.
154 : * @background_scan_runs: Number of background scans performed.
155 : * @background_medium_scan_runs: Number of background medium scans performed.
156 : * @read_errors_corrected_eccfast: Error counter log - read errors corrected by ECC fast.
157 : * @read_errors_corrected_eccdelayed: Error counter log - read errors corrected by ECC delayed.
158 : * @read_errors_corrected_rereads: Error counter log - read errors corrected by rereads.
159 : * @read_errors_corrected_total: Error counter log - total read errors corrected.
160 : * @read_errors_uncorrected: Error counter log - total uncorrected read errors.
161 : * @read_processed_bytes: Error counter log - total bytes processed.
162 : * @write_errors_corrected_eccfast: Error counter log - write errors corrected by ECC fast.
163 : * @write_errors_corrected_eccdelayed: Error counter log - write errors corrected by ECC delayed.
164 : * @write_errors_corrected_rewrites: Error counter log - write errors corrected by rewrites.
165 : * @write_errors_corrected_total: Error counter log - total write errors corrected.
166 : * @write_errors_uncorrected: Error counter log - total uncorrected write errors.
167 : * @write_processed_bytes: Error counter log - total bytes processed.
168 : * @start_stop_cycle_count: Accumulated start-stop cycles.
169 : * @start_stop_cycle_lifetime: Specified cycle count over device lifetime.
170 : * @load_unload_cycle_count: Accumulated load-unload cycles.
171 : * @load_unload_cycle_lifetime: Specified load-unload count over device lifetime.
172 : * @scsi_grown_defect_list: Elements in grown defect list.
173 : * @power_on_time: Accumulated power on time in minutes.
174 : * @temperature_warning_enabled: Indicates that temperature warning is enabled.
175 : * @temperature: The current drive temperature in Kelvin or 0 when temperature is not reported.
176 : * @temperature_drive_trip: The drive trip temperature in Kelvin or 0 when temperature is not reported.
177 : */
178 : /**
179 : * bd_smart_scsi_free: (skip)
180 : * @data: (nullable): %BDSmartSCSI to free
181 : *
182 : * Frees @data.
183 : */
184 6 : void bd_smart_scsi_free (BDSmartSCSI *data) {
185 6 : if (data == NULL)
186 0 : return;
187 :
188 6 : g_free (data->scsi_ie_string);
189 6 : g_free (data);
190 : }
191 :
192 : /**
193 : * bd_smart_scsi_copy: (skip)
194 : * @data: (nullable): %BDSmartSCSI to copy
195 : *
196 : * Creates a new copy of @data.
197 : */
198 0 : BDSmartSCSI * bd_smart_scsi_copy (BDSmartSCSI *data) {
199 : BDSmartSCSI *new_data;
200 :
201 0 : if (data == NULL)
202 0 : return NULL;
203 :
204 0 : new_data = g_new0 (BDSmartSCSI, 1);
205 0 : memcpy (new_data, data, sizeof (BDSmartSCSI));
206 0 : new_data->scsi_ie_string = g_strdup (data->scsi_ie_string);
207 :
208 0 : return new_data;
209 : }
210 :
211 45 : GType bd_smart_scsi_get_type () {
212 : static GType type = 0;
213 :
214 45 : if (G_UNLIKELY (type == 0)) {
215 1 : type = g_boxed_type_register_static ("BDSmartSCSI",
216 : (GBoxedCopyFunc) bd_smart_scsi_copy,
217 : (GBoxedFreeFunc) bd_smart_scsi_free);
218 : }
219 45 : return type;
220 : }
221 :
222 0 : static gboolean bd_smart_is_tech_avail_stub (BDSmartTechMode tech G_GNUC_UNUSED, G_GNUC_UNUSED guint64 mode G_GNUC_UNUSED, GError **error) {
223 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_smart_is_tech_avail' called, but not implemented!");
224 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
225 : "The function 'bd_smart_is_tech_avail' called, but not implemented!");
226 0 : return FALSE;
227 : }
228 :
229 : static gboolean (*_bd_smart_is_tech_avail) (BDSmartTechMode tech, G_GNUC_UNUSED guint64 mode, GError **error) = bd_smart_is_tech_avail_stub;
230 :
231 : /**
232 : * bd_smart_is_tech_avail:
233 : * @tech: the queried tech
234 : * @mode: a bit mask of queried modes of operation (#BDSmartTechMode) for @tech
235 : * @error: (out) (nullable): place to store error (details about why the @tech-@mode combination is not available)
236 : *
237 : * Returns: whether the @tech-@mode combination is available -- supported by the
238 : * plugin implementation and having all the runtime dependencies available
239 : */
240 0 : gboolean bd_smart_is_tech_avail (BDSmartTechMode tech, G_GNUC_UNUSED guint64 mode, GError **error) {
241 0 : return _bd_smart_is_tech_avail (tech, mode, error);
242 : }
243 :
244 :
245 0 : static BDSmartATA * bd_smart_ata_get_info_stub (const gchar *device G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
246 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_smart_ata_get_info' called, but not implemented!");
247 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
248 : "The function 'bd_smart_ata_get_info' called, but not implemented!");
249 0 : return NULL;
250 : }
251 :
252 : static BDSmartATA * (*_bd_smart_ata_get_info) (const gchar *device, const BDExtraArg **extra, GError **error) = bd_smart_ata_get_info_stub;
253 :
254 : /**
255 : * bd_smart_ata_get_info:
256 : * @device: device to check.
257 : * @extra: (nullable) (array zero-terminated=1): extra options to pass through.
258 : * @error: (out) (optional): place to store error (if any).
259 : *
260 : * Retrieve SMART information from the drive.
261 : *
262 : * Returns: (transfer full): ATA SMART log or %NULL in case of an error (with @error set).
263 : *
264 : * Tech category: %BD_SMART_TECH_ATA-%BD_SMART_TECH_MODE_INFO
265 : */
266 28 : BDSmartATA * bd_smart_ata_get_info (const gchar *device, const BDExtraArg **extra, GError **error) {
267 28 : return _bd_smart_ata_get_info (device, extra, error);
268 : }
269 :
270 :
271 0 : static BDSmartATA * bd_smart_ata_get_info_from_data_stub (const guint8 *data G_GNUC_UNUSED, gsize data_len G_GNUC_UNUSED, GError **error) {
272 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_smart_ata_get_info_from_data' called, but not implemented!");
273 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
274 : "The function 'bd_smart_ata_get_info_from_data' called, but not implemented!");
275 0 : return NULL;
276 : }
277 :
278 : static BDSmartATA * (*_bd_smart_ata_get_info_from_data) (const guint8 *data, gsize data_len, GError **error) = bd_smart_ata_get_info_from_data_stub;
279 :
280 : /**
281 : * bd_smart_ata_get_info_from_data:
282 : * @data: (array length=data_len): binary data to parse.
283 : * @data_len: length of the data supplied.
284 : * @error: (out) (optional): place to store error (if any).
285 : *
286 : * Retrieve SMART information from the supplied data.
287 : *
288 : * Returns: (transfer full): ATA SMART log or %NULL in case of an error (with @error set).
289 : *
290 : * Tech category: %BD_SMART_TECH_ATA-%BD_SMART_TECH_MODE_INFO
291 : */
292 23 : BDSmartATA * bd_smart_ata_get_info_from_data (const guint8 *data, gsize data_len, GError **error) {
293 23 : return _bd_smart_ata_get_info_from_data (data, data_len, error);
294 : }
295 :
296 :
297 0 : static BDSmartSCSI * bd_smart_scsi_get_info_stub (const gchar *device G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
298 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_smart_scsi_get_info' called, but not implemented!");
299 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
300 : "The function 'bd_smart_scsi_get_info' called, but not implemented!");
301 0 : return NULL;
302 : }
303 :
304 : static BDSmartSCSI * (*_bd_smart_scsi_get_info) (const gchar *device, const BDExtraArg **extra, GError **error) = bd_smart_scsi_get_info_stub;
305 :
306 : /**
307 : * bd_smart_scsi_get_info:
308 : * @device: device to check.
309 : * @extra: (nullable) (array zero-terminated=1): extra options to pass through.
310 : * @error: (out) (optional): place to store error (if any).
311 : *
312 : * Retrieve SMART information from SCSI or SAS-compliant drive.
313 : *
314 : * Returns: (transfer full): SCSI SMART log or %NULL in case of an error (with @error set).
315 : *
316 : * Tech category: %BD_SMART_TECH_SCSI-%BD_SMART_TECH_MODE_INFO
317 : */
318 22 : BDSmartSCSI * bd_smart_scsi_get_info (const gchar *device, const BDExtraArg **extra, GError **error) {
319 22 : return _bd_smart_scsi_get_info (device, extra, error);
320 : }
321 :
322 :
323 0 : static gboolean bd_smart_set_enabled_stub (const gchar *device G_GNUC_UNUSED, gboolean enabled G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
324 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_smart_set_enabled' called, but not implemented!");
325 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
326 : "The function 'bd_smart_set_enabled' called, but not implemented!");
327 0 : return FALSE;
328 : }
329 :
330 : static gboolean (*_bd_smart_set_enabled) (const gchar *device, gboolean enabled, const BDExtraArg **extra, GError **error) = bd_smart_set_enabled_stub;
331 :
332 : /**
333 : * bd_smart_set_enabled:
334 : * @device: SMART-capable device.
335 : * @enabled: whether to enable or disable the SMART functionality
336 : * @extra: (nullable) (array zero-terminated=1): extra options to pass through.
337 : * @error: (out) (optional): place to store error (if any).
338 : *
339 : * Enables or disables SMART functionality on device.
340 : *
341 : * Returns: %TRUE when the functionality was set successfully or %FALSE in case of an error (with @error set).
342 : *
343 : * Tech category: %BD_SMART_TECH_ATA-%BD_SMART_TECH_MODE_INFO
344 : */
345 30 : gboolean bd_smart_set_enabled (const gchar *device, gboolean enabled, const BDExtraArg **extra, GError **error) {
346 30 : return _bd_smart_set_enabled (device, enabled, extra, error);
347 : }
348 :
349 :
350 0 : static gboolean bd_smart_device_self_test_stub (const gchar *device G_GNUC_UNUSED, BDSmartSelfTestOp operation G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
351 0 : bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_smart_device_self_test' called, but not implemented!");
352 0 : g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
353 : "The function 'bd_smart_device_self_test' called, but not implemented!");
354 0 : return FALSE;
355 : }
356 :
357 : static gboolean (*_bd_smart_device_self_test) (const gchar *device, BDSmartSelfTestOp operation, const BDExtraArg **extra, GError **error) = bd_smart_device_self_test_stub;
358 :
359 : /**
360 : * bd_smart_device_self_test:
361 : * @device: device to trigger the test on.
362 : * @operation: #BDSmartSelfTestOp self-test operation.
363 : * @extra: (nullable) (array zero-terminated=1): extra options to pass through.
364 : * @error: (out) (optional): place to store error (if any).
365 : *
366 : * Executes or aborts device self-test.
367 : *
368 : * Returns: %TRUE when the self-test was triggered successfully or %FALSE in case of an error (with @error set).
369 : *
370 : * Tech category: %BD_SMART_TECH_ATA-%BD_SMART_TECH_MODE_SELFTEST
371 : */
372 78 : gboolean bd_smart_device_self_test (const gchar *device, BDSmartSelfTestOp operation, const BDExtraArg **extra, GError **error) {
373 78 : return _bd_smart_device_self_test (device, operation, extra, error);
374 : }
375 :
376 :
377 2 : static gpointer load_smart_from_plugin(const gchar *so_name) {
378 2 : void *handle = NULL;
379 2 : char *error = NULL;
380 2 : gboolean (*init_fn) (void) = NULL;
381 :
382 2 : handle = dlopen(so_name, RTLD_LAZY);
383 2 : if (!handle) {
384 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load module smart: %s", dlerror());
385 0 : return NULL;
386 : }
387 :
388 2 : dlerror();
389 2 : * (void**) (&init_fn) = dlsym(handle, "bd_smart_init");
390 2 : if ((error = dlerror()) != NULL)
391 0 : bd_utils_log_format (BD_UTILS_LOG_DEBUG, "failed to load the init() function for smart: %s", error);
392 : /* coverity[dead_error_condition] */
393 2 : if (init_fn && !init_fn()) {
394 0 : dlclose(handle);
395 0 : return NULL;
396 : }
397 2 : init_fn = NULL;
398 :
399 2 : dlerror();
400 2 : * (void**) (&_bd_smart_is_tech_avail) = dlsym(handle, "bd_smart_is_tech_avail");
401 2 : if ((error = dlerror()) != NULL)
402 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_smart_is_tech_avail: %s", error);
403 :
404 2 : dlerror();
405 2 : * (void**) (&_bd_smart_ata_get_info) = dlsym(handle, "bd_smart_ata_get_info");
406 2 : if ((error = dlerror()) != NULL)
407 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_smart_ata_get_info: %s", error);
408 :
409 2 : dlerror();
410 2 : * (void**) (&_bd_smart_ata_get_info_from_data) = dlsym(handle, "bd_smart_ata_get_info_from_data");
411 2 : if ((error = dlerror()) != NULL)
412 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_smart_ata_get_info_from_data: %s", error);
413 :
414 2 : dlerror();
415 2 : * (void**) (&_bd_smart_scsi_get_info) = dlsym(handle, "bd_smart_scsi_get_info");
416 2 : if ((error = dlerror()) != NULL)
417 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_smart_scsi_get_info: %s", error);
418 :
419 2 : dlerror();
420 2 : * (void**) (&_bd_smart_set_enabled) = dlsym(handle, "bd_smart_set_enabled");
421 2 : if ((error = dlerror()) != NULL)
422 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_smart_set_enabled: %s", error);
423 :
424 2 : dlerror();
425 2 : * (void**) (&_bd_smart_device_self_test) = dlsym(handle, "bd_smart_device_self_test");
426 2 : if ((error = dlerror()) != NULL)
427 0 : bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_smart_device_self_test: %s", error);
428 :
429 2 : return handle;
430 : }
431 :
432 2 : static gboolean unload_smart (gpointer handle) {
433 2 : char *error = NULL;
434 2 : gboolean (*close_fn) (void) = NULL;
435 :
436 2 : _bd_smart_is_tech_avail = bd_smart_is_tech_avail_stub;
437 2 : _bd_smart_ata_get_info = bd_smart_ata_get_info_stub;
438 2 : _bd_smart_ata_get_info_from_data = bd_smart_ata_get_info_from_data_stub;
439 2 : _bd_smart_scsi_get_info = bd_smart_scsi_get_info_stub;
440 2 : _bd_smart_set_enabled = bd_smart_set_enabled_stub;
441 2 : _bd_smart_device_self_test = bd_smart_device_self_test_stub;
442 :
443 2 : dlerror();
444 2 : * (void**) (&close_fn) = dlsym(handle, "bd_smart_close");
445 2 : if (((error = dlerror()) != NULL) || !close_fn)
446 0 : bd_utils_log_format (BD_UTILS_LOG_DEBUG, "failed to load the close_plugin() function for smart: %s", error);
447 : /* coverity[dead_error_condition] */
448 2 : if (close_fn) {
449 2 : close_fn();
450 : }
451 :
452 2 : return dlclose(handle) == 0;
453 : }
454 :
|