GQuark  bd_dm_error_quark (void) {
        return g_quark_from_static_string ("g-bd-dm-error-quark");
}

static gboolean  bd_dm_is_tech_avail_stub (BDDMTech tech G_GNUC_UNUSED, guint64 mode G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_is_tech_avail' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_is_tech_avail' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_dm_is_tech_avail) (BDDMTech tech, guint64 mode, GError **error) = bd_dm_is_tech_avail_stub;

/**
 * bd_dm_is_tech_avail:
 * @tech: the queried tech
 * @mode: a bit mask of queried modes of operation (#BDDMTechMode) for @tech
 * @error: (out) (optional): place to store error (details about why the @tech-@mode combination is not available)
 *
 * Returns: whether the @tech-@mode combination is available -- supported by the
 *          plugin implementation and having all the runtime dependencies available
 */
gboolean  bd_dm_is_tech_avail (BDDMTech tech, guint64 mode, GError **error) {
    return _bd_dm_is_tech_avail (tech, mode, error);
}


static gboolean  bd_dm_create_linear_stub (const gchar *map_name G_GNUC_UNUSED, const gchar *device G_GNUC_UNUSED, guint64 length G_GNUC_UNUSED, const gchar *uuid G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_create_linear' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_create_linear' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_dm_create_linear) (const gchar *map_name, const gchar *device, guint64 length, const gchar *uuid, GError **error) = bd_dm_create_linear_stub;

/**
 * bd_dm_create_linear:
 * @map_name: name of the map
 * @device: device to create map for
 * @length: length of the mapping in sectors
 * @uuid: (nullable): UUID for the new dev mapper device or %NULL if not specified
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the new linear mapping @map_name was successfully created
 * for the @device or not
 *
 * Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_CREATE_ACTIVATE
 */
gboolean  bd_dm_create_linear (const gchar *map_name, const gchar *device, guint64 length, const gchar *uuid, GError **error) {
    return _bd_dm_create_linear (map_name, device, length, uuid, error);
}


static gboolean  bd_dm_remove_stub (const gchar *map_name G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_remove' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_remove' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_dm_remove) (const gchar *map_name, GError **error) = bd_dm_remove_stub;

/**
 * bd_dm_remove:
 * @map_name: name of the map to remove
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @map_name map was successfully removed or not
 *
 * Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_REMOVE_DEACTIVATE
 */
gboolean  bd_dm_remove (const gchar *map_name, GError **error) {
    return _bd_dm_remove (map_name, error);
}


static gchar* bd_dm_name_from_node_stub (const gchar *dm_node G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_name_from_node' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_name_from_node' called, but not implemented!");
    return NULL;
}

static gchar* (*_bd_dm_name_from_node) (const gchar *dm_node, GError **error) = bd_dm_name_from_node_stub;

/**
 * bd_dm_name_from_node:
 * @dm_node: name of the DM node (e.g. "dm-0")
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: map name of the map providing the @dm_node device or %NULL
 * (@error) contains the error in such cases
 *
 * Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_QUERY
 */
gchar* bd_dm_name_from_node (const gchar *dm_node, GError **error) {
    return _bd_dm_name_from_node (dm_node, error);
}


static gchar* bd_dm_node_from_name_stub (const gchar *map_name G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_node_from_name' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_node_from_name' called, but not implemented!");
    return NULL;
}

static gchar* (*_bd_dm_node_from_name) (const gchar *map_name, GError **error) = bd_dm_node_from_name_stub;

/**
 * bd_dm_node_from_name:
 * @map_name: name of the queried DM map
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: DM node name for the @map_name map or %NULL (@error) contains
 * the error in such cases
 *
 * Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_QUERY
 */
gchar* bd_dm_node_from_name (const gchar *map_name, GError **error) {
    return _bd_dm_node_from_name (map_name, error);
}


static gchar* bd_dm_get_subsystem_from_name_stub (const gchar *device_name G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_get_subsystem_from_name' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_get_subsystem_from_name' called, but not implemented!");
    return NULL;
}

static gchar* (*_bd_dm_get_subsystem_from_name) (const gchar *device_name, GError **error) = bd_dm_get_subsystem_from_name_stub;

/**
 * bd_dm_get_subsystem_from_name:
 * @device_name: name of the device
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: subsystem of the given device
 *
 * Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_QUERY
 */
gchar* bd_dm_get_subsystem_from_name (const gchar *device_name, GError **error) {
    return _bd_dm_get_subsystem_from_name (device_name, error);
}


static gboolean  bd_dm_map_exists_stub (const gchar *map_name G_GNUC_UNUSED, gboolean live_only G_GNUC_UNUSED, gboolean active_only G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_dm_map_exists' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_dm_map_exists' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_dm_map_exists) (const gchar *map_name, gboolean live_only, gboolean active_only, GError **error) = bd_dm_map_exists_stub;

/**
 * bd_dm_map_exists:
 * @map_name: name of the queried map
 * @live_only: whether to go through the live maps only or not
 * @active_only: whether to ignore suspended maps or not
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the given @map_name exists (and is live if @live_only is
 * %TRUE (and is active if @active_only is %TRUE)). If %FALSE is returned,
 * @error indicates whether error appeared (non-%NULL) or not (%NULL).
 *
 * Tech category: %BD_DM_TECH_MAP-%BD_DM_TECH_MODE_QUERY
 */
gboolean  bd_dm_map_exists (const gchar *map_name, gboolean live_only, gboolean active_only, GError **error) {
    return _bd_dm_map_exists (map_name, live_only, active_only, error);
}


static gpointer load_dm_from_plugin(const gchar *so_name) {
    void *handle = NULL;
    char *error = NULL;
    gboolean (*init_fn) (void) = NULL;

    handle = dlopen(so_name, RTLD_LAZY | RTLD_NODELETE);
    if (!handle) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load module dm: %s", dlerror());
        return NULL;
    }

    dlerror();
    * (void**) (&init_fn) = dlsym(handle, "bd_dm_init");
    if ((error = dlerror()) != NULL)
        bd_utils_log_format (BD_UTILS_LOG_DEBUG, "failed to load the init() function for dm: %s", error);
    /* coverity[dead_error_condition] */
    if (init_fn && !init_fn()) {
        dlclose(handle);
        return NULL;
    }
    init_fn = NULL;

    dlerror();
    * (void**) (&_bd_dm_is_tech_avail) = dlsym(handle, "bd_dm_is_tech_avail");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_is_tech_avail: %s", error);
        _bd_dm_is_tech_avail = bd_dm_is_tech_avail_stub;
    }

    dlerror();
    * (void**) (&_bd_dm_create_linear) = dlsym(handle, "bd_dm_create_linear");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_create_linear: %s", error);
        _bd_dm_create_linear = bd_dm_create_linear_stub;
    }

    dlerror();
    * (void**) (&_bd_dm_remove) = dlsym(handle, "bd_dm_remove");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_remove: %s", error);
        _bd_dm_remove = bd_dm_remove_stub;
    }

    dlerror();
    * (void**) (&_bd_dm_name_from_node) = dlsym(handle, "bd_dm_name_from_node");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_name_from_node: %s", error);
        _bd_dm_name_from_node = bd_dm_name_from_node_stub;
    }

    dlerror();
    * (void**) (&_bd_dm_node_from_name) = dlsym(handle, "bd_dm_node_from_name");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_node_from_name: %s", error);
        _bd_dm_node_from_name = bd_dm_node_from_name_stub;
    }

    dlerror();
    * (void**) (&_bd_dm_get_subsystem_from_name) = dlsym(handle, "bd_dm_get_subsystem_from_name");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_get_subsystem_from_name: %s", error);
        _bd_dm_get_subsystem_from_name = bd_dm_get_subsystem_from_name_stub;
    }

    dlerror();
    * (void**) (&_bd_dm_map_exists) = dlsym(handle, "bd_dm_map_exists");
    if ((error = dlerror()) != NULL) {
        bd_utils_log_format (BD_UTILS_LOG_WARNING, "failed to load bd_dm_map_exists: %s", error);
        _bd_dm_map_exists = bd_dm_map_exists_stub;
    }

    return handle;
}

static gboolean unload_dm (gpointer handle) {
    char *error = NULL;
    gboolean (*close_fn) (void) = NULL;

    _bd_dm_is_tech_avail = bd_dm_is_tech_avail_stub;
    _bd_dm_create_linear = bd_dm_create_linear_stub;
    _bd_dm_remove = bd_dm_remove_stub;
    _bd_dm_name_from_node = bd_dm_name_from_node_stub;
    _bd_dm_node_from_name = bd_dm_node_from_name_stub;
    _bd_dm_get_subsystem_from_name = bd_dm_get_subsystem_from_name_stub;
    _bd_dm_map_exists = bd_dm_map_exists_stub;

    dlerror();
    * (void**) (&close_fn) = dlsym(handle, "bd_dm_close");
    if (((error = dlerror()) != NULL) || !close_fn)
        bd_utils_log_format (BD_UTILS_LOG_DEBUG, "failed to load the close_plugin() function for dm: %s", error);
    /* coverity[dead_error_condition] */
    if (close_fn) {
        close_fn();
    }

    return dlclose(handle) == 0;
}

