LCOV - code coverage report
Current view: top level - lib/plugin_apis - loop.c (source / functions) Coverage Total Hit
Test: libblockdev Coverage Report Lines: 57.7 % 137 79
Test Date: 2026-01-26 13:19:28 Functions: 59.1 % 22 13
Legend: Lines: hit not hit

            Line data    Source code
       1            3 : GQuark  bd_loop_error_quark (void) {
       2            3 :         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            1 : gboolean  bd_loop_is_tech_avail (BDLoopTech tech, guint64 mode, GError **error) {
      81            1 :     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           31 : 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           31 :     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            5 : gboolean  bd_loop_set_autoclear (const gchar *loop, gboolean autoclear, GError **error) {
     232            5 :     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            2 : gboolean  bd_loop_set_capacity (const gchar *loop, GError **error) {
     258            2 :     return _bd_loop_set_capacity (loop, error);
     259              : }
     260              : 
     261              : 
     262          157 : static gpointer load_loop_from_plugin(const gchar *so_name) {
     263          157 :     void *handle = NULL;
     264          157 :     char *error = NULL;
     265          157 :     gboolean (*init_fn) (void) = NULL;
     266              : 
     267          157 :     handle = dlopen(so_name, RTLD_LAZY);
     268          157 :     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          157 :     dlerror();
     274          157 :     * (void**) (&init_fn) = dlsym(handle, "bd_loop_init");
     275          157 :     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          157 :     if (init_fn && !init_fn()) {
     279            0 :         dlclose(handle);
     280            0 :         return NULL;
     281              :     }
     282          157 :     init_fn = NULL;
     283              : 
     284          157 :     dlerror();
     285          157 :     * (void**) (&_bd_loop_is_tech_avail) = dlsym(handle, "bd_loop_is_tech_avail");
     286          157 :     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          157 :     dlerror();
     290          157 :     * (void**) (&_bd_loop_info) = dlsym(handle, "bd_loop_info");
     291          157 :     if ((error = dlerror()) != NULL)
     292            0 :         bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_info: %s", error);
     293              : 
     294          157 :     dlerror();
     295          157 :     * (void**) (&_bd_loop_get_loop_name) = dlsym(handle, "bd_loop_get_loop_name");
     296          157 :     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          157 :     dlerror();
     300          157 :     * (void**) (&_bd_loop_setup) = dlsym(handle, "bd_loop_setup");
     301          157 :     if ((error = dlerror()) != NULL)
     302            0 :         bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_setup: %s", error);
     303              : 
     304          157 :     dlerror();
     305          157 :     * (void**) (&_bd_loop_setup_from_fd) = dlsym(handle, "bd_loop_setup_from_fd");
     306          157 :     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          157 :     dlerror();
     310          157 :     * (void**) (&_bd_loop_teardown) = dlsym(handle, "bd_loop_teardown");
     311          157 :     if ((error = dlerror()) != NULL)
     312            0 :         bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_loop_teardown: %s", error);
     313              : 
     314          157 :     dlerror();
     315          157 :     * (void**) (&_bd_loop_set_autoclear) = dlsym(handle, "bd_loop_set_autoclear");
     316          157 :     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          157 :     dlerror();
     320          157 :     * (void**) (&_bd_loop_set_capacity) = dlsym(handle, "bd_loop_set_capacity");
     321          157 :     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          157 :     return handle;
     325              : }
     326              : 
     327          157 : static gboolean unload_loop (gpointer handle) {
     328          157 :     char *error = NULL;
     329          157 :     gboolean (*close_fn) (void) = NULL;
     330              : 
     331          157 :     _bd_loop_is_tech_avail = bd_loop_is_tech_avail_stub;
     332          157 :     _bd_loop_info = bd_loop_info_stub;
     333          157 :     _bd_loop_get_loop_name = bd_loop_get_loop_name_stub;
     334          157 :     _bd_loop_setup = bd_loop_setup_stub;
     335          157 :     _bd_loop_setup_from_fd = bd_loop_setup_from_fd_stub;
     336          157 :     _bd_loop_teardown = bd_loop_teardown_stub;
     337          157 :     _bd_loop_set_autoclear = bd_loop_set_autoclear_stub;
     338          157 :     _bd_loop_set_capacity = bd_loop_set_capacity_stub;
     339              : 
     340          157 :     dlerror();
     341          157 :     * (void**) (&close_fn) = dlsym(handle, "bd_loop_close");
     342          157 :     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          157 :     if (close_fn) {
     346          157 :         close_fn();
     347              :     }
     348              : 
     349          157 :     return dlclose(handle) == 0;
     350              : }
     351              : 
        

Generated by: LCOV version 2.0-1