GQuark  bd_btrfs_error_quark (void) {
        return g_quark_from_static_string ("g-bd-btrfs-error-quark");
}

/**
 * BDBtrfsDeviceInfo:
 * @id: ID of the device
 * @path: path of the device
 * @size: size of the device
 * @used: size of the used space
 */
/**
 * bd_btrfs_device_info_copy: (skip)
 * @info: (nullable): %BDBtrfsDeviceInfo to copy
 *
 * Creates a new copy of @info.
 */
BDBtrfsDeviceInfo* bd_btrfs_device_info_copy (BDBtrfsDeviceInfo *info) {
        if (info == NULL)
        return NULL;

    BDBtrfsDeviceInfo *new_info = g_new0 (BDBtrfsDeviceInfo, 1);

    new_info->id = info->id;
    new_info->path = g_strdup (info->path);
    new_info->size = info->size;
    new_info->used = info->used;

    return new_info;
}

/**
 * bd_btrfs_device_info_free: (skip)
 * @info: (nullable): %BDBtrfsDeviceInfo to free
 *
 * Frees @info.
 */
void  bd_btrfs_device_info_free (BDBtrfsDeviceInfo *info) {
        if (info == NULL)
        return;

    g_free (info->path);
    g_free (info);
}

GType  bd_btrfs_device_info_get_type () {
        static GType type = 0;

    if (G_UNLIKELY(type == 0)) {
        type = g_boxed_type_register_static("BDBtrfsDeviceInfo",
                                            (GBoxedCopyFunc) bd_btrfs_device_info_copy,
                                            (GBoxedFreeFunc) bd_btrfs_device_info_free);
    }

    return type;
}

/**
 * BDBtrfsSubvolumeInfo:
 * @id: ID of the subvolume
 * @parent_id: ID of the parent (sub)volume
 * @path: path of the subvolume
 */
/**
 * bd_btrfs_subvolume_info_copy: (skip)
 * @info: (nullable): %BDBtrfsSubvolumeInfo to copy
 *
 * Creates a new copy of @info.
 */
BDBtrfsSubvolumeInfo* bd_btrfs_subvolume_info_copy (BDBtrfsSubvolumeInfo *info) {
        if (info == NULL)
        return NULL;

    BDBtrfsSubvolumeInfo *new_info = g_new0 (BDBtrfsSubvolumeInfo, 1);

    new_info->id = info->id;
    new_info->parent_id = info->parent_id;
    new_info->path = g_strdup (info->path);

    return new_info;
}

/**
 * bd_btrfs_subvolume_info_free: (skip)
 * @info: (nullable): %BDBtrfsSubvolumeInfo to free
 *
 * Frees @info.
 */
void  bd_btrfs_subvolume_info_free (BDBtrfsSubvolumeInfo *info) {
        if (info == NULL)
        return;

    g_free (info->path);
    g_free (info);
}

GType  bd_btrfs_subvolume_info_get_type () {
        static GType type = 0;

    if (G_UNLIKELY(type == 0)) {
        type = g_boxed_type_register_static("BDBtrfsSubvolumeInfo",
                                            (GBoxedCopyFunc) bd_btrfs_subvolume_info_copy,
                                            (GBoxedFreeFunc) bd_btrfs_subvolume_info_free);
    }

    return type;
}

/**
 * BDBtrfsFilesystemInfo:
 * @label: label of the filesystem
 * @uuid: uuid of the filesystem
 * @num_devices: number of device in the filesystem
 * @used: size of the used space
 */
/**
 * bd_btrfs_filesystem_info_copy: (skip)
 * @info: (nullable): %BDBtrfsFilesystemInfo to copy
 *
 * Creates a new copy of @info.
 */
BDBtrfsFilesystemInfo* bd_btrfs_filesystem_info_copy (BDBtrfsFilesystemInfo *info) {
        if (info == NULL)
        return NULL;

    BDBtrfsFilesystemInfo *new_info = g_new0 (BDBtrfsFilesystemInfo, 1);

    new_info->label = g_strdup (info->label);
    new_info->uuid = g_strdup (info->uuid);
    new_info->num_devices = info->num_devices;
    new_info->used = info->used;

    return new_info;
}

/**
 * bd_btrfs_filesystem_info_free: (skip)
 * @info: (nullable): %BDBtrfsFilesystemInfo to free
 *
 * Frees @info.
 */
void  bd_btrfs_filesystem_info_free (BDBtrfsFilesystemInfo *info) {
        if (info == NULL)
        return;

    g_free (info->label);
    g_free (info->uuid);
    g_free (info);
}

GType  bd_btrfs_filesystem_info_get_type () {
        static GType type = 0;

    if (G_UNLIKELY(type == 0)) {
        type = g_boxed_type_register_static("BDBtrfsFilesystemInfo",
                                            (GBoxedCopyFunc) bd_btrfs_filesystem_info_copy,
                                            (GBoxedFreeFunc) bd_btrfs_filesystem_info_free);
    }

    return type;
}

/**
 * BDBtrfsDeviceStats:
 * @id: ID of the device
 * @path: path of the device
 * @write_io_errs: number of write I/O errors
 * @read_io_errs: number of read I/O errors
 * @flush_io_errs: number of flush I/O errors
 * @corruption_errs: number of corruption errors
 * @generation_errs: number of generation errors
 */
/**
 * bd_btrfs_device_stats_copy: (skip)
 * @stats: (nullable): %BDBtrfsDeviceStats to copy
 *
 * Creates a new copy of @stats.
 */
BDBtrfsDeviceStats* bd_btrfs_device_stats_copy (BDBtrfsDeviceStats *stats) {
        if (stats == NULL)
        return NULL;

    BDBtrfsDeviceStats *new_stats = g_new0 (BDBtrfsDeviceStats, 1);

    new_stats->id = stats->id;
    new_stats->path = g_strdup (stats->path);
    new_stats->write_io_errs = stats->write_io_errs;
    new_stats->read_io_errs = stats->read_io_errs;
    new_stats->flush_io_errs = stats->flush_io_errs;
    new_stats->corruption_errs = stats->corruption_errs;
    new_stats->generation_errs = stats->generation_errs;

    return new_stats;
}

/**
 * bd_btrfs_device_stats_free: (skip)
 * @stats: (nullable): %BDBtrfsDeviceStats to free
 *
 * Frees @stats.
 */
void  bd_btrfs_device_stats_free (BDBtrfsDeviceStats *stats) {
        if (stats == NULL)
        return;

    g_free (stats->path);
    g_free (stats);
}

GType  bd_btrfs_device_stats_get_type () {
        static GType type = 0;

    if (G_UNLIKELY(type == 0)) {
        type = g_boxed_type_register_static("BDBtrfsDeviceStats",
                                            (GBoxedCopyFunc) bd_btrfs_device_stats_copy,
                                            (GBoxedFreeFunc) bd_btrfs_device_stats_free);
    }

    return type;
}

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

static gboolean  (*_bd_btrfs_is_tech_avail) (BDBtrfsTech tech, guint64 mode, GError **error) = bd_btrfs_is_tech_avail_stub;

/**
 * bd_btrfs_is_tech_avail:
 * @tech: the queried tech
 * @mode: a bit mask of queried modes of operation (#BDBtrfsTechMode) 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_btrfs_is_tech_avail (BDBtrfsTech tech, guint64 mode, GError **error) {
    return _bd_btrfs_is_tech_avail (tech, mode, error);
}


static gboolean  bd_btrfs_create_volume_stub (const gchar **devices G_GNUC_UNUSED, const gchar *label G_GNUC_UNUSED, const gchar *data_level G_GNUC_UNUSED, const gchar *md_level G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_create_volume' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_create_volume' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_create_volume) (const gchar **devices, const gchar *label, const gchar *data_level, const gchar *md_level, const BDExtraArg **extra, GError **error) = bd_btrfs_create_volume_stub;

/**
 * bd_btrfs_create_volume:
 * @devices: (array zero-terminated=1): list of devices to create btrfs volume from
 * @label: (nullable): label for the volume
 * @data_level: (nullable): RAID level for the data or %NULL to use the default
 * @md_level: (nullable): RAID level for the metadata or %NULL to use the default
 * @extra: (nullable) (array zero-terminated=1): extra options for the volume creation (right now
 *                                                 passed to the 'mkfs.btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the new btrfs volume was created from @devices or not
 *
 * See mkfs.btrfs(8) for details about @data_level, @md_level and btrfs in general.
 *
 * Tech category: %BD_BTRFS_TECH_MULTI_DEV-%BD_BTRFS_TECH_MODE_CREATE
 */
gboolean  bd_btrfs_create_volume (const gchar **devices, const gchar *label, const gchar *data_level, const gchar *md_level, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_create_volume (devices, label, data_level, md_level, extra, error);
}


static gboolean  bd_btrfs_add_device_stub (const gchar *mountpoint G_GNUC_UNUSED, const gchar *device G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_add_device' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_add_device' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_add_device) (const gchar *mountpoint, const gchar *device, const BDExtraArg **extra, GError **error) = bd_btrfs_add_device_stub;

/**
 * bd_btrfs_add_device:
 * @mountpoint: mountpoint of the btrfs volume to add new device to
 * @device: a device to add to the btrfs volume
 * @extra: (nullable) (array zero-terminated=1): extra options for the addition (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @device was successfully added to the @mountpoint btrfs volume or not
 *
 * Tech category: %BD_BTRFS_TECH_MULTI_DEV-%BD_BTRFS_TECH_MODE_MODIFY
 */
gboolean  bd_btrfs_add_device (const gchar *mountpoint, const gchar *device, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_add_device (mountpoint, device, extra, error);
}


static gboolean  bd_btrfs_remove_device_stub (const gchar *mountpoint G_GNUC_UNUSED, const gchar *device G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_remove_device' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_remove_device' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_remove_device) (const gchar *mountpoint, const gchar *device, const BDExtraArg **extra, GError **error) = bd_btrfs_remove_device_stub;

/**
 * bd_btrfs_remove_device:
 * @mountpoint: mountpoint of the btrfs volume to remove device from
 * @device: a device to remove from the btrfs volume
 * @extra: (nullable) (array zero-terminated=1): extra options for the removal (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @device was successfully removed from the @mountpoint btrfs volume or not
 *
 * Tech category: %BD_BTRFS_TECH_MULTI_DEV-%BD_BTRFS_TECH_MODE_MODIFY
 */
gboolean  bd_btrfs_remove_device (const gchar *mountpoint, const gchar *device, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_remove_device (mountpoint, device, extra, error);
}


static gboolean  bd_btrfs_create_subvolume_stub (const gchar *mountpoint G_GNUC_UNUSED, const gchar *name G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_create_subvolume' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_create_subvolume' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_create_subvolume) (const gchar *mountpoint, const gchar *name, const BDExtraArg **extra, GError **error) = bd_btrfs_create_subvolume_stub;

/**
 * bd_btrfs_create_subvolume:
 * @mountpoint: mountpoint of the btrfs volume to create subvolume under
 * @name: name of the subvolume
 * @extra: (nullable) (array zero-terminated=1): extra options for the subvolume creation (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @mountpoint/@name subvolume was successfully created or not
 *
 * Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_CREATE
 */
gboolean  bd_btrfs_create_subvolume (const gchar *mountpoint, const gchar *name, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_create_subvolume (mountpoint, name, extra, error);
}


static gboolean  bd_btrfs_delete_subvolume_stub (const gchar *mountpoint G_GNUC_UNUSED, const gchar *name G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_delete_subvolume' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_delete_subvolume' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_delete_subvolume) (const gchar *mountpoint, const gchar *name, const BDExtraArg **extra, GError **error) = bd_btrfs_delete_subvolume_stub;

/**
 * bd_btrfs_delete_subvolume:
 * @mountpoint: mountpoint of the btrfs volume to delete subvolume from
 * @name: name of the subvolume
 * @extra: (nullable) (array zero-terminated=1): extra options for the subvolume deletion (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @mountpoint/@name subvolume was successfully deleted or not
 *
 * Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_DELETE
 */
gboolean  bd_btrfs_delete_subvolume (const gchar *mountpoint, const gchar *name, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_delete_subvolume (mountpoint, name, extra, error);
}


static gboolean  bd_btrfs_delete_subvolume_recursive_stub (const gchar *mountpoint G_GNUC_UNUSED, const gchar *name G_GNUC_UNUSED, gboolean recursive G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_delete_subvolume_recursive' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_delete_subvolume_recursive' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_delete_subvolume_recursive) (const gchar *mountpoint, const gchar *name, gboolean recursive, const BDExtraArg **extra, GError **error) = bd_btrfs_delete_subvolume_recursive_stub;

/**
 * bd_btrfs_delete_subvolume_recursive:
 * @mountpoint: mountpoint of the btrfs volume to delete subvolume from
 * @name: name of the subvolume
 * @recursive: whether to delete child subvolumes recursively
 * @extra: (nullable) (array zero-terminated=1): extra options for the subvolume deletion (right now
 *                                               passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @mountpoint/@name subvolume was successfully deleted or not
 *
 * If @recursive is %TRUE, all child subvolumes will be deleted before deleting
 * the subvolume itself. This requires btrfs-progs >= 6.12.
 *
 * Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_DELETE if @recursive is %FALSE,
 *                %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_DELETE_RECURSIVE if @recursive is %TRUE
 */
gboolean  bd_btrfs_delete_subvolume_recursive (const gchar *mountpoint, const gchar *name, gboolean recursive, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_delete_subvolume_recursive (mountpoint, name, recursive, extra, error);
}


static guint64  bd_btrfs_get_default_subvolume_id_stub (const gchar *mountpoint G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_get_default_subvolume_id' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_get_default_subvolume_id' called, but not implemented!");
    return 0;
}

static guint64  (*_bd_btrfs_get_default_subvolume_id) (const gchar *mountpoint, GError **error) = bd_btrfs_get_default_subvolume_id_stub;

/**
 * bd_btrfs_get_default_subvolume_id:
 * @mountpoint: mountpoint of the volume to get the default subvolume ID of
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: ID of the @mountpoint volume's default subvolume. If 0,
 *          @error may be set to indicate error
 *
 * Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_QUERY
 */
guint64  bd_btrfs_get_default_subvolume_id (const gchar *mountpoint, GError **error) {
    return _bd_btrfs_get_default_subvolume_id (mountpoint, error);
}


static gboolean  bd_btrfs_set_default_subvolume_stub (const gchar *mountpoint G_GNUC_UNUSED, guint64 subvol_id G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_set_default_subvolume' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_set_default_subvolume' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_set_default_subvolume) (const gchar *mountpoint, guint64 subvol_id, const BDExtraArg **extra, GError **error) = bd_btrfs_set_default_subvolume_stub;

/**
 * bd_btrfs_set_default_subvolume:
 * @mountpoint: mountpoint of the volume to set the default subvolume ID of
 * @subvol_id: ID of the subvolume to be set as the default subvolume
 * @extra: (nullable) (array zero-terminated=1): extra options for the setting (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @mountpoint volume's default subvolume was correctly set
 *          to @subvol_id or not
 *
 * Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_MODIFY
 */
gboolean  bd_btrfs_set_default_subvolume (const gchar *mountpoint, guint64 subvol_id, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_set_default_subvolume (mountpoint, subvol_id, extra, error);
}


static gboolean  bd_btrfs_create_snapshot_stub (const gchar *source G_GNUC_UNUSED, const gchar *dest G_GNUC_UNUSED, gboolean ro G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_create_snapshot' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_create_snapshot' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_create_snapshot) (const gchar *source, const gchar *dest, gboolean ro, const BDExtraArg **extra, GError **error) = bd_btrfs_create_snapshot_stub;

/**
 * bd_btrfs_create_snapshot:
 * @source: path to source subvolume
 * @dest: path to new snapshot volume
 * @ro: whether the snapshot should be read-only
 * @extra: (nullable) (array zero-terminated=1): extra options for the snapshot creation (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @dest snapshot of @source was successfully created or not
 *
 * Tech category: %BD_BTRFS_TECH_SNAPSHOT-%BD_BTRFS_TECH_MODE_CREATE
 */
gboolean  bd_btrfs_create_snapshot (const gchar *source, const gchar *dest, gboolean ro, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_create_snapshot (source, dest, ro, extra, error);
}


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

static BDBtrfsDeviceInfo** (*_bd_btrfs_list_devices) (const gchar *device, GError **error) = bd_btrfs_list_devices_stub;

/**
 * bd_btrfs_list_devices:
 * @device: a device that is part of the queried btrfs volume
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: (array zero-terminated=1): information about the devices that are part of the btrfs volume
 * containing @device or %NULL in case of error
 *
 * Tech category: %BD_BTRFS_TECH_MULTI_DEV-%BD_BTRFS_TECH_MODE_QUERY
 */
BDBtrfsDeviceInfo** bd_btrfs_list_devices (const gchar *device, GError **error) {
    return _bd_btrfs_list_devices (device, error);
}


static BDBtrfsSubvolumeInfo** bd_btrfs_list_subvolumes_stub (const gchar *mountpoint G_GNUC_UNUSED, gboolean snapshots_only G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_list_subvolumes' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_list_subvolumes' called, but not implemented!");
    return NULL;
}

static BDBtrfsSubvolumeInfo** (*_bd_btrfs_list_subvolumes) (const gchar *mountpoint, gboolean snapshots_only, GError **error) = bd_btrfs_list_subvolumes_stub;

/**
 * bd_btrfs_list_subvolumes:
 * @mountpoint: a mountpoint of the queried btrfs volume
 * @snapshots_only: whether to list only snapshot subvolumes or not
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: (array zero-terminated=1): information about the subvolumes that are part of the btrfs volume
 * mounted at @mountpoint or %NULL in case of error
 *
 * The subvolumes are sorted in a way that no child subvolume appears in the
 * list before its parent (sub)volume.
 *
 * Tech category: %BD_BTRFS_TECH_SUBVOL-%BD_BTRFS_TECH_MODE_QUERY
 */
BDBtrfsSubvolumeInfo** bd_btrfs_list_subvolumes (const gchar *mountpoint, gboolean snapshots_only, GError **error) {
    return _bd_btrfs_list_subvolumes (mountpoint, snapshots_only, error);
}


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

static BDBtrfsFilesystemInfo* (*_bd_btrfs_filesystem_info) (const gchar *device, GError **error) = bd_btrfs_filesystem_info_stub;

/**
 * bd_btrfs_filesystem_info:
 * @device: a device that is part of the queried btrfs volume
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: information about the @device's volume's filesystem or %NULL in case of error
 *
 * Tech category: %BD_BTRFS_TECH_FS-%BD_BTRFS_TECH_MODE_QUERY
 */
BDBtrfsFilesystemInfo* bd_btrfs_filesystem_info (const gchar *device, GError **error) {
    return _bd_btrfs_filesystem_info (device, error);
}


static gboolean  bd_btrfs_mkfs_stub (const gchar **devices G_GNUC_UNUSED, const gchar *label G_GNUC_UNUSED, const gchar *data_level G_GNUC_UNUSED, const gchar *md_level G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_mkfs' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_mkfs' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_mkfs) (const gchar **devices, const gchar *label, const gchar *data_level, const gchar *md_level, const BDExtraArg **extra, GError **error) = bd_btrfs_mkfs_stub;

/**
 * bd_btrfs_mkfs:
 * @devices: (array zero-terminated=1): list of devices to create btrfs volume from
 * @label: (nullable): label for the volume
 * @data_level: (nullable): RAID level for the data or %NULL to use the default
 * @md_level: (nullable): RAID level for the metadata or %NULL to use the default
 * @extra: (nullable) (array zero-terminated=1): extra options for the volume creation (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the new btrfs volume was created from @devices or not
 *
 * See mkfs.btrfs(8) for details about @data_level, @md_level and btrfs in general.
 *
 * Tech category: %BD_BTRFS_TECH_FS-%BD_BTRFS_TECH_MODE_CREATE
 */
gboolean  bd_btrfs_mkfs (const gchar **devices, const gchar *label, const gchar *data_level, const gchar *md_level, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_mkfs (devices, label, data_level, md_level, extra, error);
}


static gboolean  bd_btrfs_resize_stub (const gchar *mountpoint G_GNUC_UNUSED, guint64 size G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_resize' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_resize' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_resize) (const gchar *mountpoint, guint64 size, const BDExtraArg **extra, GError **error) = bd_btrfs_resize_stub;

/**
 * bd_btrfs_resize:
 * @mountpoint: a mountpoint of the to be resized btrfs filesystem
 * @size: requested new size
 * @extra: (nullable) (array zero-terminated=1): extra options for the volume resize (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the @mountpoint filesystem was successfully resized to @size
 * or not
 *
 * Tech category: %BD_BTRFS_TECH_FS-%BD_BTRFS_TECH_MODE_MODIFY
 */
gboolean  bd_btrfs_resize (const gchar *mountpoint, guint64 size, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_resize (mountpoint, size, extra, error);
}


static gboolean  bd_btrfs_check_stub (const gchar *device G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_check' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_check' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_check) (const gchar *device, const BDExtraArg **extra, GError **error) = bd_btrfs_check_stub;

/**
 * bd_btrfs_check:
 * @device: a device that is part of the checked btrfs volume
 * @extra: (nullable) (array zero-terminated=1): extra options for the check (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the filesystem was successfully checked or not
 *
 * Tech category: %BD_BTRFS_TECH_FS-%BD_BTRFS_TECH_MODE_QUERY
 */
gboolean  bd_btrfs_check (const gchar *device, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_check (device, extra, error);
}


static gboolean  bd_btrfs_repair_stub (const gchar *device G_GNUC_UNUSED, const BDExtraArg **extra G_GNUC_UNUSED, GError **error) {
    bd_utils_log_format (BD_UTILS_LOG_CRIT, "The function 'bd_btrfs_repair' called, but not implemented!");
    g_set_error (error, BD_INIT_ERROR, BD_INIT_ERROR_NOT_IMPLEMENTED,
                "The function 'bd_btrfs_repair' called, but not implemented!");
    return FALSE;
}

static gboolean  (*_bd_btrfs_repair) (const gchar *device, const BDExtraArg **extra, GError **error) = bd_btrfs_repair_stub;

/**
 * bd_btrfs_repair:
 * @device: a device that is part of the to be repaired btrfs volume
 * @extra: (nullable) (array zero-terminated=1): extra options for the repair (right now
 *                                                 passed to the 'btrfs' utility)
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the filesystem was successfully checked and repaired or not
 *
 * Tech category: %BD_BTRFS_TECH_FS-%BD_BTRFS_TECH_MODE_MODIFY
 */
gboolean  bd_btrfs_repair (const gchar *device, const BDExtraArg **extra, GError **error) {
    return _bd_btrfs_repair (device, extra, error);
}


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

static gboolean  (*_bd_btrfs_change_label) (const gchar *mountpoint, const gchar *label, GError **error) = bd_btrfs_change_label_stub;

/**
 * bd_btrfs_change_label:
 * @mountpoint: a mountpoint of the btrfs filesystem to change label of
 * @label: new label for the filesystem
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: whether the label of the @mountpoint filesystem was successfully set
 * to @label or not
 *
 * Tech category: %BD_BTRFS_TECH_FS-%BD_BTRFS_TECH_MODE_MODIFY
 */
gboolean  bd_btrfs_change_label (const gchar *mountpoint, const gchar *label, GError **error) {
    return _bd_btrfs_change_label (mountpoint, label, error);
}


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

static BDBtrfsDeviceStats** (*_bd_btrfs_device_stats) (const gchar *mountpoint, GError **error) = bd_btrfs_device_stats_stub;

/**
 * bd_btrfs_device_stats:
 * @mountpoint: a mountpoint of the queried btrfs volume
 * @error: (out) (optional): place to store error (if any)
 *
 * Returns: (array zero-terminated=1): device stats for each device that is part of the btrfs volume
 * mounted at @mountpoint or %NULL in case of error
 *
 * Tech category: %BD_BTRFS_TECH_MULTI_DEV-%BD_BTRFS_TECH_MODE_QUERY
 */
BDBtrfsDeviceStats** bd_btrfs_device_stats (const gchar *mountpoint, GError **error) {
    return _bd_btrfs_device_stats (mountpoint, error);
}


static gpointer load_btrfs_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 btrfs: %s", dlerror());
        return NULL;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return handle;
}

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

    _bd_btrfs_is_tech_avail = bd_btrfs_is_tech_avail_stub;
    _bd_btrfs_create_volume = bd_btrfs_create_volume_stub;
    _bd_btrfs_add_device = bd_btrfs_add_device_stub;
    _bd_btrfs_remove_device = bd_btrfs_remove_device_stub;
    _bd_btrfs_create_subvolume = bd_btrfs_create_subvolume_stub;
    _bd_btrfs_delete_subvolume = bd_btrfs_delete_subvolume_stub;
    _bd_btrfs_delete_subvolume_recursive = bd_btrfs_delete_subvolume_recursive_stub;
    _bd_btrfs_get_default_subvolume_id = bd_btrfs_get_default_subvolume_id_stub;
    _bd_btrfs_set_default_subvolume = bd_btrfs_set_default_subvolume_stub;
    _bd_btrfs_create_snapshot = bd_btrfs_create_snapshot_stub;
    _bd_btrfs_list_devices = bd_btrfs_list_devices_stub;
    _bd_btrfs_list_subvolumes = bd_btrfs_list_subvolumes_stub;
    _bd_btrfs_filesystem_info = bd_btrfs_filesystem_info_stub;
    _bd_btrfs_mkfs = bd_btrfs_mkfs_stub;
    _bd_btrfs_resize = bd_btrfs_resize_stub;
    _bd_btrfs_check = bd_btrfs_check_stub;
    _bd_btrfs_repair = bd_btrfs_repair_stub;
    _bd_btrfs_change_label = bd_btrfs_change_label_stub;
    _bd_btrfs_device_stats = bd_btrfs_device_stats_stub;

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

    return dlclose(handle) == 0;
}

