{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
 "version": "2.1.0",
 "runs": [{"tool": {"driver": {"name": "GNU C99",
                               "fullName": "GNU C99 (GCC) version 16.1.1 20260703 (Red Hat 16.1.1-4) (x86_64-redhat-linux)",
                               "version": "16.1.1 20260703 (Red Hat 16.1.1-4)",
                               "informationUri": "https://gcc.gnu.org/gcc-16/",
                               "rules": [{"id": "-Wanalyzer-null-argument",
                                          "helpUri": "https://gcc.gnu.org/onlinedocs/gcc-16.1.0/gcc/Static-Analyzer-Options.html#index-Wanalyzer-null-argument"}]}},
           "taxonomies": [{"name": "CWE",
                           "version": "4.7",
                           "organization": "MITRE",
                           "shortDescription": {"text": "The MITRE Common Weakness Enumeration"},
                           "taxa": [{"id": "476",
                                     "helpUri": "https://cwe.mitre.org/data/definitions/476.html"}]}],
           "invocations": [{"arguments": ["/usr/libexec/gcc/x86_64-redhat-linux/16/cc1",
                                          "-quiet",
                                          "-I",
                                          ".",
                                          "-I",
                                          "./../../include/",
                                          "-I",
                                          "/usr/include/glib-2.0",
                                          "-I",
                                          "/usr/lib64/glib-2.0/include",
                                          "-I",
                                          "/usr/include/sysprof-6",
                                          "-I",
                                          "/usr/include/glib-2.0",
                                          "-I",
                                          "/usr/lib64/glib-2.0/include",
                                          "-I",
                                          "/usr/include/libmount",
                                          "-I",
                                          "/usr/include/blkid",
                                          "-I",
                                          "/usr/include/sysprof-6",
                                          "-I",
                                          "/usr/include/uuid",
                                          "-I",
                                          "/usr/include/json-c",
                                          "-I",
                                          "/usr/include/blkid",
                                          "-I",
                                          "/usr/include/blkid",
                                          "-I",
                                          "/usr/include/nss3",
                                          "-I",
                                          "/usr/include/nspr4",
                                          "-D",
                                          "PACKAGE_NAME=\"libblockdev\"",
                                          "-D",
                                          "PACKAGE_TARNAME=\"libblockdev\"",
                                          "-D",
                                          "PACKAGE_VERSION=\"3.4.0\"",
                                          "-D",
                                          "PACKAGE_STRING=\"libblockdev 3.4.0\"",
                                          "-D",
                                          "PACKAGE_BUGREPORT=\"\"",
                                          "-D",
                                          "PACKAGE_URL=\"https://github.com/storaged-project/libblockdev\"",
                                          "-D",
                                          "PACKAGE=\"libblockdev\"",
                                          "-D",
                                          "VERSION=\"3.4.0\"",
                                          "-D",
                                          "NDEBUG=1",
                                          "-D",
                                          "HAVE_STDIO_H=1",
                                          "-D",
                                          "HAVE_STDLIB_H=1",
                                          "-D",
                                          "HAVE_STRING_H=1",
                                          "-D",
                                          "HAVE_INTTYPES_H=1",
                                          "-D",
                                          "HAVE_STDINT_H=1",
                                          "-D",
                                          "HAVE_STRINGS_H=1",
                                          "-D",
                                          "HAVE_SYS_STAT_H=1",
                                          "-D",
                                          "HAVE_SYS_TYPES_H=1",
                                          "-D",
                                          "HAVE_UNISTD_H=1",
                                          "-D",
                                          "STDC_HEADERS=1",
                                          "-D",
                                          "HAVE_DLFCN_H=1",
                                          "-D",
                                          "LT_OBJDIR=\".libs/\"",
                                          "-D",
                                          "HAVE_DLFCN_H=1",
                                          "-D",
                                          "HAVE_STRING_H=1",
                                          "-D",
                                          "HAVE_UNISTD_H=1",
                                          "-D",
                                          "HAVE_SYS_FCNTL_H=1",
                                          "-D",
                                          "HAVE_SYS_IOCTL_H=1",
                                          "-D",
                                          "HAVE_LINUX_RANDOM_H=1",
                                          "-D",
                                          "HAVE_GLOB_H=1",
                                          "-D",
                                          "HAVE_SYSLOG_H=1",
                                          "-D",
                                          "HAVE_MATH_H=1",
                                          "-D",
                                          "WITH_BD_ESCROW=/**/",
                                          "-D",
                                          "WITH_BD_NVME=/**/",
                                          "-D",
                                          "WITH_BD_BTRFS=/**/",
                                          "-D",
                                          "WITH_BD_CRYPTO=/**/",
                                          "-D",
                                          "WITH_BD_DM=/**/",
                                          "-D",
                                          "WITH_BD_LOOP=/**/",
                                          "-D",
                                          "WITH_BD_LVM=/**/",
                                          "-D",
                                          "WITH_BD_LVM_DBUS=/**/",
                                          "-D",
                                          "WITH_BD_MDRAID=/**/",
                                          "-D",
                                          "WITH_BD_MPATH=/**/",
                                          "-D",
                                          "WITH_BD_SWAP=/**/",
                                          "-D",
                                          "WITH_BD_PART=/**/",
                                          "-D",
                                          "WITH_BD_FS=/**/",
                                          "-D",
                                          "WITH_BD_NVDIMM=/**/",
                                          "-D",
                                          "WITH_BD_NVME=/**/",
                                          "-D",
                                          "WITH_BD_SMART=/**/",
                                          "-D",
                                          "LIBCRYPTSETUP_24=1",
                                          "-D",
                                          "LIBCRYPTSETUP_26=1",
                                          "-D",
                                          "LIBCRYPTSETUP_27=1",
                                          "-D",
                                          "LIBCRYPTSETUP_28=1",
                                          "-D",
                                          "HAVE_LINUX_OPAL=1",
                                          "-D",
                                          "LIBMOUNT_NEW_ERR_API=1",
                                          "-D",
                                          "LIBNDCTL_NEW_MODES=1",
                                          "-D",
                                          "HAVE_LIBNVME_1_4=1",
                                          "-D",
                                          "HAVE_SMART=1",
                                          "-D",
                                          "HAVE_SMARTMONTOOLS=1",
                                          "-D",
                                          "WITH_GZFILEOP",
                                          "-D",
                                          "PIC",
                                          "crypto.c",
                                          "-quiet",
                                          "-dumpbase",
                                          "crypto.c",
                                          "-dumpbase-ext",
                                          ".c",
                                          "-m64",
                                          "-mtune=generic",
                                          "-march=x86-64",
                                          "-mtls-dialect=gnu2",
                                          "-O2",
                                          "-Wno-unknown-pragmas",
                                          "-std=gnu99",
                                          "-flto=auto",
                                          "-ffat-lto-objects",
                                          "-fexceptions",
                                          "-fstack-protector-strong",
                                          "-fasynchronous-unwind-tables",
                                          "-fstack-clash-protection",
                                          "-fcf-protection=full",
                                          "-fno-omit-frame-pointer",
                                          "-fPIC",
                                          "-fanalyzer",
                                          "-fdiagnostics-path-format=separate-events",
                                          "-fno-diagnostics-show-caret",
                                          "-fno-lto",
                                          "-fanalyzer-assume-nothrow",
                                          "-fdiagnostics-text-art-charset=none",
                                          "-fdiagnostics-set-output=sarif:file=/builddir/gcc-results/3784-ovuA.sarif",
                                          "-o",
                                          "/tmp/ccEpmujQ.s"],
                            "workingDirectory": {"uri": "/builddir/build/BUILD/libblockdev-3.4.0-build/libblockdev-3.4.0/src/plugins"},
                            "startTimeUtc": "2026-08-03T16:58:14Z",
                            "executionSuccessful": true,
                            "toolExecutionNotifications": [],
                            "endTimeUtc": "2026-08-03T16:58:17Z"}],
           "originalUriBaseIds": {"PWD": {"uri": "file:///builddir/build/BUILD/libblockdev-3.4.0-build/libblockdev-3.4.0/src/plugins/"}},
           "artifacts": [{"location": {"uri": "crypto.c",
                                       "uriBaseId": "PWD"},
                          "sourceLanguage": "c",
                          "contents": {"text": "/*\n * Copyright (C) 2014  Red Hat, Inc.\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Vratislav Podzimek <vpodzime@redhat.com>\n */\n\n#include <string.h>\n#include <glib.h>\n#include <libcryptsetup.h>\n#include <fcntl.h>\n#include <sys/ioctl.h>\n#include <linux/random.h>\n#include <locale.h>\n#include <unistd.h>\n#include <errno.h>\n#include <blkid.h>\n#include <sys/types.h>\n#include <keyutils.h>\n#include <blockdev/utils.h>\n\n#ifdef WITH_BD_ESCROW\n#include <nss.h>\n#include <volume_key/libvolume_key.h>\n#endif\n\n#ifdef HAVE_LINUX_OPAL\n#include <linux/sed-opal.h>\n#endif\n\n#include \"crypto.h\"\n\n#ifdef __clang__\n#define ZERO_INIT {}\n#else\n#define ZERO_INIT {0}\n#endif\n\n#define SECTOR_SIZE 512\n\n#define DEFAULT_LUKS_KEYSIZE_BITS 256\n#define DEFAULT_LUKS_CIPHER \"aes-xts-plain64\"\n\n#define DEFAULT_OPAL_KEYSIZE_BITS 256\n\n#define SQUARE_LOWER_LIMIT 136\n#define SQUARE_UPPER_LIMIT 426\n#define SQUARE_BYTES_TO_CHECK 512\n\n#ifdef LIBCRYPTSETUP_24\n/* 0 for autodetect since 2.4.0 */\n#define DEFAULT_LUKS2_SECTOR_SIZE 0\n#else\n#define DEFAULT_LUKS2_SECTOR_SIZE 512\n#endif\n\n\n/**\n * SECTION: crypto\n * @short_description: plugin for operations with encrypted devices\n * @title: Crypto\n * @include: crypto.h\n *\n * A plugin for operations with encrypted devices. Currently LUKS, Integrity,\n * TrueCrypt/VeraCrypt, BitLocker and FileVault2 devices are supported.\n * See %BDCryptoTech for full list of supported technologies.\n *\n * Functions taking a parameter called \"device\" require the backing device to be\n * passed. On the other hand functions taking the \"luks_device\" parameter\n * require the LUKS device (/dev/mapper/SOMETHING\").\n *\n * Sizes are given in bytes unless stated otherwise.\n */\n\nBDCryptoLUKSPBKDF* bd_crypto_luks_pbkdf_copy (BDCryptoLUKSPBKDF *pbkdf) {\n    if (pbkdf == NULL)\n        return NULL;\n\n    BDCryptoLUKSPBKDF *new_pbkdf = g_new0 (BDCryptoLUKSPBKDF, 1);\n    new_pbkdf->type = g_strdup (pbkdf->type);\n    new_pbkdf->hash = g_strdup (pbkdf->hash);\n    new_pbkdf->max_memory_kb = pbkdf->max_memory_kb;\n    new_pbkdf->iterations = pbkdf->iterations;\n    new_pbkdf->time_ms = pbkdf->time_ms;\n    new_pbkdf->parallel_threads = pbkdf->parallel_threads;\n\n    return new_pbkdf;\n}\n\nvoid bd_crypto_luks_pbkdf_free (BDCryptoLUKSPBKDF *pbkdf) {\n    if (pbkdf == NULL)\n        return;\n\n    g_free (pbkdf->type);\n    g_free (pbkdf->hash);\n    g_free (pbkdf);\n}\n\nBDCryptoLUKSPBKDF* bd_crypto_luks_pbkdf_new (const gchar *type, const gchar *hash, guint32 max_memory_kb, guint32 iterations, guint32 time_ms, guint32 parallel_threads) {\n    BDCryptoLUKSPBKDF *ret = g_new0 (BDCryptoLUKSPBKDF, 1);\n    ret->type = g_strdup (type);\n    ret->hash = g_strdup (hash);\n    ret->max_memory_kb = max_memory_kb;\n    ret->iterations = iterations;\n    ret->time_ms = time_ms;\n    ret->parallel_threads = parallel_threads;\n\n    return ret;\n}\n\nBDCryptoLUKSExtra* bd_crypto_luks_extra_copy (BDCryptoLUKSExtra *extra) {\n    if (extra == NULL)\n        return NULL;\n\n    BDCryptoLUKSExtra *new_extra = g_new0 (BDCryptoLUKSExtra, 1);\n\n    new_extra->integrity = g_strdup (extra->integrity);\n    new_extra->data_alignment = extra->data_alignment;\n    new_extra->data_device = g_strdup (extra->data_device);\n    new_extra->sector_size = extra->sector_size;\n    new_extra->label = g_strdup (extra->label);\n    new_extra->subsystem = g_strdup (extra->subsystem);\n    new_extra->pbkdf = bd_crypto_luks_pbkdf_copy (extra->pbkdf);\n\n    return new_extra;\n}\n\nvoid bd_crypto_luks_extra_free (BDCryptoLUKSExtra *extra) {\n    if (extra == NULL)\n        return;\n\n    g_free (extra->integrity);\n    g_free (extra->data_device);\n    g_free (extra->label);\n    g_free (extra->subsystem);\n    bd_crypto_luks_pbkdf_free (extra->pbkdf);\n    g_free (extra);\n}\n\nBDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar *data_device, const gchar *integrity, guint32 sector_size, const gchar *label, const gchar *subsystem, BDCryptoLUKSPBKDF *pbkdf) {\n    BDCryptoLUKSExtra *ret = g_new0 (BDCryptoLUKSExtra, 1);\n    ret->integrity = g_strdup (integrity);\n    ret->data_alignment = data_alignment;\n    ret->data_device = g_strdup (data_device);\n    ret->sector_size = sector_size;\n    ret->label = g_strdup (label);\n    ret->subsystem = g_strdup (subsystem);\n    ret->pbkdf = bd_crypto_luks_pbkdf_copy (pbkdf);\n\n    return ret;\n}\n\nBDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint32 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) {\n    BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1);\n    ret->sector_size = sector_size;\n    ret->journal_size = journal_size;\n    ret->journal_watermark = journal_watermark;\n    ret->journal_commit_time = journal_commit_time;\n    ret->interleave_sectors = interleave_sectors;\n    ret->tag_size = tag_size;\n    ret->buffer_sectors = buffer_sectors;\n\n    return ret;\n}\n\nBDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) {\n    if (extra == NULL)\n        return NULL;\n\n    BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1);\n\n    new_extra->sector_size = extra->sector_size;\n    new_extra->journal_size = extra->journal_size;\n    new_extra->journal_watermark = extra->journal_watermark;\n    new_extra->journal_commit_time = extra->journal_commit_time;\n    new_extra->interleave_sectors = extra->interleave_sectors;\n    new_extra->tag_size = extra->tag_size;\n    new_extra->buffer_sectors = extra->buffer_sectors;\n\n    return new_extra;\n}\n\nvoid bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) {\n    if (extra == NULL)\n        return;\n\n    g_free (extra);\n}\n\nvoid bd_crypto_luks_info_free (BDCryptoLUKSInfo *info) {\n    if (info == NULL)\n        return;\n\n    g_free (info->cipher);\n    g_free (info->mode);\n    g_free (info->uuid);\n    g_free (info->backing_device);\n    g_free (info->label);\n    g_free (info->subsystem);\n    g_free (info);\n}\n\nBDCryptoLUKSInfo* bd_crypto_luks_info_copy (BDCryptoLUKSInfo *info) {\n    if (info == NULL)\n        return NULL;\n\n    BDCryptoLUKSInfo *new_info = g_new0 (BDCryptoLUKSInfo, 1);\n\n    new_info->version = info->version;\n    new_info->cipher = g_strdup (info->cipher);\n    new_info->mode = g_strdup (info->mode);\n    new_info->uuid = g_strdup (info->uuid);\n    new_info->backing_device = g_strdup (info->backing_device);\n    new_info->sector_size = info->sector_size;\n    new_info->metadata_size = info->metadata_size;\n    new_info->label = g_strdup (info->label);\n    new_info->subsystem = g_strdup (info->subsystem);\n    new_info->hw_encryption = info->hw_encryption;\n\n    return new_info;\n}\n\nvoid bd_crypto_bitlk_info_free (BDCryptoBITLKInfo *info) {\n    if (info == NULL)\n        return;\n\n    g_free (info->cipher);\n    g_free (info->mode);\n    g_free (info->uuid);\n    g_free (info->backing_device);\n    g_free (info);\n}\n\nBDCryptoBITLKInfo* bd_crypto_bitlk_info_copy (BDCryptoBITLKInfo *info) {\n    if (info == NULL)\n        return NULL;\n\n    BDCryptoBITLKInfo *new_info = g_new0 (BDCryptoBITLKInfo, 1);\n\n    new_info->cipher = g_strdup (info->cipher);\n    new_info->mode = g_strdup (info->mode);\n    new_info->uuid = g_strdup (info->uuid);\n    new_info->backing_device = g_strdup (info->backing_device);\n    new_info->sector_size = info->sector_size;\n\n    return new_info;\n}\n\nvoid bd_crypto_integrity_info_free (BDCryptoIntegrityInfo *info) {\n    if (info == NULL)\n        return;\n\n    g_free (info->algorithm);\n    g_free (info->journal_crypt);\n    g_free (info->journal_integrity);\n    g_free (info);\n}\n\nBDCryptoIntegrityInfo* bd_crypto_integrity_info_copy (BDCryptoIntegrityInfo *info) {\n    if (info == NULL)\n        return NULL;\n\n    BDCryptoIntegrityInfo *new_info = g_new0 (BDCryptoIntegrityInfo, 1);\n\n    new_info->algorithm = g_strdup (info->algorithm);\n    new_info->key_size = info->key_size;\n    new_info->sector_size = info->sector_size;\n    new_info->tag_size = info->tag_size;\n    new_info->interleave_sectors = info->interleave_sectors;\n    new_info->journal_size = info->journal_size;\n    new_info->journal_crypt = g_strdup (info->journal_crypt);\n    new_info->journal_integrity = g_strdup (info->journal_integrity);\n\n    return new_info;\n}\n\nvoid bd_crypto_luks_token_info_free (BDCryptoLUKSTokenInfo *info) {\n    if (info == NULL)\n        return;\n\n    g_free (info->type);\n    g_free (info);\n}\n\nBDCryptoLUKSTokenInfo* bd_crypto_luks_token_info_copy (BDCryptoLUKSTokenInfo *info) {\n    if (info == NULL)\n        return NULL;\n\n    BDCryptoLUKSTokenInfo *new_info = g_new0 (BDCryptoLUKSTokenInfo, 1);\n\n    new_info->id = info->id;\n    new_info->type = g_strdup (info->type);\n    new_info->keyslot = info->keyslot;\n\n    return new_info;\n}\n\n/* \"C\" locale to get the locale-agnostic error messages */\nstatic locale_t c_locale = (locale_t) 0;\n\nstatic void crypto_log_redirect (gint level, const gchar *msg, void *usrptr G_GNUC_UNUSED) {\n    gchar *message = NULL;\n\n    switch (level) {\n        case CRYPT_LOG_DEBUG:\n        case CRYPT_LOG_VERBOSE:\n            message = g_strdup_printf (\"[cryptsetup] %s\", msg);\n            bd_utils_log (BD_UTILS_LOG_DEBUG, message);\n            g_free (message);\n            break;\n        case CRYPT_LOG_NORMAL:\n        case CRYPT_LOG_ERROR:\n            message = g_strdup_printf (\"[cryptsetup] %s\", msg);\n            bd_utils_log (BD_UTILS_LOG_INFO, message);\n            g_free (message);\n            break;\n        default:\n            bd_utils_log_format (BD_UTILS_LOG_WARNING, \"Unknown cryptsetup log level %d.\", level);\n            message = g_strdup_printf (\"[cryptsetup] %s\", msg);\n            bd_utils_log (BD_UTILS_LOG_INFO, message);\n            g_free (message);\n            break;\n\n    }\n}\n\n/**\n * bd_crypto_init:\n *\n * Initializes the plugin. **This function is called automatically by the\n * library's initialization functions.**\n *\n */\ngboolean bd_crypto_init (void) {\n#ifdef DEBUG\n    crypt_set_debug_level (CRYPT_DEBUG_ALL);\n#endif\n    c_locale = newlocale (LC_ALL_MASK, \"C\", c_locale);\n    crypt_set_log_callback (NULL, &crypto_log_redirect, NULL);\n    return TRUE;\n}\n\n/**\n * bd_crypto_close:\n *\n * Cleans up after the plugin. **This function is called automatically by the\n * library's functions that unload it.**\n *\n */\nvoid bd_crypto_close (void) {\n    c_locale = (locale_t) 0;\n    crypt_set_log_callback (NULL, NULL, NULL);\n    crypt_set_debug_level (CRYPT_DEBUG_NONE);\n}\n\n/**\n * bd_crypto_is_tech_avail:\n * @tech: the queried tech\n * @mode: a bit mask of queried modes of operation (#BDCryptoTechMode) for @tech\n * @error: (out) (optional): place to store error (details about why the @tech-@mode combination is not available)\n *\n * Returns: whether the @tech-@mode combination is available -- supported by the\n *          plugin implementation and having all the runtime dependencies available\n */\ngboolean bd_crypto_is_tech_avail (BDCryptoTech tech, guint64 mode, GError **error) {\n    guint64 ret = 0;\n    switch (tech) {\n        case BD_CRYPTO_TECH_LUKS:\n            ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY|\n                          BD_CRYPTO_TECH_MODE_ADD_KEY|BD_CRYPTO_TECH_MODE_REMOVE_KEY|BD_CRYPTO_TECH_MODE_RESIZE|\n                          BD_CRYPTO_TECH_MODE_SUSPEND_RESUME|BD_CRYPTO_TECH_MODE_BACKUP_RESTORE);\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'create', 'open', 'query', 'add-key', 'remove-key', 'resize', 'suspend-resume', 'backup-restore' supported for LUKS\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_TRUECRYPT:\n            ret = mode & BD_CRYPTO_TECH_MODE_OPEN_CLOSE;\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'open' supported for TrueCrypt\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_ESCROW:\n#ifndef WITH_BD_ESCROW\n            g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                         \"Escrow technology is not available, libblockdev has been compiled without escrow support.\");\n            return FALSE;\n#endif\n            ret = mode & BD_CRYPTO_TECH_MODE_CREATE;\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'create' supported for device escrow\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_INTEGRITY:\n            ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY);\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'create', 'open' and 'query' supported for Integrity\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_BITLK:\n            ret = mode & (BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY);\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'open' and 'query' supported for BITLK\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_KEYRING:\n            ret = mode & BD_CRYPTO_TECH_MODE_ADD_KEY;\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'add key' supported for kernel keyring\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_FVAULT2:\n#ifndef LIBCRYPTSETUP_26\n            g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                         \"FVAULT2 technology requires libcryptsetup >= 2.6.0\");\n            return FALSE;\n#endif\n            ret = mode & BD_CRYPTO_TECH_MODE_OPEN_CLOSE;\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'open' supported for FVAULT2\");\n                return FALSE;\n            } else\n                return TRUE;\n        case BD_CRYPTO_TECH_SED_OPAL:\n#if !defined(LIBCRYPTSETUP_27) || !defined(HAVE_LINUX_OPAL)\n            g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                         \"OPAL technology requires libcryptsetup >= 2.7.0 and kernel with SED OPAL support\");\n            return FALSE;\n#endif\n            ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_QUERY|BD_CRYPTO_TECH_MODE_MODIFY);\n            if (ret != mode) {\n                g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                             \"Only 'create', 'query' and 'modify' supported for OPAL\");\n                return FALSE;\n            } else\n                return TRUE;\n        default:\n            g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, \"Unknown technology\");\n            return FALSE;\n    }\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_error_quark: (skip)\n */\nGQuark bd_crypto_error_quark (void)\n{\n    return g_quark_from_static_string (\"g-bd-crypto-error-quark\");\n}\n\n/**\n * bd_crypto_generate_backup_passphrase:\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: (transfer full): A newly generated %BD_CRYPTO_BACKUP_PASSPHRASE_LENGTH-long passphrase.\n *\n * See %BD_CRYPTO_BACKUP_PASSPHRASE_CHARSET for the definition of the charset used for the passphrase.\n *\n * Tech category: always available\n */\ngchar* bd_crypto_generate_backup_passphrase (GError **error G_GNUC_UNUSED) {\n    guint8 i = 0;\n    guint8 offset = 0;\n    guint8 charset_length = strlen (BD_CRYPTO_BACKUP_PASSPHRASE_CHARSET);\n\n    /* passphrase with groups of 5 characters separated with dashes, plus a null terminator */\n    gchar *ret = g_new0 (gchar, BD_CRYPTO_BACKUP_PASSPHRASE_LENGTH + (BD_CRYPTO_BACKUP_PASSPHRASE_LENGTH / 5));\n\n    for (i=0; i < BD_CRYPTO_BACKUP_PASSPHRASE_LENGTH; i++) {\n        if (i > 0 && (i % 5 == 0)) {\n            /* put a dash between every 5 characters */\n            ret[i+offset] = '-';\n            offset++;\n        }\n        ret[i+offset] = BD_CRYPTO_BACKUP_PASSPHRASE_CHARSET[g_random_int_range (0, charset_length)];\n    }\n\n    return ret;\n}\n\n/**\n * bd_crypto_device_is_luks:\n * @device: the queried device\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: %TRUE if the given @device is a LUKS device or %FALSE if not or\n * failed to determine (the @error) is populated with the error in such\n * cases)\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_QUERY\n */\ngboolean bd_crypto_device_is_luks (const gchar *device, GError **error) {\n    blkid_probe probe = NULL;\n    gint fd = 0;\n    gint status = 0;\n    const gchar *value = NULL;\n    guint n_try = 0;\n\n    probe = blkid_new_probe ();\n    if (!probe) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to create a new probe\");\n        return FALSE;\n    }\n\n    fd = open (device, O_RDONLY|O_CLOEXEC);\n    if (fd == -1) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to open the device '%s'\", device);\n        blkid_free_probe (probe);\n        return FALSE;\n    }\n\n    /* we may need to try multiple times with some delays in case the device is\n       busy at the very moment */\n    for (n_try=5, status=-1; (status != 0) && (n_try > 0); n_try--) {\n        status = blkid_probe_set_device (probe, fd, 0, 0);\n        if (status != 0)\n            g_usleep (100 * 1000); /* microseconds */\n    }\n    if (status != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to create a probe for the device '%s'\", device);\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    }\n\n    blkid_probe_enable_partitions (probe, 1);\n    blkid_probe_set_partitions_flags (probe, BLKID_PARTS_MAGIC);\n    blkid_probe_enable_superblocks (probe, 1);\n    blkid_probe_set_superblocks_flags (probe, BLKID_SUBLKS_USAGE | BLKID_SUBLKS_TYPE |\n                                              BLKID_SUBLKS_MAGIC | BLKID_SUBLKS_BADCSUM);\n\n    /* we may need to try multiple times with some delays in case the device is\n       busy at the very moment */\n    for (n_try=5, status=-1; !(status == 0 || status == 1) && (n_try > 0); n_try--) {\n        status = blkid_do_safeprobe (probe);\n        if (status < 0)\n            g_usleep (100 * 1000); /* microseconds */\n    }\n    if (status < 0) {\n        /* -1 or -2 = error during probing*/\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to probe the device '%s'\", device);\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    } else if (status == 1) {\n        /* 1 = nothing detected */\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    }\n\n    status = blkid_probe_lookup_value (probe, \"USAGE\", &value, NULL);\n    if (status != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to get usage for the device '%s'\", device);\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    }\n\n    if (g_strcmp0 (value, \"crypto\") != 0) {\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    }\n\n    status = blkid_probe_lookup_value (probe, \"TYPE\", &value, NULL);\n    if (status != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to get filesystem type for the device '%s'\", device);\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    }\n\n    if (g_strcmp0 (value, \"crypto_LUKS\") != 0) {\n        blkid_free_probe (probe);\n        close (fd);\n        return FALSE;\n    }\n\n    blkid_free_probe (probe);\n    close (fd);\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_status:\n * @luks_device: the queried LUKS device\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: (transfer none): one of \"invalid\", \"inactive\", \"active\" or \"busy\" or\n * %NULL if failed to determine (@error is populated with the error in\n * such cases)\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_QUERY\n */\nconst gchar* bd_crypto_luks_status (const gchar *luks_device, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret_num;\n    const gchar *ret = NULL;\n    crypt_status_info status;\n\n    ret_num = crypt_init_by_name (&cd, luks_device);\n    if (ret_num != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret_num, c_locale));\n        return NULL;\n    }\n\n    status = crypt_status (cd, luks_device);\n    switch (status) {\n    case CRYPT_INVALID:\n        ret = \"invalid\";\n        break;\n    case CRYPT_INACTIVE:\n        ret = \"inactive\";\n        break;\n    case CRYPT_ACTIVE:\n        ret = \"active\";\n        break;\n    case CRYPT_BUSY:\n        ret = \"busy\";\n        break;\n    default:\n        ret = NULL;\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_STATE,\n                     \"Unknown device's state\");\n    }\n\n    crypt_free (cd);\n    return ret;\n}\n\nstatic struct crypt_pbkdf_type *get_pbkdf_params (BDCryptoLUKSPBKDF *user_pbkdf, GError **error) {\n    const struct crypt_pbkdf_type *default_pbkdf = NULL;\n    struct crypt_pbkdf_type *new_pbkdf = NULL;\n\n    if (user_pbkdf == NULL)\n        return NULL;\n\n    /* crypt_get_pbkdf_default returns default pbkdf parameters only based\n       on the luks version -- so for LUKS2 it returns default values for\n       argon2 but we also need to be able to provide default values if user\n       wants pbkdf2 and only specifies type -- we will use the defaults for\n       argon2 and ignore parameters specific to it\n       better API for this should be part of cryptsetup 2.0.4\n     */\n    default_pbkdf = crypt_get_pbkdf_default (CRYPT_LUKS2);\n    if (!default_pbkdf) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                     \"Failed to get default values for pbkdf.\");\n        return NULL;\n    }\n\n    new_pbkdf = g_new0 (struct crypt_pbkdf_type, 1);\n\n    new_pbkdf->flags = default_pbkdf->flags;\n\n    if (user_pbkdf->type)\n        new_pbkdf->type = user_pbkdf->type;\n    else\n        new_pbkdf->type = default_pbkdf->type;\n\n    if (user_pbkdf->hash)\n        new_pbkdf->hash = user_pbkdf->hash;\n    else\n        new_pbkdf->hash = default_pbkdf->hash;\n\n    if (user_pbkdf->time_ms)\n        new_pbkdf->time_ms = user_pbkdf->time_ms;\n    else\n        new_pbkdf->time_ms = default_pbkdf->time_ms;\n\n    if (user_pbkdf->iterations) {\n        new_pbkdf->iterations = user_pbkdf->iterations;\n        /* iterations set manually -> do not run benchmark */\n        new_pbkdf->flags = CRYPT_PBKDF_NO_BENCHMARK;\n    } else\n        new_pbkdf->iterations = default_pbkdf->iterations;\n\n    /* 'max_memory_kb' and 'parallel_threads' are not used in pbkdf2 */\n    if (g_strcmp0 (user_pbkdf->type, CRYPT_KDF_PBKDF2) == 0) {\n        if (user_pbkdf->max_memory_kb)\n            bd_utils_log_format (LOG_WARNING, \"'max_memory_kb' is not valid option for 'pbkdf2', ignoring.\");\n\n        new_pbkdf->max_memory_kb = 0;\n        new_pbkdf->parallel_threads = 0;\n    } else {\n        if (user_pbkdf->max_memory_kb)\n            new_pbkdf->max_memory_kb = user_pbkdf->max_memory_kb;\n        else\n            new_pbkdf->max_memory_kb = default_pbkdf->max_memory_kb;\n\n        if (user_pbkdf->parallel_threads)\n            new_pbkdf->parallel_threads = user_pbkdf->parallel_threads;\n        else\n            new_pbkdf->parallel_threads = default_pbkdf->parallel_threads;\n    }\n\n    return new_pbkdf;\n}\n\ntypedef enum {\n    BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_NONE = 0,\n    BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE,\n    BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE,\n    BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYRING,\n    BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_VOLUME_KEY,\n} BDCryptoKeyslotContextType;\n\nstruct _BDCryptoKeyslotContext {\n    BDCryptoKeyslotContextType type;\n\n    union {\n        struct {\n            guint8 *pass_data;\n            gsize data_len;\n        } passphrase;\n\n        struct {\n            gchar *keyfile;\n            guint64 keyfile_offset;\n            gsize key_size;\n        } keyfile;\n\n        struct {\n            gchar *key_desc;\n        } keyring;\n\n        struct {\n            guint8 *volume_key;\n            gsize volume_key_size;\n        } volume_key;\n    } u;\n};\n\nvoid bd_crypto_keyslot_context_free (BDCryptoKeyslotContext *context) {\n    if (context == NULL)\n        return;\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE)\n        g_free (context->u.passphrase.pass_data);\n    else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n        g_free (context->u.keyfile.keyfile);\n    else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYRING)\n        g_free (context->u.keyring.key_desc);\n    else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_VOLUME_KEY)\n        g_free (context->u.volume_key.volume_key);\n\n    g_free (context);\n}\n\nBDCryptoKeyslotContext* bd_crypto_keyslot_context_copy (BDCryptoKeyslotContext *context) {\n    if (context == NULL)\n        return NULL;\n\n    BDCryptoKeyslotContext *new_context = g_new0 (BDCryptoKeyslotContext, 1);\n    new_context->type = context->type;\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        new_context->u.passphrase.pass_data = g_new0 (guint8, context->u.passphrase.data_len);\n        memcpy (new_context->u.passphrase.pass_data, context->u.passphrase.pass_data, context->u.passphrase.data_len);\n        new_context->u.passphrase.data_len = context->u.passphrase.data_len;\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        new_context->u.keyfile.keyfile = g_strdup (context->u.keyfile.keyfile);\n        new_context->u.keyfile.keyfile_offset = context->u.keyfile.keyfile_offset;\n        new_context->u.keyfile.key_size = context->u.keyfile.key_size;\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYRING)\n        new_context->u.keyring.key_desc = g_strdup (context->u.keyring.key_desc);\n    else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_VOLUME_KEY) {\n        new_context->u.volume_key.volume_key = g_new0 (guint8, context->u.volume_key.volume_key_size);\n        memcpy (new_context->u.volume_key.volume_key, context->u.volume_key.volume_key, context->u.volume_key.volume_key_size);\n        new_context->u.volume_key.volume_key_size = context->u.volume_key.volume_key_size;\n    }\n\n    return new_context;\n}\n\n/**\n * bd_crypto_keyslot_context_new_passphrase:\n * @pass_data: (array length=data_len): a passphrase for the new context (may contain arbitrary binary data)\n * @data_len: length of the @pass_data buffer\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): new %BDCryptoKeyslotContext initialized by passphrase or\n *                          %NULL in case of error\n *\n * Tech category: always available\n */\nBDCryptoKeyslotContext* bd_crypto_keyslot_context_new_passphrase (const guint8 *pass_data, gsize data_len, GError **error) {\n    BDCryptoKeyslotContext *context = NULL;\n\n    if (!pass_data || data_len == 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_NO_KEY,\n                     \"No passphrase specified.\");\n        return NULL;\n    }\n\n    context = g_new0 (BDCryptoKeyslotContext, 1);\n\n    context->type = BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE;\n\n    context->u.passphrase.pass_data = g_new0 (guint8, data_len);\n    memcpy (context->u.passphrase.pass_data, pass_data, data_len);\n\n    context->u.passphrase.data_len = data_len;\n\n    return context;\n}\n\n/**\n * bd_crypto_keyslot_context_new_keyfile:\n * @keyfile: a key file for the new context\n * @keyfile_offset: number of bytes to skip at start of @keyfile\n * @key_size: number of bytes to read from @keyfile or 0 for unlimited\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): new %BDCryptoKeyslotContext initialized by key file or\n *                          %NULL in case of error\n *\n * Tech category: always available\n */\nBDCryptoKeyslotContext* bd_crypto_keyslot_context_new_keyfile (const gchar *keyfile, guint64 keyfile_offset, gsize key_size, GError **error G_GNUC_UNUSED) {\n    BDCryptoKeyslotContext *context = NULL;\n\n    context = g_new0 (BDCryptoKeyslotContext, 1);\n\n    context->type = BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE;\n\n    context->u.keyfile.keyfile = g_strdup (keyfile);\n    context->u.keyfile.keyfile_offset = keyfile_offset;\n    context->u.keyfile.key_size = key_size;\n\n    return context;\n}\n\n/**\n * bd_crypto_keyslot_context_new_keyring:\n * @key_desc: kernel keyring key description\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): new %BDCryptoKeyslotContext initialized by @key_desc or\n *                          %NULL in case of error\n *\n * Note: Keyslot passphrase must be stored in 'user' key type and the key has to be reachable\n *       by process context on behalf of which this function is called.\n *\n * Tech category: always available\n */\nBDCryptoKeyslotContext* bd_crypto_keyslot_context_new_keyring (const gchar *key_desc, GError **error G_GNUC_UNUSED) {\n    BDCryptoKeyslotContext *context = NULL;\n\n    context = g_new0 (BDCryptoKeyslotContext, 1);\n\n    context->type = BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYRING;\n\n    context->u.keyring.key_desc = g_strdup (key_desc);\n\n    return context;\n}\n\n/**\n * bd_crypto_keyslot_context_new_volume_key:\n * @volume_key: (array length=volume_key_size): a volume key for the new context (may contain arbitrary binary data)\n * @volume_key_size: length of the @volume_key_size buffer\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): new %BDCryptoKeyslotContext initialized by volume key or\n *                          %NULL in case of error\n *\n * Tech category: always available\n */\nBDCryptoKeyslotContext* bd_crypto_keyslot_context_new_volume_key (const guint8 *volume_key, gsize volume_key_size, GError **error) {\n    BDCryptoKeyslotContext *context = NULL;\n\n    if (!volume_key || volume_key_size == 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_NO_KEY,\n                     \"No volume key specified.\");\n        return NULL;\n    }\n\n    context = g_new0 (BDCryptoKeyslotContext, 1);\n\n    context->type = BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_VOLUME_KEY;\n\n    context->u.volume_key.volume_key = g_new0 (guint8, volume_key_size);\n    memcpy (context->u.volume_key.volume_key, volume_key, volume_key_size);\n\n    context->u.volume_key.volume_key_size = volume_key_size;\n\n    return context;\n}\n\n\n\ngboolean _crypto_luks_format (const gchar *device,\n                              const gchar *cipher,\n                              guint64 key_size,\n                              BDCryptoKeyslotContext *context,\n                              guint64 min_entropy,\n                              BDCryptoLUKSVersion luks_version,\n                              BDCryptoLUKSExtra *extra,\n                              BDCryptoLUKSHWEncryptionType hw_encryption,\n#ifdef LIBCRYPTSETUP_27\n                              BDCryptoKeyslotContext *opal_context,\n#else\n                              BDCryptoKeyslotContext *opal_context G_GNUC_UNUSED,\n#endif\n                               GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret;\n    gchar **cipher_specs = NULL;\n    guint32 current_entropy = 0;\n    gint dev_random_fd = -1;\n    gchar *key_buffer = NULL;\n    gsize buf_len = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    const gchar* crypt_version = NULL;\n    GError *l_error = NULL;\n    struct crypt_pbkdf_type *pbkdf = NULL;\n\n#ifdef LIBCRYPTSETUP_27\n    struct crypt_params_hw_opal opal_params = {\n\t\t.user_key_size = DEFAULT_OPAL_KEYSIZE_BITS / 8\n\t};\n\n    gboolean is_opal = (hw_encryption == BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_ONLY || hw_encryption == BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_AND_SW);\n#endif\n\n    msg = g_strdup_printf (\"Started formatting '%s' as LUKS device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    if (luks_version == BD_CRYPTO_LUKS_VERSION_LUKS1)\n        crypt_version = CRYPT_LUKS1;\n    else if (luks_version == BD_CRYPTO_LUKS_VERSION_LUKS2)\n        crypt_version = CRYPT_LUKS2;\n    else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                     \"Unknown or unsupported LUKS version specified\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (hw_encryption == BD_CRYPTO_LUKS_HW_ENCRYPTION_SW_ONLY || hw_encryption == BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_AND_SW) {\n        cipher = cipher ? cipher : DEFAULT_LUKS_CIPHER;\n        cipher_specs = g_strsplit (cipher, \"-\", 2);\n        if (g_strv_length (cipher_specs) != 2) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_SPEC,\n                        \"Invalid cipher specification: '%s'\", cipher);\n            crypt_free (cd);\n            g_strfreev (cipher_specs);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n\n        if (key_size == 0) {\n            if (g_str_has_prefix (cipher_specs[1], \"xts-\"))\n                key_size = DEFAULT_LUKS_KEYSIZE_BITS * 2;\n            else\n                key_size = DEFAULT_LUKS_KEYSIZE_BITS;\n        }\n    } else\n        cipher_specs = g_new0 (gchar*, 2);\n\n#ifdef LIBCRYPTSETUP_27\n    if (is_opal)\n        key_size += DEFAULT_OPAL_KEYSIZE_BITS;\n#endif\n\n    /* key_size should be in bytes */\n    key_size = key_size / 8;\n\n    /* wait for enough random data entropy (if requested) */\n    if (min_entropy > 0) {\n        dev_random_fd = open (\"/dev/random\", O_RDONLY);\n        if (dev_random_fd >= 0) {\n            ioctl (dev_random_fd, RNDGETENTCNT, &current_entropy);\n            while (current_entropy < min_entropy) {\n                bd_utils_report_progress (progress_id, 0, \"Waiting for enough random data entropy\");\n                sleep (1);\n                ioctl (dev_random_fd, RNDGETENTCNT, &current_entropy);\n            }\n            close (dev_random_fd);\n        } else {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                         \"Failed to check random data entropy level\");\n            crypt_free (cd);\n            g_strfreev (cipher_specs);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    }\n\n#ifdef LIBCRYPTSETUP_27\n    if (is_opal) {\n        if (opal_context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n            opal_params.admin_key = (char *) opal_context->u.passphrase.pass_data;\n            opal_params.admin_key_size = opal_context->u.passphrase.data_len;\n        } else {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                         \"Only 'passphrase' context type is valid for OPAL format.\");\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            crypt_free (cd);\n            g_strfreev (cipher_specs);\n            return FALSE;\n        }\n    }\n\n    if (is_opal) {\n        /* XXX: workaround for a bug in cryptsetup where crypt_format_luks2_opal doesn't\n         *      initialize crypto backend leading to an abort during the call, setting\n         *      the pbkdf parameters will run the initialization so just get the default\n         *      params and set them\n         *      See also: https://gitlab.com/cryptsetup/cryptsetup/-/commit/42f4a68705384eeecb5b31b71cc8a8fe19bca916\n         */\n        const struct crypt_pbkdf_type *pbkdf_default;\n        pbkdf_default = crypt_get_pbkdf_default (CRYPT_LUKS2);\n        crypt_set_pbkdf_type (cd, pbkdf_default);\n    }\n#endif\n\n    if (extra) {\n        if (luks_version == BD_CRYPTO_LUKS_VERSION_LUKS1) {\n\n            if (extra->integrity || extra->sector_size || extra->label || extra->subsystem) {\n                g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_PARAMS,\n                             \"Invalid extra arguments specified. Only `data_alignment`\"\n                             \"and `data_device` are valid for LUKS 1.\");\n                crypt_free (cd);\n                g_strfreev (cipher_specs);\n                bd_utils_report_finished (progress_id, l_error->message);\n                g_propagate_error (error, l_error);\n                return FALSE;\n            }\n\n            if (extra->pbkdf) {\n                if (g_strcmp0 (extra->pbkdf->type, \"pbkdf2\") != 0) {\n                    g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_PARAMS,\n                                 \"Invalid pbkdf specified. Only `pbkdf2` is valid for LUKS 1.\");\n                crypt_free (cd);\n                g_strfreev (cipher_specs);\n                bd_utils_report_finished (progress_id, l_error->message);\n                g_propagate_error (error, l_error);\n                return FALSE;\n                }\n\n                pbkdf = get_pbkdf_params (extra->pbkdf, &l_error);\n                if (pbkdf == NULL && l_error != NULL) {\n                    crypt_free (cd);\n                    g_strfreev (cipher_specs);\n                    bd_utils_report_finished (progress_id, l_error->message);\n                    g_propagate_prefixed_error (error, l_error,\n                                                \"Failed to get PBKDF parameters for '%s'.\", device);\n                    return FALSE;\n                }\n                crypt_set_pbkdf_type (cd, pbkdf);\n            }\n\n            struct crypt_params_luks1 params = ZERO_INIT;\n            params.data_alignment = extra->data_alignment;\n            params.data_device = extra->data_device;\n            ret = crypt_format (cd, crypt_version, cipher_specs[0], cipher_specs[1],\n                                NULL, NULL, key_size, &params);\n            g_free (pbkdf);\n        }\n        else if (luks_version == BD_CRYPTO_LUKS_VERSION_LUKS2) {\n            struct crypt_params_luks2 params = ZERO_INIT;\n            struct crypt_pbkdf_type *pbkdf = get_pbkdf_params (extra->pbkdf, &l_error);\n\n            if (pbkdf == NULL && l_error != NULL) {\n                crypt_free (cd);\n                g_strfreev (cipher_specs);\n                bd_utils_report_finished (progress_id, l_error->message);\n                g_propagate_prefixed_error (error, l_error,\n                                            \"Failed to get PBKDF parameters for '%s'.\", device);\n                return FALSE;\n            }\n\n            params.pbkdf = pbkdf;\n            params.integrity = extra->integrity;\n            params.integrity_params = NULL;\n            params.data_alignment = extra->data_alignment;\n            params.data_device = extra->data_device;\n            params.sector_size = extra->sector_size ? extra->sector_size : DEFAULT_LUKS2_SECTOR_SIZE;\n            params.label = extra->label;\n            params.subsystem = extra->subsystem;\n\n#ifdef LIBCRYPTSETUP_27\n            if (is_opal)\n                ret = crypt_format_luks2_opal (cd, cipher_specs[0], cipher_specs[1],\n                                               NULL, NULL, key_size, &params, &opal_params);\n            else\n#endif\n                ret = crypt_format (cd, crypt_version, cipher_specs[0], cipher_specs[1],\n                                    NULL, NULL, key_size, &params);\n            g_free (pbkdf);\n        }\n    } else {\n#ifdef LIBCRYPTSETUP_27\n        if (is_opal) {\n            struct crypt_params_luks2 params = ZERO_INIT;\n            params.pbkdf = crypt_get_pbkdf_default (CRYPT_LUKS2);\n            ret = crypt_format_luks2_opal (cd, cipher_specs[0], cipher_specs[1],\n                                            NULL, NULL, key_size, &params, &opal_params);\n        } else\n#endif\n            ret = crypt_format (cd, crypt_version, cipher_specs[0], cipher_specs[1],\n                                NULL, NULL, key_size, NULL);\n    }\n    g_strfreev (cipher_specs);\n\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                     \"Failed to format device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    bd_utils_report_progress (progress_id, 50, \"Format created\");\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        ret = crypt_keyslot_add_by_volume_key (cd, CRYPT_ANY_SLOT, NULL, 0,\n                                               (const char *) context->u.passphrase.pass_data,\n                                               context->u.passphrase.data_len);\n        if (ret < 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ADD_KEY,\n                         \"Failed to add passphrase: %s\", strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        bd_utils_report_progress (progress_id, 100, \"Added key\");\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buffer, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile,\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        ret = crypt_keyslot_add_by_volume_key (cd, CRYPT_ANY_SLOT, NULL, 0,\n                                               (const char*) key_buffer, buf_len);\n        crypt_safe_free (key_buffer);\n        if (ret < 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ADD_KEY,\n                         \"Failed to add key file: %s\", strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        bd_utils_report_progress (progress_id, 100, \"Added key\");\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for LUKS format.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_format:\n * @device: a device to format as LUKS\n * @cipher: (nullable): cipher specification (type-mode, e.g. \"aes-xts-plain64\") or %NULL to use the default\n * @key_size: size of the volume key in bits or 0 to use the default\n * @context: key slot context (passphrase/keyfile/token...) for this LUKS device\n * @min_entropy: minimum random data entropy (in bits) required to format @device as LUKS\n * @luks_version: whether to use LUKS v1 or LUKS v2\n * @extra: (nullable): extra arguments for LUKS format creation\n * @error: (out) (optional): place to store error (if any)\n *\n * Formats the given @device as LUKS according to the other parameters given. If\n * @min_entropy is specified (greater than 0), the function waits for enough\n * entropy to be available in the random data pool (WHICH MAY POTENTIALLY TAKE\n * FOREVER).\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the given @device was successfully formatted as LUKS or not\n * (the @error) contains the error in such cases)\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_CREATE\n */\ngboolean bd_crypto_luks_format (const gchar *device, const gchar *cipher, guint64 key_size, BDCryptoKeyslotContext *context, guint64 min_entropy, BDCryptoLUKSVersion luks_version, BDCryptoLUKSExtra *extra,GError **error) {\n    return _crypto_luks_format (device, cipher, key_size, context, min_entropy, luks_version, extra, BD_CRYPTO_LUKS_HW_ENCRYPTION_SW_ONLY, NULL, error);\n}\n\nstatic gboolean _is_dm_name_valid (const gchar *name, GError **error) {\n    if (strlen (name) >= 128) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_PARAMS,\n                     \"Device name can be at most 127 characters long.\");\n        return FALSE;\n    }\n\n    if (strchr (name, '/')) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_PARAMS,\n                     \"Device name cannot contain '/' character.\");\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_open:\n * @device: the device to open\n * @name: name for the LUKS device\n * @context: key slot context (passphrase/keyfile/token...) to open this LUKS @device\n * @read_only: whether to open as read-only or not (meaning read-write)\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file, keyring\n *\n * Returns: whether the @device was successfully opened or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n *\n * Example of using %bd_crypto_luks_open with %BDCryptoKeyslotContext:\n *\n * |[<!-- language=\"C\" -->\n * BDCryptoKeyslotContext *context = NULL;\n *\n * context = bd_crypto_keyslot_context_new_passphrase (\"passphrase\", 10, NULL);\n * bd_crypto_luks_open (\"/dev/vda1\", \"luks-device\", context, FALSE, NULL);\n * ]|\n */\ngboolean bd_crypto_luks_open (const gchar *device, const gchar *name, BDCryptoKeyslotContext *context, gboolean read_only, GError **error) {\n    struct crypt_device *cd = NULL;\n    gchar *key_buffer = NULL;\n    gsize buf_len = 0;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    if (!_is_dm_name_valid (name, error))\n        return FALSE;\n\n    msg = g_strdup_printf (\"Started opening '%s' LUKS device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT,\n                                            (const char *) context->u.passphrase.pass_data,\n                                            context->u.passphrase.data_len,\n                                            read_only ? CRYPT_ACTIVATE_READONLY : 0);\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buffer, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile, strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT, key_buffer, buf_len,\n                                            read_only ? CRYPT_ACTIVATE_READONLY : 0);\n        crypt_safe_free (key_buffer);\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYRING)\n        ret = crypt_activate_by_keyring (cd, name, context->u.keyring.key_desc, CRYPT_ANY_SLOT,\n                                         read_only ? CRYPT_ACTIVATE_READONLY : 0);\n    else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase', 'key file' and 'keyring' context types are valid for LUKS open.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (ret < 0) {\n        if (ret == -EPERM)\n          g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                       \"Failed to activate device: Incorrect passphrase.\");\n        else\n          g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                       \"Failed to activate device: %s\", strerror_l (-ret, c_locale));\n\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\nstatic gboolean _crypto_close (const gchar *device, const gchar *tech_name, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started closing %s device '%s'\", tech_name, device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init_by_name (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_deactivate (cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to deactivate device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_close:\n * @luks_device: LUKS device to close\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @luks_device was successfully closed or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_luks_close (const gchar *luks_device, GError **error) {\n    return _crypto_close (luks_device, \"LUKS\", error);\n}\n\n/**\n * bd_crypto_luks_add_key:\n * @device: device to add new key to\n * @context: key slot context (passphrase/keyfile/token...) for this LUKS @device\n * @ncontext: new key slot context (passphrase/keyfile/token...) to add to this LUKS @device\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the @ncontext was successfully added to @device\n * or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_ADD_KEY\n */\ngboolean bd_crypto_luks_add_key (const gchar *device, BDCryptoKeyslotContext *context, BDCryptoKeyslotContext *ncontext, GError **error) {\n    gchar *key_buf = NULL;\n    gsize buf_len = 0;\n    gchar *nkey_buf = NULL;\n    gsize nbuf_len = 0;\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    GError *l_error = NULL;\n    gchar *msg = NULL;\n\n    msg = g_strdup_printf (\"Started adding key to the LUKS device '%s'\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buf, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to load key from file '%s': %s\", context->u.keyfile.keyfile,\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        key_buf = (char *) context->u.passphrase.pass_data;\n        buf_len = context->u.passphrase.data_len;\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for LUKS add key.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (ncontext->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, ncontext->u.keyfile.keyfile, &nkey_buf, &nbuf_len,\n                                         ncontext->u.keyfile.keyfile_offset, ncontext->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to load key from file '%s': %s\", ncontext->u.keyfile.keyfile,\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n                crypt_safe_free (key_buf);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    } else if (ncontext->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        nkey_buf = (char *) ncontext->u.passphrase.pass_data;\n        nbuf_len = ncontext->u.passphrase.data_len;\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for LUKS add key.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_keyslot_add_by_passphrase (cd, CRYPT_ANY_SLOT, key_buf, buf_len, nkey_buf, nbuf_len);\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n        crypt_safe_free (key_buf);\n    if (ncontext->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n        crypt_safe_free (nkey_buf);\n    crypt_free (cd);\n\n    if (ret < 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ADD_KEY,\n                     \"Failed to add key: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_remove_key:\n * @device: device to add new key to\n * @context: key slot context (passphrase/keyfile/token...) to remove from this LUKS @device\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the key was successfully removed or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_REMOVE_KEY\n */\ngboolean bd_crypto_luks_remove_key (const gchar *device, BDCryptoKeyslotContext *context, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    gchar *key_buf = NULL;\n    gsize buf_len = 0;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started removing key from the LUKS device '%s'\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        ret = crypt_activate_by_passphrase (cd, NULL, CRYPT_ANY_SLOT,\n                                            (const char *) context->u.passphrase.pass_data,\n                                            context->u.passphrase.data_len, 0);\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buf, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile, strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        ret = crypt_activate_by_passphrase (cd, NULL, CRYPT_ANY_SLOT, key_buf, buf_len, 0);\n        crypt_safe_free (key_buf);\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for LUKS remove key.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (ret < 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEY_SLOT,\n                     \"Failed to determine key slot: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_keyslot_destroy (cd, ret);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_REMOVE_KEY,\n                     \"Failed to remove key: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_change_key:\n * @device: device to change key of\n * @context: key slot context (passphrase/keyfile/token...) for this LUKS @device\n * @ncontext: new key slot context (passphrase/keyfile/token...) to add to this LUKS @device\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the key was successfully changed or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_ADD_KEY&%BD_CRYPTO_TECH_MODE_REMOVE_KEY\n */\ngboolean bd_crypto_luks_change_key (const gchar *device, BDCryptoKeyslotContext *context, BDCryptoKeyslotContext *ncontext, GError **error) {\n    struct crypt_device *cd = NULL;\n    gchar *key_buf = NULL;\n    gsize buf_len = 0;\n    gchar *nkey_buf = NULL;\n    gsize nbuf_len = 0;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started changing key on the LUKS device '%s'\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buf, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to load key from file '%s': %s\", context->u.keyfile.keyfile,\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        key_buf = (char *) context->u.passphrase.pass_data;\n        buf_len = context->u.passphrase.data_len;\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for LUKS change key.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (ncontext->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, ncontext->u.keyfile.keyfile, &key_buf, &buf_len,\n                                         ncontext->u.keyfile.keyfile_offset, ncontext->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to load key from file '%s': %s\", ncontext->u.keyfile.keyfile,\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n                crypt_safe_free (key_buf);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    } else if (ncontext->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        nkey_buf = (char *) ncontext->u.passphrase.pass_data;\n        nbuf_len = ncontext->u.passphrase.data_len;\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for LUKS change key.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_keyslot_change_by_passphrase (cd, CRYPT_ANY_SLOT, CRYPT_ANY_SLOT,\n                                              key_buf, buf_len, nkey_buf, nbuf_len);\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n        crypt_safe_free (key_buf);\n    if (ncontext->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE)\n        crypt_safe_free (nkey_buf);\n    crypt_free (cd);\n\n    if (ret < 0) {\n        if (ret == -EPERM)\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                         \"Failed to change the passphrase: No keyslot with given passphrase found.\");\n        else\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ADD_KEY,\n                         \"Failed to change the passphrase: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_resize:\n * @luks_device: opened LUKS device to resize\n * @size: requested size in sectors or 0 to adapt to the backing device\n * @context: (nullable): key slot context (passphrase/keyfile/token...) for this LUKS @device\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the @luks_device was successfully resized or not\n *\n * You need to specify either @context for LUKS 2 devices that\n * don't have verified key loaded in kernel.\n * For LUKS 1 devices you can set @context %NULL.\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_RESIZE\n */\ngboolean bd_crypto_luks_resize (const gchar *luks_device, guint64 size, BDCryptoKeyslotContext *context, GError **error) {\n    struct crypt_device *cd = NULL;\n    struct crypt_active_device cad;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    gchar *key_buffer = NULL;\n    gsize buf_len = 0;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started resizing LUKS device '%s'\", luks_device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init_by_name (&cd, luks_device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_get_active_device (cd, luks_device, &cad);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to get information about '%s': %s\",\n                     luks_device, strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context) {\n        if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n            ret = crypt_activate_by_passphrase (cd, NULL, CRYPT_ANY_SLOT,\n                                                (const char *) context->u.passphrase.pass_data,\n                                                context->u.passphrase.data_len,\n                                                cad.flags & CRYPT_ACTIVATE_KEYRING_KEY);\n        } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n            ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buffer, &buf_len,\n                                             context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n            if (ret != 0) {\n                g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                             \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile, strerror_l (-ret, c_locale));\n                crypt_free (cd);\n                bd_utils_report_finished (progress_id, l_error->message);\n                g_propagate_error (error, l_error);\n                return FALSE;\n            }\n            ret = crypt_activate_by_passphrase (cd, NULL, CRYPT_ANY_SLOT, key_buffer, buf_len,\n                                                cad.flags & CRYPT_ACTIVATE_KEYRING_KEY);\n            crypt_safe_free (key_buffer);\n        } else {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                        \"Only 'passphrase' and 'key file' context types are valid for LUKS resize.\");\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            crypt_free (cd);\n            return FALSE;\n        }\n\n        if (ret < 0) {\n            if (ret == -EPERM)\n              g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                           \"Failed to activate device: Incorrect passphrase.\");\n            else\n              g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                           \"Failed to activate device: %s\", strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    }\n\n    ret = crypt_resize (cd, luks_device, size);\n    if (ret != 0) {\n        if (ret == -EPERM && g_strcmp0 (crypt_get_type (cd), CRYPT_LUKS2) == 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_RESIZE_PERM,\n                         \"Insufficient permissions to resize device. You need to specify\"\n                         \" passphrase or keyfile to resize LUKS 2 devices that don't\"\n                         \" have verified key loaded in kernel.\");\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n\n        }\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_RESIZE_FAILED,\n                     \"Failed to resize device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_suspend:\n * @luks_device: LUKS device to suspend\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @luks_device was successfully suspended or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_SUSPEND_RESUME\n */\ngboolean bd_crypto_luks_suspend (const gchar *luks_device, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started suspending LUKS device '%s'\", luks_device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init_by_name (&cd, luks_device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_suspend (cd, luks_device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to suspend device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_resume:\n * @luks_device: LUKS device to resume\n * @context: (nullable): key slot context (passphrase/keyfile/token...) for @luks_device\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the given @luks_device was successfully resumed or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_SUSPEND_RESUME\n */\ngboolean bd_crypto_luks_resume (const gchar *luks_device, BDCryptoKeyslotContext *context, GError **error) {\n    struct crypt_device *cd = NULL;\n    gchar *key_buffer = NULL;\n    gsize buf_len = 0;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started resuming '%s' LUKS device\", luks_device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init_by_name (&cd, luks_device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        ret = crypt_resume_by_passphrase (cd, luks_device, CRYPT_ANY_SLOT,\n                                          (const char *) context->u.passphrase.pass_data,\n                                          context->u.passphrase.data_len);\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buffer, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile, strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        ret = crypt_resume_by_passphrase (cd, luks_device, CRYPT_ANY_SLOT, key_buffer, buf_len);\n        crypt_safe_free (key_buffer);\n    } else {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                        \"Only 'passphrase' and 'key file' context types are valid for LUKS resume.\");\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            crypt_free (cd);\n            return FALSE;\n    }\n\n    if (ret < 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to resume device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_kill_slot:\n * @device: device to kill slot on\n * @slot: keyslot to destroy\n * @error: (out) (optional): place to store error (if any)\n *\n * Note: This can destroy last remaining keyslot without confirmation making\n *       the LUKS device permanently inaccessible.\n *\n * Returns: whether the given @slot was successfully destroyed or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_REMOVE_KEY\n */\ngboolean bd_crypto_luks_kill_slot (const gchar *device, gint slot, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started killing slot %d on LUKS device '%s'\", slot, device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_keyslot_destroy (cd, slot);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to destroy keyslot: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_header_backup:\n * @device: device to backup the LUKS header\n * @backup_file: file to save the header backup to\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given backup of @device was successfully written to\n *          @backup_file or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_BACKUP_RESTORE\n */\ngboolean bd_crypto_luks_header_backup (const gchar *device, const gchar *backup_file, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started header backup of LUKS device '%s'\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_header_backup (cd, NULL, backup_file);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to backup LUKS header: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_header_restore:\n * @device: device to restore the LUKS header to\n * @backup_file: existing file with a LUKS header backup\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @device LUKS header was successfully restored\n *          from @backup_file\n *\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_BACKUP_RESTORE\n */\ngboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup_file, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started LUKS header restore on device '%s'\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_header_restore (cd, NULL, backup_file);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to restore LUKS header: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_set_label:\n * @device: device to set label on\n * @label: (nullable): label to set\n * @subsystem: (nullable): subsystem to set\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @label and @subsystem were successfully set or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY\n */\ngboolean bd_crypto_luks_set_label (const gchar *device, const gchar *label, const gchar *subsystem, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (g_strcmp0 (crypt_get_type (cd), CRYPT_LUKS2) != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                     \"Label can be set only on LUKS 2 devices: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_set_label (cd, label, subsystem);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to set label: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_set_uuid:\n * @device: device to set UUID on\n * @uuid: (nullable): UUID to set or %NULL to generate a new one\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @uuid was successfully set or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY\n */\ngboolean bd_crypto_luks_set_uuid (const gchar *device, const gchar *uuid, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_set_uuid (cd, uuid);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to set UUID: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_convert:\n * @device:  a LUKS device to convert to a different version of LUKS\n * @target_version: the LUKS version to convert to\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the @device was converted to @target_version.\n *          False, if the @device is already in the @target_version format.\n *\n * Warning: LUKS header loss is possible. See bd_crypto_luks_header_backup() and bd_crypto_luks_header_restore()\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY\n */\ngboolean bd_crypto_luks_convert (const gchar *device, BDCryptoLUKSVersion target_version, GError **error) {\n    struct crypt_device *cd = NULL;\n    const char *cd_type;\n    const char *target_type;\n    gint ret = 0;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    cd_type = crypt_get_type (cd);\n    if (g_strcmp0 (cd_type, CRYPT_LUKS1) != 0 &&\n        g_strcmp0 (cd_type, CRYPT_LUKS2) != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_CONVERT_FAILED,\n                     \"It is possible to convert only between LUKS1 and LUKS2 formats. Device %s is of type: %s\", device, cd_type);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    target_type = target_version == BD_CRYPTO_LUKS_VERSION_LUKS1 ? CRYPT_LUKS1 : CRYPT_LUKS2;\n    if (g_strcmp0 (cd_type, target_type) == 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_CONVERT_FAILED,\n                     \"Conversion to the %s type was requested, but device %s is already of type: %s\", target_type, device, cd_type);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_convert (cd, target_type, NULL);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Conversion failed: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_set_persistent_flags:\n * @device: a LUKS device to set the persistent flags on\n * @flags: flags to set\n * @error: (out) (optional): place to store error (if any)\n *\n * Note: This function is valid only for LUKS2.\n *\n * Returns: whether the given @flags were successfully set or not\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY\n */\ngboolean bd_crypto_luks_set_persistent_flags (const gchar *device, BDCryptoLUKSPersistentFlags flags, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint32 crypt_flags = 0;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (g_strcmp0 (crypt_get_type (cd), CRYPT_LUKS2) != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Persistent flags can be set only on LUKS v2\");\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_ALLOW_DISCARDS)\n        crypt_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_SAME_CPU_CRYPT)\n        crypt_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)\n        crypt_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_NO_JOURNAL)\n        crypt_flags |= CRYPT_ACTIVATE_NO_JOURNAL;\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_NO_READ_WORKQUEUE)\n        crypt_flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_NO_WRITE_WORKQUEUE)\n        crypt_flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;\n    if (flags & BD_CRYPTO_LUKS_ACTIVATE_HIGH_PRIORITY) {\n#ifdef LIBCRYPTSETUP_28\n        crypt_flags |= CRYPT_ACTIVATE_HIGH_PRIORITY;\n#else\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                     \"Libcryptsetup 2.8 or newer is needed for 'high priority' flag support\");\n        crypt_free (cd);\n        return FALSE;\n#endif\n    }\n\n\n    ret = crypt_persistent_flags_set (cd, CRYPT_FLAGS_ACTIVATION, crypt_flags);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to set flags: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n\n    return TRUE;\n}\n\nstatic gint synced_close (gint fd) {\n    gint ret = 0;\n    ret = fsync (fd);\n    if (close (fd) != 0)\n        ret = 1;\n    return ret;\n}\n\nstatic gboolean get_subsystem_label (const gchar *device, gchar **subsystem, gchar **label, GError **error) {\n    blkid_probe probe = NULL;\n    gint fd = 0;\n    gint status = 0;\n    const gchar *value = NULL;\n\n    probe = blkid_new_probe ();\n    if (!probe) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to create a probe for the device '%s'\", device);\n        return FALSE;\n    }\n\n    fd = open (device, O_RDONLY|O_CLOEXEC);\n    if (fd == -1) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to create a probe for the device '%s'\", device);\n        blkid_free_probe (probe);\n        return FALSE;\n    }\n\n    status = blkid_probe_set_device (probe, fd, 0, 0);\n    if (status != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to create a probe for the device '%s'\", device);\n        blkid_free_probe (probe);\n        synced_close (fd);\n        return FALSE;\n    }\n\n    blkid_probe_enable_partitions (probe, 1);\n\n    status = blkid_do_probe (probe);\n    if (status != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to probe the device '%s'\", device);\n        blkid_free_probe (probe);\n        synced_close (fd);\n        return FALSE;\n    }\n\n    status = blkid_probe_has_value (probe, \"LABEL\");\n\n    if (status == 0)\n        *label = g_strdup (\"\");\n    else {\n        status = blkid_probe_lookup_value (probe, \"LABEL\", &value, NULL);\n        if (status != 0) {\n            g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                         \"Failed to get label for the device '%s'\", device);\n            blkid_free_probe (probe);\n            synced_close (fd);\n            return FALSE;\n        }\n\n        if (value)\n            *label = g_strdup (value);\n        else\n            *label = g_strdup (\"\");\n    }\n\n    status = blkid_probe_has_value (probe, \"SUBSYSTEM\");\n    if (status == 0)\n        *subsystem = g_strdup (\"\");\n    else {\n        status = blkid_probe_lookup_value (probe, \"SUBSYSTEM\", &value, NULL);\n        if (status != 0) {\n            g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                         \"Failed to get subsystem for the device '%s'\", device);\n            blkid_free_probe (probe);\n            synced_close (fd);\n            return FALSE;\n        }\n\n        if (value)\n            *subsystem = g_strdup (value);\n        else\n            *subsystem = g_strdup (\"\");\n    }\n\n    blkid_free_probe (probe);\n    synced_close (fd);\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_luks_info:\n * @device: a device to get information about\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): information about the @device or %NULL in case of error\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_QUERY\n */\nBDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *device, GError **error) {\n    struct crypt_device *cd = NULL;\n    BDCryptoLUKSInfo *info = NULL;\n    const gchar *version = NULL;\n    gint ret;\n    gboolean success = FALSE;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        /* not a block device, try init_by_name */\n        crypt_free (cd);\n        ret = crypt_init_by_name (&cd, device);\n    } else {\n        ret = crypt_load (cd, CRYPT_LUKS, NULL);\n        if (ret != 0) {\n            /* not a LUKS device, try init_by_name */\n            crypt_free (cd);\n            ret = crypt_init_by_name (&cd, device);\n        }\n    }\n\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return NULL;\n    }\n\n    info = g_new0 (BDCryptoLUKSInfo, 1);\n\n    version = crypt_get_type (cd);\n    if (g_strcmp0 (version, CRYPT_LUKS1) == 0)\n        info->version = BD_CRYPTO_LUKS_VERSION_LUKS1;\n    else if (g_strcmp0 (version, CRYPT_LUKS2) == 0)\n        info->version = BD_CRYPTO_LUKS_VERSION_LUKS2;\n    else {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                     \"Unknown or unsupported LUKS version\");\n        bd_crypto_luks_info_free (info);\n        return NULL;\n    }\n\n    info->cipher = g_strdup (crypt_get_cipher (cd));\n    info->mode = g_strdup (crypt_get_cipher_mode (cd));\n    info->uuid = g_strdup (crypt_get_uuid (cd));\n    info->backing_device = g_strdup (crypt_get_device_name (cd));\n    ret = crypt_get_sector_size (cd);\n    info->sector_size = ret > 0 ? ret : 0;\n    info->metadata_size = SECTOR_SIZE * crypt_get_data_offset (cd);\n\n    if (info->version == BD_CRYPTO_LUKS_VERSION_LUKS2) {\n        success = get_subsystem_label (crypt_get_device_name (cd) , &(info->subsystem), &(info->label), error);\n        if (!success) {\n            crypt_free (cd);\n            bd_crypto_luks_info_free (info);\n            return NULL;\n        }\n    } else {\n        info->label = g_strdup (\"\");\n        info->subsystem = g_strdup (\"\");\n    }\n\n#ifdef LIBCRYPTSETUP_27\n    ret = crypt_get_hw_encryption_type (cd);\n    if (ret < 0) {\n        info->hw_encryption = BD_CRYPTO_LUKS_HW_ENCRYPTION_UNKNOWN;\n        bd_utils_log_format (BD_UTILS_LOG_WARNING, \"Failed to get HW encryption type: %s\", strerror_l (-ret, c_locale));\n    } else {\n        switch (ret) {\n            case CRYPT_SW_ONLY:\n                info->hw_encryption = BD_CRYPTO_LUKS_HW_ENCRYPTION_SW_ONLY;\n                break;\n            case CRYPT_SW_AND_OPAL_HW:\n                info->hw_encryption = BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_AND_SW;\n                break;\n            case CRYPT_OPAL_HW_ONLY:\n                info->hw_encryption = BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_ONLY;\n                break;\n            default:\n                bd_utils_log_format (BD_UTILS_LOG_WARNING, \"Unknown HW encryption type: %d\", ret);\n                info->hw_encryption = BD_CRYPTO_LUKS_HW_ENCRYPTION_UNKNOWN;\n                break;\n        }\n    }\n#else\n    info->hw_encryption = BD_CRYPTO_LUKS_HW_ENCRYPTION_UNKNOWN;\n#endif\n\n    crypt_free (cd);\n\n    return info;\n}\n\n/**\n * bd_crypto_bitlk_info:\n * @device: a device to get information about\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): information about the @device or %NULL in case of error\n *\n * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_QUERY\n */\nBDCryptoBITLKInfo* bd_crypto_bitlk_info (const gchar *device, GError **error) {\n    struct crypt_device *cd = NULL;\n    BDCryptoBITLKInfo *info = NULL;\n    gint ret;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        /* not a block device, try init_by_name */\n        crypt_free (cd);\n        cd = NULL;\n        ret = crypt_init_by_name (&cd, device);\n    } else {\n        ret = crypt_load (cd, CRYPT_BITLK, NULL);\n        if (ret != 0) {\n            /* not a BITLK device, try init_by_name */\n            crypt_free (cd);\n            cd = NULL;\n            ret = crypt_init_by_name (&cd, device);\n        }\n    }\n\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return NULL;\n    }\n\n    info = g_new0 (BDCryptoBITLKInfo, 1);\n\n    info->cipher = g_strdup (crypt_get_cipher (cd));\n    info->mode = g_strdup (crypt_get_cipher_mode (cd));\n    info->uuid = g_strdup (crypt_get_uuid (cd));\n    info->backing_device = g_strdup (crypt_get_device_name (cd));\n    ret = crypt_get_sector_size (cd);\n    info->sector_size = ret > 0 ? ret : 0;\n\n    crypt_free (cd);\n\n    return info;\n}\n\n/**\n * bd_crypto_integrity_info:\n * @device: a device to get information about\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns (transfer full): information about the @device or %NULL in case of error\n *\n * Tech category: %BD_CRYPTO_TECH_INTEGRITY%BD_CRYPTO_TECH_MODE_QUERY\n */\nBDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error) {\n    struct crypt_device *cd = NULL;\n    struct crypt_params_integrity ip = ZERO_INIT;\n    BDCryptoIntegrityInfo *info = NULL;\n    gint ret;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        /* not a block device, try init_by_name */\n        crypt_free (cd);\n        ret = crypt_init_by_name (&cd, device);\n    } else {\n        ret = crypt_load (cd, CRYPT_LUKS, NULL);\n        if (ret != 0) {\n            /* not a LUKS device, try integrity */\n            ret = crypt_load (cd, CRYPT_INTEGRITY, NULL);\n            if (ret != 0) {\n                crypt_free (cd);\n                ret = crypt_init_by_name (&cd, device);\n            }\n        }\n    }\n\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return NULL;\n    }\n\n    ret = crypt_get_integrity_info (cd, &ip);\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to get information about device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        return NULL;\n    }\n\n    info = g_new0 (BDCryptoIntegrityInfo, 1);\n\n    info->algorithm = g_strdup (ip.integrity);\n    info->key_size = ip.integrity_key_size;\n    info->sector_size = ip.sector_size;\n    info->tag_size = ip.tag_size;\n    info->interleave_sectors = ip.interleave_sectors;\n    info->journal_size = ip.journal_size;\n    info->journal_crypt = g_strdup (ip.journal_crypt);\n    info->journal_integrity = g_strdup (ip.journal_integrity);\n\n    crypt_free (cd);\n    return info;\n}\n\n/* added in cryptsetup 2.4.0 */\n#ifndef LIBCRYPTSETUP_24\nstatic int crypt_token_max (const char *type G_GNUC_UNUSED) {\n    return 32;\n}\n#endif\n\n\n/**\n * bd_crypto_luks_token_info:\n * @device: a device to get LUKS2 token information about\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: (array zero-terminated=1) (transfer full): information about tokens on @device\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_QUERY\n */\nBDCryptoLUKSTokenInfo** bd_crypto_luks_token_info (const gchar *device, GError **error) {\n    struct crypt_device *cd = NULL;\n    GPtrArray *tokens = NULL;\n    BDCryptoLUKSTokenInfo *info = NULL;\n    crypt_token_info token_info;\n    const gchar *type = NULL;\n    gint ret;\n    gint token_it, keyslot_it;\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        /* not a block device, try init_by_name */\n        crypt_free (cd);\n        ret = crypt_init_by_name (&cd, device);\n    } else {\n        ret = crypt_load (cd, CRYPT_LUKS, NULL);\n        if (ret != 0) {\n            /* not a LUKS device, try init_by_name */\n            crypt_free (cd);\n            ret = crypt_init_by_name (&cd, device);\n        }\n    }\n\n    if (ret != 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        return NULL;\n    }\n\n    if (g_strcmp0 (crypt_get_type (cd), CRYPT_LUKS2) != 0) {\n        crypt_free (cd);\n        return NULL;\n    }\n\n    tokens = g_ptr_array_new ();\n\n    for (token_it = 0; token_it < crypt_token_max (CRYPT_LUKS2); token_it++) {\n        token_info = crypt_token_status (cd, token_it, &type);\n        if (token_info == CRYPT_TOKEN_INVALID || token_info == CRYPT_TOKEN_INACTIVE)\n            continue;\n\n        info = g_new0 (BDCryptoLUKSTokenInfo, 1);\n        info->id = token_it;\n        info->type = g_strdup (type);\n        info->keyslot = -1;\n\n        for (keyslot_it = 0; keyslot_it < crypt_keyslot_max (CRYPT_LUKS2); keyslot_it++) {\n            ret = crypt_token_is_assigned (cd, token_it, keyslot_it);\n            if (ret == 0) {\n                info->keyslot = keyslot_it;\n                break;\n            }\n        }\n\n        g_ptr_array_add (tokens, info);\n    }\n\n    crypt_free (cd);\n\n    /* returning NULL-terminated array of BDCryptoLUKSTokenInfo */\n    g_ptr_array_add (tokens, NULL);\n    return (BDCryptoLUKSTokenInfo **) g_ptr_array_free (tokens, FALSE);\n}\n\nstatic int _wipe_progress (guint64 size, guint64 offset, void *usrptr) {\n    /* \"convert\" the progress from 0-100 to 50-100 because wipe starts at 50 in bd_crypto_integrity_format */\n    gdouble progress = 50 + (((gdouble) offset / size) * 100) / 2;\n    bd_utils_report_progress (*(guint64 *) usrptr, progress, \"Integrity device wipe in progress\");\n\n    return 0;\n}\n\n/**\n * bd_crypto_integrity_format:\n * @device: a device to format as integrity\n * @algorithm: integrity algorithm specification (e.g. \"crc32c\" or \"sha256\")\n * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums\n * @context: (nullable): key slot context (passphrase/keyfile/token...) for this device\n * @extra: (nullable): extra arguments for integrity format creation\n * @error: (out) (optional): place to store error (if any)\n *\n * Formats the given @device as integrity according to the other parameters given.\n *\n * Supported @context types for this function: volume key\n *\n * Returns: whether the given @device was successfully formatted as integrity or not\n * (the @error) contains the error in such cases)\n *\n * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE\n */\ngboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, BDCryptoKeyslotContext *context, BDCryptoIntegrityExtra *extra, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    struct crypt_params_integrity params = ZERO_INIT;\n    g_autofree gchar *tmp_name = NULL;\n    g_autofree gchar *tmp_path = NULL;\n    g_autofree gchar *dev_name = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started formatting '%s' as integrity device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    if (context && context->type != BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_VOLUME_KEY) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                    \"Only 'volume key' context type is valid for integrity format.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (extra) {\n        params.sector_size = extra->sector_size;\n        params.journal_size = extra->journal_size;\n        params.journal_watermark = extra->journal_watermark;\n        params.journal_commit_time = extra->journal_commit_time;\n        params.interleave_sectors = extra->interleave_sectors;\n        params.tag_size = extra->tag_size;\n        params.buffer_sectors = extra->buffer_sectors;\n    }\n\n    params.integrity_key_size = context ? context->u.volume_key.volume_key_size : 0;\n    params.integrity = algorithm;\n    params.tag_size = params.tag_size ? params.tag_size : 0;\n\n    ret = crypt_format (cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, &params);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                     \"Failed to format device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (wipe) {\n        bd_utils_report_progress (progress_id, 50, \"Format created\");\n\n        dev_name = g_path_get_basename (device);\n        tmp_name = g_strdup_printf (\"bd-temp-integrity-%s-%d\", dev_name, g_random_int ());\n        tmp_path = g_strdup_printf (\"%s/%s\", crypt_get_dir (), tmp_name);\n\n        ret = crypt_activate_by_volume_key (cd, tmp_name,\n                                            context ? (const char *) context->u.volume_key.volume_key : NULL,\n                                            context ? context->u.volume_key.volume_key_size : 0,\n                                            CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                         \"Failed to activate the newly created integrity device for wiping: %s\",\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n\n        bd_utils_report_progress (progress_id, 50, \"Starting to wipe the newly created integrity device\");\n        ret = crypt_wipe (cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, 1048576,\n                          0, &_wipe_progress, &progress_id);\n        bd_utils_report_progress (progress_id, 100, \"Wipe finished\");\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                         \"Failed to wipe the newly created integrity device: %s\",\n                         strerror_l (-ret, c_locale));\n\n            ret = crypt_deactivate (cd, tmp_name);\n            if (ret != 0)\n                bd_utils_log_format (BD_UTILS_LOG_ERR, \"Failed to deactivate temporary device %s\", tmp_name);\n\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n\n        ret = crypt_deactivate (cd, tmp_name);\n        if (ret != 0)\n            bd_utils_log_format (BD_UTILS_LOG_ERR, \"Failed to deactivate temporary device %s\", tmp_name);\n\n    } else\n        bd_utils_report_finished (progress_id, \"Completed\");\n\n    crypt_free (cd);\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_integrity_open:\n * @device: integrity device to open\n * @name: name for the opened @device\n * @algorithm: integrity algorithm specification (e.g. \"crc32c\" or \"sha256\")\n * @context: (nullable): key slot context (passphrase/keyfile/token...) for this device\n * @flags: flags for the integrity device activation\n * @extra: (nullable): extra arguments for integrity open\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: volume key\n *\n * Returns: whether the @device was successfully opened or not\n *\n * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, BDCryptoKeyslotContext *context, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    struct crypt_params_integrity params = ZERO_INIT;\n    guint32 activate_flags = 0;\n    GError *l_error = NULL;\n\n    if (context && context->type != BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_VOLUME_KEY) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'volume key' context type is valid for integrity format.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    params.integrity = algorithm;\n    params.integrity_key_size = context ? context->u.volume_key.volume_key_size : 0;\n\n    if (extra) {\n        params.sector_size = extra->sector_size;\n        params.journal_size = extra->journal_size;\n        params.journal_watermark = extra->journal_watermark;\n        params.journal_commit_time = extra->journal_commit_time;\n        params.interleave_sectors = extra->interleave_sectors;\n        params.tag_size = extra->tag_size;\n        params.buffer_sectors = extra->buffer_sectors;\n    }\n\n\n    if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL)\n        activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL;\n    if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECOVERY)\n        activate_flags |= CRYPT_ACTIVATE_RECOVERY;\n    if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE)\n        activate_flags |= CRYPT_ACTIVATE_RECALCULATE;\n    if (flags & BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS)\n        activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;\n    if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP)\n        activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;\n\n    if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET) {\n#ifndef CRYPT_ACTIVATE_RECALCULATE_RESET\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL,\n                     \"Cannot reset integrity recalculation while activating %s, installed version of cryptsetup doesn't support this option.\", device);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n#else\n        activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET;\n#endif\n    }\n\n    if (!_is_dm_name_valid (name, error))\n        return FALSE;\n\n    msg = g_strdup_printf (\"Started opening '%s' integrity device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_INTEGRITY, &params);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_activate_by_volume_key (cd, name,\n                                        context ? (const char *) context->u.volume_key.volume_key : NULL,\n                                        context ? context->u.volume_key.volume_key_size : 0,\n                                        activate_flags);\n    if (ret < 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to activate device: %s\", strerror_l (-ret, c_locale));\n\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_integrity_close:\n * @integrity_device: integrity device to close\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @integrity_device was successfully closed or not\n *\n * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error) {\n    return _crypto_close (integrity_device, \"integrity\", error);\n}\n\n/**\n * bd_crypto_keyring_add_key:\n * @key_desc: kernel keyring key description\n * @key_data: (array length=data_len): a key to add to kernel keyring (may contain arbitrary binary data)\n * @data_len: length of the @key_data buffer\n * @error: (out) (optional): place to store error (if any)\n * *\n * Returns: whether the given key was successfully saved to kernel keyring or not\n *\n * Tech category: %BD_CRYPTO_TECH_KEYRING-%BD_CRYPTO_TECH_MODE_ADD_KEY\n */\ngboolean bd_crypto_keyring_add_key (const gchar *key_desc, const guint8 *key_data, gsize data_len, GError **error) {\n    key_serial_t ret;\n\n    ret = add_key (\"user\", key_desc, key_data, data_len, KEY_SPEC_SESSION_KEYRING);\n    if (ret < 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYRING,\n                     \"Failed to add key to kernel keyring: %s\", strerror_l (errno, c_locale));\n        return FALSE;\n    }\n\n    return TRUE;\n}\n\n/**\n * bd_crypto_device_seems_encrypted:\n * @device: the queried device\n * @error: (out) (optional): place to store error (if any)\n *\n * Determines whether a block device seems to be encrypted.\n *\n * TCRYPT volumes are not easily identifiable, because they have no\n * cleartext header, but are completely encrypted. This function is\n * used to determine whether a block device is a candidate for being\n * TCRYPT encrypted.\n *\n * To achieve this, we calculate the chi square value of the first\n * 512 Bytes and treat devices with a chi square value between 136\n * and 426 as candidates for being encrypted.\n * For the reasoning, see: https://tails.boum.org/blueprint/veracrypt/#detection\n *\n * Returns: %TRUE if the given @device seems to be encrypted or %FALSE if not or\n * failed to determine (the @error) is populated with the error in such\n * cases)\n *\n * Tech category: %BD_CRYPTO_TECH_TRUECRYPT-%BD_CRYPTO_TECH_MODE_QUERY\n */\ngboolean bd_crypto_device_seems_encrypted (const gchar *device, GError **error) {\n    gint fd = -1;\n    guchar buf[SQUARE_BYTES_TO_CHECK];\n    guint symbols[256] = {0};\n    gfloat chi_square = 0.0;\n    gfloat e = (gfloat) sizeof (buf) / (gfloat) 256.0;\n    guint i;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started determining if device '%s' seems to be encrypted\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    fd = open (device, O_RDONLY);\n    if (fd == -1) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, \"Failed to open device\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (read (fd, buf, sizeof (buf)) != sizeof (buf)) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, \"Failed to read device\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        close (fd);\n        return FALSE;\n    }\n\n    close (fd);\n\n    /* Calculate Chi Square */\n    for (i = 0; i < sizeof (buf); i++)\n        /* This is safe because the max value of buf[i] is < sizeof (symbols). */\n        symbols[buf[i]]++;\n    for (i = 0; i < 256; i++)\n        chi_square += (symbols[i] - e) * (symbols[i] - e);\n    chi_square /= e;\n\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return SQUARE_LOWER_LIMIT < chi_square && chi_square < SQUARE_UPPER_LIMIT;\n}\n\n/**\n * bd_crypto_tc_open:\n * @device: the device to open\n * @name: name for the TrueCrypt/VeraCrypt device\n * @context: (nullable): passphrase key slot context for this TrueCrypt/VeraCrypt volume\n * @read_only: whether to open as read-only or not (meaning read-write)\n * @keyfiles: (nullable) (array zero-terminated=1): paths to the keyfiles for the TrueCrypt/VeraCrypt volume\n * @hidden: whether a hidden volume inside the volume should be opened\n * @system: whether to try opening as an encrypted system (with boot loader)\n * @veracrypt: whether to try VeraCrypt modes (TrueCrypt modes are tried anyway)\n * @veracrypt_pim: VeraCrypt PIM value (only used if @veracrypt is %TRUE)\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase\n *\n * Returns: whether the @device was successfully opened or not\n *\n * Tech category: %BD_CRYPTO_TECH_TRUECRYPT-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_tc_open (const gchar *device, const gchar *name, BDCryptoKeyslotContext *context, const gchar **keyfiles, gboolean hidden, gboolean system, gboolean veracrypt, guint32 veracrypt_pim, gboolean read_only, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    struct crypt_params_tcrypt params = ZERO_INIT;\n    gsize keyfiles_count = 0;\n    guint i;\n    GError *l_error = NULL;\n\n    if (!_is_dm_name_valid (name, error))\n        return FALSE;\n\n    msg = g_strdup_printf (\"Started opening '%s' TrueCrypt/VeraCrypt device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    if (keyfiles) {\n        for (i=0; *(keyfiles + i); i++);\n        keyfiles_count = i;\n    }\n\n    if (context && context->type != BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' context type is valid for TC open.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if ((context == NULL) && (keyfiles_count == 0)) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_NO_KEY,\n                     \"No passphrase nor key file specified, cannot open.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    params.passphrase = context ? (const char*) context->u.passphrase.pass_data : NULL;\n    params.passphrase_size = context ? context->u.passphrase.data_len : 0;\n    params.keyfiles = keyfiles;\n    params.keyfiles_count = keyfiles_count;\n\n    if (veracrypt)\n        params.flags |= CRYPT_TCRYPT_VERA_MODES;\n    if (hidden)\n        params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;\n    if (system)\n        params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;\n    if (veracrypt && veracrypt_pim != 0)\n        params.veracrypt_pim = veracrypt_pim;\n\n    ret = crypt_load (cd, CRYPT_TCRYPT, &params);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_activate_by_volume_key (cd, name, NULL, 0,\n                                        read_only ? CRYPT_ACTIVATE_READONLY : 0);\n\n    if (ret < 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to activate device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_tc_close:\n * @tc_device: TrueCrypt/VeraCrypt device to close\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @tc_device was successfully closed or not\n *\n * Tech category: %BD_CRYPTO_TECH_TRUECRYPT-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_tc_close (const gchar *tc_device, GError **error) {\n    return _crypto_close (tc_device, \"TrueCrypt/VeraCrypt\", error);\n}\n\n#ifdef WITH_BD_ESCROW\nstatic gchar *always_fail_cb (gpointer data G_GNUC_UNUSED, const gchar *prompt G_GNUC_UNUSED, int echo G_GNUC_UNUSED) {\n    return NULL;\n}\n\nstatic gchar *give_passphrase_cb (gpointer data, const gchar *prompt G_GNUC_UNUSED, unsigned failed_attempts) {\n    if (failed_attempts == 0)\n        /* Return a copy of the passphrase that will be freed by volume_key */\n        return g_strdup (data);\n    return NULL;\n}\n\nstatic void free_passphrase_cb (gpointer data) {\n    g_free (data);\n}\n\n/**\n * replace_char:\n *\n * Replaces all occurrences of @orig in @str with @new (in place).\n */\nstatic gchar *replace_char (gchar *str, gchar orig, gchar new) {\n    gchar *pos = str;\n    if (!str)\n        return str;\n\n    for (pos=str; *pos; pos++)\n        *pos = *pos == orig ? new : *pos;\n\n    return str;\n}\n\nstatic gboolean write_escrow_data_file (struct libvk_volume *volume, struct libvk_ui *ui, enum libvk_secret secret_type, const gchar *out_path,\n                                        CERTCertificate *cert, GError **error) {\n    gpointer packet_data = NULL;\n    gsize packet_data_size = 0;\n    GIOChannel *out_file = NULL;\n    GIOStatus status = G_IO_STATUS_ERROR;\n    gsize bytes_written = 0;\n    GError *l_error = NULL;\n\n    packet_data = libvk_volume_create_packet_asymmetric_with_format (volume, &packet_data_size, secret_type, cert,\n                                                                     ui, LIBVK_PACKET_FORMAT_ASYMMETRIC_WRAP_SECRET_ONLY, &l_error);\n    if (!packet_data) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_ESCROW_FAILED,\n                     \"Failed to get escrow data: %s\", l_error->message);\n        g_clear_error (&l_error);\n        return FALSE;\n    }\n\n    out_file = g_io_channel_new_file (out_path, \"w\", error);\n    if (!out_file) {\n        /* error is already populated */\n        g_free (packet_data);\n        return FALSE;\n    }\n\n    status = g_io_channel_set_encoding (out_file, NULL, error);\n    if (status != G_IO_STATUS_NORMAL) {\n        g_free (packet_data);\n\n        /* try to shutdown the channel, but if it fails, we cannot do anything about it here */\n        g_io_channel_shutdown (out_file, TRUE, NULL);\n\n        /* error is already populated */\n        g_io_channel_unref (out_file);\n        return FALSE;\n    }\n\n    status = g_io_channel_write_chars (out_file, (const gchar *) packet_data, (gssize) packet_data_size,\n                                       &bytes_written, error);\n    g_free (packet_data);\n    if (status != G_IO_STATUS_NORMAL) {\n        /* try to shutdown the channel, but if it fails, we cannot do anything about it here */\n        g_io_channel_shutdown (out_file, TRUE, NULL);\n\n        /* error is already populated */\n        g_io_channel_unref (out_file);\n        return FALSE;\n    }\n\n    if (g_io_channel_shutdown (out_file, TRUE, error) != G_IO_STATUS_NORMAL) {\n        /* error is already populated */\n        g_io_channel_unref (out_file);\n        return FALSE;\n    }\n    g_io_channel_unref (out_file);\n\n    return TRUE;\n}\n#endif /* WITH_BD_ESCROW */\n\n/**\n * bd_crypto_escrow_device:\n * @device: path of the device to create escrow data for\n * @passphrase: passphrase used for the device\n * @cert_data: (array zero-terminated=1) (element-type gchar): certificate data to use for escrow\n * @directory: directory to put escrow data into\n * @backup_passphrase: (nullable): backup passphrase for the device or %NULL\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the escrow data was successfully created for @device or not\n *\n * Tech category: %BD_CRYPTO_TECH_ESCROW-%BD_CRYPTO_TECH_MODE_CREATE\n */\n#ifndef WITH_BD_ESCROW\ngboolean bd_crypto_escrow_device (const gchar *device G_GNUC_UNUSED, const gchar *passphrase G_GNUC_UNUSED,const gchar *cert_data G_GNUC_UNUSED,\n                                  const gchar *directory G_GNUC_UNUSED, const gchar *backup_passphrase G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because escrow technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_ESCROW, BD_CRYPTO_TECH_MODE_CREATE, error);\n}\n#else\ngboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, const gchar *cert_data, const gchar *directory, const gchar *backup_passphrase, GError **error) {\n    struct libvk_volume *volume = NULL;\n    struct libvk_ui *ui = NULL;\n    gchar *label = NULL;\n    gchar *uuid = NULL;\n    CERTCertificate *cert = NULL;\n    gchar *volume_ident = NULL;\n    gchar *out_path = NULL;\n    gboolean ret = FALSE;\n    gchar *passphrase_copy = NULL;\n    gchar *cert_data_copy = NULL;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n\n    msg = g_strdup_printf (\"Started creating escrow data for the LUKS device '%s'\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    if (!NSS_IsInitialized ())\n        if (NSS_NoDB_Init (NULL) != SECSuccess) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_NSS_INIT_FAILED,\n                         \"Failed to initialize NSS\");\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n\n    volume = libvk_volume_open (device, &l_error);\n    if (!volume) {\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ui = libvk_ui_new ();\n    /* not supposed to be called -> always fail */\n    libvk_ui_set_generic_cb (ui, always_fail_cb, NULL, NULL);\n\n    /* Create a copy of the passphrase to be used by the passphrase callback.\n     * The passphrase will be freed by volume_key via the free callback.\n     */\n    passphrase_copy = g_strdup (passphrase);\n    libvk_ui_set_passphrase_cb (ui, give_passphrase_cb, passphrase_copy, free_passphrase_cb);\n\n    if (libvk_volume_get_secret (volume, LIBVK_SECRET_DEFAULT, ui, &l_error) != 0) {\n        /* error is already populated */\n        libvk_volume_free (volume);\n        libvk_ui_free (ui);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    cert_data_copy = g_strdup (cert_data);\n    cert = CERT_DecodeCertFromPackage (cert_data_copy, strlen (cert_data_copy));\n    if (!cert) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_CERT_DECODE,\n                     \"Failed to decode the certificate data\");\n        libvk_volume_free (volume);\n        libvk_ui_free (ui);\n        g_free (cert_data_copy);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    label = libvk_volume_get_label (volume);\n    replace_char (label, '/', '_');\n    uuid = libvk_volume_get_uuid (volume);\n    replace_char (uuid, '/', '_');\n\n    if (label && uuid) {\n        volume_ident = g_strdup_printf (\"%s-%s\", label, uuid);\n        g_free (label);\n        g_free (uuid);\n    } else if (uuid)\n        volume_ident = uuid;\n    else\n        volume_ident = g_strdup (\"_unknown\");\n\n    out_path = g_strdup_printf (\"%s/%s-escrow\", directory, volume_ident);\n    ret = write_escrow_data_file (volume, ui, LIBVK_SECRET_DEFAULT, out_path, cert, &l_error);\n    g_free (out_path);\n\n    if (!ret) {\n        CERT_DestroyCertificate (cert);\n        libvk_volume_free (volume);\n        libvk_ui_free (ui);\n        g_free (volume_ident);\n        g_free (cert_data_copy);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (backup_passphrase) {\n        if (libvk_volume_add_secret (volume, LIBVK_SECRET_PASSPHRASE, backup_passphrase, strlen (backup_passphrase), &l_error) != 0) {\n            /* error is already populated */\n            CERT_DestroyCertificate (cert);\n            libvk_volume_free (volume);\n            libvk_ui_free (ui);\n            g_free (volume_ident);\n            g_free (cert_data_copy);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n\n        out_path = g_strdup_printf (\"%s/%s-escrow-backup-passphrase\", directory, volume_ident);\n        ret = write_escrow_data_file (volume, ui, LIBVK_SECRET_PASSPHRASE, out_path, cert, &l_error);\n        g_free (out_path);\n\n        if (!ret) {\n            CERT_DestroyCertificate (cert);\n            libvk_volume_free (volume);\n            libvk_ui_free (ui);\n            g_free (volume_ident);\n            g_free (cert_data_copy);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    }\n\n    CERT_DestroyCertificate (cert);\n    libvk_volume_free (volume);\n    libvk_ui_free (ui);\n    g_free (volume_ident);\n    g_free (cert_data_copy);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return ret;\n}\n#endif /* WITH_BD_ESCROW */\n\n/**\n * bd_crypto_bitlk_open:\n * @device: the device to open\n * @name: name for the BITLK device\n * @context: key slot context (passphrase/keyfile/token...) for this BITLK device\n * @read_only: whether to open as read-only or not (meaning read-write)\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the @device was successfully opened or not\n *\n * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_bitlk_open (const gchar *device, const gchar *name, BDCryptoKeyslotContext *context, gboolean read_only, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n    gchar *key_buffer = NULL;\n    gsize buf_len = 0;\n\n    if (!_is_dm_name_valid (name, error))\n        return FALSE;\n\n    msg = g_strdup_printf (\"Started opening '%s' BITLK device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_BITLK, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT,\n                                            (const char *) context->u.passphrase.pass_data,\n                                            context->u.passphrase.data_len,\n                                            read_only ? CRYPT_ACTIVATE_READONLY : 0);\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buffer, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile, strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT, key_buffer, buf_len,\n                                            read_only ? CRYPT_ACTIVATE_READONLY : 0);\n        crypt_safe_free (key_buffer);\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for BITLK open.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (ret < 0) {\n        if (ret == -EPERM)\n          g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                       \"Failed to activate device: Incorrect passphrase.\");\n        else\n          g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                       \"Failed to activate device: %s\", strerror_l (-ret, c_locale));\n\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n\n/**\n * bd_crypto_bitlk_close:\n * @bitlk_device: BITLK device to close\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @bitlk_device was successfully closed or not\n *\n * Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\ngboolean bd_crypto_bitlk_close (const gchar *bitlk_device, GError **error) {\n    return _crypto_close (bitlk_device, \"BITLK\", error);\n}\n\n/**\n * bd_crypto_fvault2_open:\n * @device: the device to open\n * @name: name for the FVAULT2 device\n * @context: key slot context (passphrase/keyfile/token...) for this FVAULT2 volume\n * @read_only: whether to open as read-only or not (meaning read-write)\n * @error: (out) (optional): place to store error (if any)\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Returns: whether the @device was successfully opened or not\n *\n * Tech category: %BD_CRYPTO_TECH_FVAULT2-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\n#ifndef LIBCRYPTSETUP_26\ngboolean bd_crypto_fvault2_open (const gchar *device G_GNUC_UNUSED, const gchar *name G_GNUC_UNUSED, BDCryptoKeyslotContext *context G_GNUC_UNUSED,\n                                 gboolean read_only G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because FVAULT2 technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_FVAULT2, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error);\n#else\ngboolean bd_crypto_fvault2_open (const gchar *device, const gchar *name, BDCryptoKeyslotContext *context, gboolean read_only, GError **error) {\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    gchar *msg = NULL;\n    GError *l_error = NULL;\n    gchar *key_buffer = NULL;\n    gsize buf_len = 0;\n\n    if (!_is_dm_name_valid (name, error))\n        return FALSE;\n\n    msg = g_strdup_printf (\"Started opening '%s' FVAULT2 device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_FVAULT2, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT,\n                                            (const char *) context->u.passphrase.pass_data,\n                                            context->u.passphrase.data_len,\n                                            read_only ? CRYPT_ACTIVATE_READONLY : 0);\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buffer, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile, strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n        ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT, key_buffer, buf_len,\n                                            read_only ? CRYPT_ACTIVATE_READONLY : 0);\n        crypt_safe_free (key_buffer);\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for FVAULT2 open.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (ret < 0) {\n        if (ret == -EPERM)\n          g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                       \"Failed to activate device: Incorrect passphrase.\");\n        else\n          g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                       \"Failed to activate device: %s\", strerror_l (-ret, c_locale));\n\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n#endif\n}\n\n/**\n * bd_crypto_fvault2_close:\n * @fvault2_device: FVAULT2 device to close\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether the given @fvault2_device was successfully closed or not\n *\n * Tech category: %BD_CRYPTO_TECH_FVAULT2-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE\n */\n#ifndef LIBCRYPTSETUP_26\ngboolean bd_crypto_fvault2_close (const gchar *fvault2_device G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because FVAULT2 technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_FVAULT2, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error);\n}\n#else\ngboolean bd_crypto_fvault2_close (const gchar *fvault2_device, GError **error) {\n    return _crypto_close (fvault2_device, \"FVAULT2\", error);\n}\n#endif\n\n/**\n * bd_crypto_opal_is_supported:\n * @device: device to check for OPAL support\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: %TRUE if the given @device supports OPAL or %FALSE if not or\n * failed to determine (the @error is populated with the error in such\n * cases).\n *\n * Tech category: %BD_CRYPTO_TECH_SED_OPAL-%BD_CRYPTO_TECH_MODE_QUERY\n */\n#if !defined(HAVE_LINUX_OPAL) || !defined(IOC_OPAL_GET_STATUS)\ngboolean bd_crypto_opal_is_supported (const gchar *device G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because OPAL technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_SED_OPAL, BD_CRYPTO_TECH_MODE_QUERY, error);\n}\n#else\ngboolean bd_crypto_opal_is_supported (const gchar *device, GError **error) {\n    gint fd = -1;\n    gint ret = 0;\n    struct opal_status st = ZERO_INIT;\n\n    fd = open (device, O_RDONLY|O_CLOEXEC);\n    if (fd == -1) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to open the device '%s'\", device);\n        return FALSE;\n    }\n\n    ret = ioctl (fd, IOC_OPAL_GET_STATUS, &st);\n    if (ret < 0) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to get opal status for the device '%s': %s\",\n                     device,\n                     strerror_l (-ret, c_locale));\n        close (fd);\n        return FALSE;\n    }\n\n    close (fd);\n\n    if (st.flags & (OPAL_FL_SUPPORTED|OPAL_FL_LOCKING_SUPPORTED|OPAL_FL_LOCKING_ENABLED))\n        return TRUE;\n    else\n        return FALSE;\n}\n#endif\n\n/**\n * bd_crypto_opal_wipe_device:\n * @device: LUKS HW-OPAL device to wipe\n * @context: OPAL admin passphrase context\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether @device was successfully wiped or not.\n *\n * Supported @context types for this function: passphrase\n *\n * Tech category: %BD_CRYPTO_TECH_SED_OPAL-%BD_CRYPTO_TECH_MODE_MODIFY\n */\n#ifndef LIBCRYPTSETUP_27\ngboolean bd_crypto_opal_wipe_device (const gchar *device G_GNUC_UNUSED, BDCryptoKeyslotContext *context G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because OPAL technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_SED_OPAL, BD_CRYPTO_TECH_MODE_QUERY, error);\n}\n#else\ngboolean bd_crypto_opal_wipe_device (const gchar *device, BDCryptoKeyslotContext *context, GError **error) {\n    gchar *key_buf = NULL;\n    gsize buf_len = 0;\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    GError *l_error = NULL;\n    gchar *msg = NULL;\n\n    msg = g_strdup_printf (\"Started wiping '%s' LUKS HW-OPAL device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_load (cd, CRYPT_LUKS, NULL);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to load device's parameters: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_get_hw_encryption_type (cd);\n    if (ret != CRYPT_OPAL_HW_ONLY && ret != CRYPT_SW_AND_OPAL_HW) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Device %s isn't a LUKS HW-OPAL device.\", device);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        key_buf = (char *) context->u.passphrase.pass_data;\n        buf_len = context->u.passphrase.data_len;\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' context type is valid for OPAL wipe.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_wipe_hw_opal (cd, CRYPT_LUKS2_SEGMENT, key_buf, buf_len, 0);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to wipe LUKS HW-OPAL device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n#endif\n\n/**\n * bd_crypto_opal_format:\n * @device: a device to format as LUKS HW-OPAL\n * @cipher: (nullable): cipher specification (type-mode, e.g. \"aes-xts-plain64\") or %NULL to use the default\n * @key_size: size of the volume key in bits or 0 to use the default\n * @context: key slot context (passphrase/keyfile/token...) for this LUKS device\n * @min_entropy: minimum random data entropy (in bits) required to format @device as LUKS\n * @hw_encryption: type of hardware encryption (SW+HW or HW only)\n * @opal_context: OPAL admin passphrase\n * @extra: (nullable): extra arguments for LUKS format creation\n * @error: (out) (optional): place to store error (if any)\n *\n * Formats the given @device as LUKS HW-OPAL according to the other parameters given. If\n * @min_entropy is specified (greater than 0), the function waits for enough\n * entropy to be available in the random data pool (WHICH MAY POTENTIALLY TAKE\n * FOREVER).\n *\n * Supported @context types for this function: passphrase, key file\n * Supported @opal_context types for this function: passphrase\n *\n * Returns: whether the given @device was successfully formatted as LUKS HW-OPAL or not\n * (the @error contains the error in such cases)\n *\n * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_CREATE\n */\n#ifndef LIBCRYPTSETUP_27\ngboolean bd_crypto_opal_format (const gchar *device G_GNUC_UNUSED, const gchar *cipher G_GNUC_UNUSED, guint64 key_size G_GNUC_UNUSED, BDCryptoKeyslotContext *context G_GNUC_UNUSED,\n                                guint64 min_entropy G_GNUC_UNUSED, BDCryptoLUKSHWEncryptionType hw_encryption G_GNUC_UNUSED,\n                                BDCryptoKeyslotContext *opal_context G_GNUC_UNUSED, BDCryptoLUKSExtra *extra G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because OPAL technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_SED_OPAL, BD_CRYPTO_TECH_MODE_CREATE, error);\n}\n#else\ngboolean bd_crypto_opal_format (const gchar *device, const gchar *cipher, guint64 key_size, BDCryptoKeyslotContext *context, guint64 min_entropy, BDCryptoLUKSHWEncryptionType hw_encryption,\n                                BDCryptoKeyslotContext *opal_context, BDCryptoLUKSExtra *extra, GError **error) {\n\n    gboolean ret = FALSE;\n\n    if (hw_encryption != BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_AND_SW && hw_encryption != BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_ONLY) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                     \"Either hardware and software encryption or hardware encryption only must be selected for OPAL format\");\n        return FALSE;\n    }\n\n    if (hw_encryption == BD_CRYPTO_LUKS_HW_ENCRYPTION_OPAL_HW_ONLY && cipher != NULL) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                     \"Cipher cannot be specified for hardware encryption only OPAL devices\");\n        return FALSE;\n    }\n\n    ret = bd_crypto_opal_is_supported (device, NULL);\n    if (!ret) {\n        g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED,\n                     \"OPAL doesn't seem to be supported on %s\", device);\n        return FALSE;\n    }\n\n    return _crypto_luks_format (device, cipher, key_size, context, min_entropy, BD_CRYPTO_LUKS_VERSION_LUKS2, extra, hw_encryption, opal_context, error);\n}\n#endif\n\n/**\n * bd_crypto_opal_reset_device:\n * @device: LUKS HW-OPAL device to run PSID reset on\n * @context: PSID context\n * @error: (out) (optional): place to store error (if any)\n *\n * Returns: whether PSI reset on @device was successful or not.\n *\n * Warning: PSID reset will remove all data from @device!\n *\n * Supported @context types for this function: passphrase, key file\n *\n * Tech category: %BD_CRYPTO_TECH_SED_OPAL-%BD_CRYPTO_TECH_MODE_MODIFY\n */\n#ifndef LIBCRYPTSETUP_27\ngboolean bd_crypto_opal_reset_device (const gchar *device G_GNUC_UNUSED, BDCryptoKeyslotContext *context G_GNUC_UNUSED, GError **error) {\n    /* this will return FALSE and set error, because OPAL technology is not available */\n    return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_SED_OPAL, BD_CRYPTO_TECH_MODE_QUERY, error);\n}\n#else\ngboolean bd_crypto_opal_reset_device (const gchar *device, BDCryptoKeyslotContext *context, GError **error) {\n    gchar *key_buf = NULL;\n    gsize buf_len = 0;\n    struct crypt_device *cd = NULL;\n    gint ret = 0;\n    guint64 progress_id = 0;\n    GError *l_error = NULL;\n    gchar *msg = NULL;\n\n    msg = g_strdup_printf (\"Started PSID reset on '%s' LUKS HW-OPAL device\", device);\n    progress_id = bd_utils_report_started (msg);\n    g_free (msg);\n\n    if (!bd_crypto_opal_is_supported (device, &l_error)) {\n        g_prefix_error (&l_error, \"OPAL doesn't seem to be supported on %s: \", device);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    ret = crypt_init (&cd, device);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to initialize device: %s\", strerror_l (-ret, c_locale));\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) {\n        key_buf = (char *) context->u.passphrase.pass_data;\n        buf_len = context->u.passphrase.data_len;\n    } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_KEYFILE) {\n        ret = crypt_keyfile_device_read (cd, context->u.keyfile.keyfile, &key_buf, &buf_len,\n                                         context->u.keyfile.keyfile_offset, context->u.keyfile.key_size, 0);\n        if (ret != 0) {\n            g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_KEYFILE_FAILED,\n                         \"Failed to read key from file '%s': %s\", context->u.keyfile.keyfile,\n                         strerror_l (-ret, c_locale));\n            crypt_free (cd);\n            bd_utils_report_finished (progress_id, l_error->message);\n            g_propagate_error (error, l_error);\n            return FALSE;\n        }\n    } else {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_INVALID_CONTEXT,\n                     \"Only 'passphrase' and 'key file' context types are valid for OPAL PSID reset.\");\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        crypt_free (cd);\n        return FALSE;\n    }\n\n    ret = crypt_wipe_hw_opal (cd, CRYPT_NO_SEGMENT, key_buf, buf_len, 0);\n    if (ret != 0) {\n        g_set_error (&l_error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE,\n                     \"Failed to wipe LUKS HW-OPAL device: %s\", strerror_l (-ret, c_locale));\n        crypt_free (cd);\n        bd_utils_report_finished (progress_id, l_error->message);\n        g_propagate_error (error, l_error);\n        return FALSE;\n    }\n\n    crypt_free (cd);\n    bd_utils_report_finished (progress_id, \"Completed\");\n    return TRUE;\n}\n#endif\n"},
                          "roles": ["analysisTarget",
                                    "tracedFile"]},
                         {"location": {"uri": "/usr/include/glib-2.0/glib/gstrfuncs.h"},
                          "sourceLanguage": "c",
                          "contents": {"text": "/* GLIB - Library of useful routines for C programming\n * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald\n *\n * SPDX-License-Identifier: LGPL-2.1-or-later\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, see <http://www.gnu.org/licenses/>.\n */\n\n/*\n * Modified by the GLib Team and others 1997-2000.  See the AUTHORS\n * file for a list of people on the GLib Team.  See the ChangeLog\n * files for a list of changes.  These files are distributed with\n * GLib at ftp://ftp.gtk.org/pub/gtk/.\n */\n\n#ifndef __G_STRFUNCS_H__\n#define __G_STRFUNCS_H__\n\n#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)\n#error \"Only <glib.h> can be included directly.\"\n#endif\n\n#include <stdarg.h>\n#include <string.h>\n\n#include <glib/gmacros.h>\n#include <glib/gtypes.h>\n#include <glib/gerror.h>\n#include <glib/gmem.h>\n\nG_BEGIN_DECLS\n\n/* Functions like the ones in <ctype.h> that are not affected by locale. */\ntypedef enum {\n  G_ASCII_ALNUM  = 1 << 0,\n  G_ASCII_ALPHA  = 1 << 1,\n  G_ASCII_CNTRL  = 1 << 2,\n  G_ASCII_DIGIT  = 1 << 3,\n  G_ASCII_GRAPH  = 1 << 4,\n  G_ASCII_LOWER  = 1 << 5,\n  G_ASCII_PRINT  = 1 << 6,\n  G_ASCII_PUNCT  = 1 << 7,\n  G_ASCII_SPACE  = 1 << 8,\n  G_ASCII_UPPER  = 1 << 9,\n  G_ASCII_XDIGIT = 1 << 10\n} G_GNUC_FLAG_ENUM GAsciiType;\n\nGLIB_VAR const guint16 * const g_ascii_table;\n\n#define g_ascii_isalnum(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0)\n\n#define g_ascii_isalpha(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_ALPHA) != 0)\n\n#define g_ascii_iscntrl(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_CNTRL) != 0)\n\n#define g_ascii_isdigit(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_DIGIT) != 0)\n\n#define g_ascii_isgraph(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_GRAPH) != 0)\n\n#define g_ascii_islower(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_LOWER) != 0)\n\n#define g_ascii_isprint(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_PRINT) != 0)\n\n#define g_ascii_ispunct(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_PUNCT) != 0)\n\n#define g_ascii_isspace(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0)\n\n#define g_ascii_isupper(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_UPPER) != 0)\n\n#define g_ascii_isxdigit(c) \\\n  ((g_ascii_table[(guchar) (c)] & G_ASCII_XDIGIT) != 0)\n\nGLIB_AVAILABLE_IN_ALL\ngchar                 g_ascii_tolower  (gchar        c) G_GNUC_CONST;\nGLIB_AVAILABLE_IN_ALL\ngchar                 g_ascii_toupper  (gchar        c) G_GNUC_CONST;\n\nGLIB_AVAILABLE_IN_ALL\ngint                  g_ascii_digit_value  (gchar    c) G_GNUC_CONST;\nGLIB_AVAILABLE_IN_ALL\ngint                  g_ascii_xdigit_value (gchar    c) G_GNUC_CONST;\n\n/* String utility functions that modify a string argument or\n * return a constant string that must not be freed.\n */\n#define\t G_STR_DELIMITERS\t\"_-|> <.\"\nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strdelimit     (gchar\t     *string,\n\t\t\t\t\tconst gchar  *delimiters,\n\t\t\t\t\tgchar\t      new_delimiter);\nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strcanon       (gchar        *string,\n\t\t\t\t\tconst gchar  *valid_chars,\n\t\t\t\t\tgchar         substitutor);\nGLIB_AVAILABLE_IN_ALL\nconst gchar *         g_strerror       (gint\t      errnum) G_GNUC_CONST;\nGLIB_AVAILABLE_IN_ALL\nconst gchar *         g_strsignal      (gint\t      signum) G_GNUC_CONST;\nGLIB_AVAILABLE_IN_ALL\ngchar *\t              g_strreverse     (gchar\t     *string);\nGLIB_AVAILABLE_IN_ALL\ngsize\t              g_strlcpy\t       (gchar\t     *dest,\n\t\t\t\t\tconst gchar  *src,\n\t\t\t\t\tgsize         dest_size);\nGLIB_AVAILABLE_IN_ALL\ngsize\t              g_strlcat        (gchar\t     *dest,\n\t\t\t\t\tconst gchar  *src,\n\t\t\t\t\tgsize         dest_size);\nGLIB_AVAILABLE_IN_ALL\ngchar *               g_strstr_len     (const gchar  *haystack,\n\t\t\t\t\tgssize        haystack_len,\n\t\t\t\t\tconst gchar  *needle);\nGLIB_AVAILABLE_IN_ALL\ngchar *               g_strrstr        (const gchar  *haystack,\n\t\t\t\t\tconst gchar  *needle);\nGLIB_AVAILABLE_IN_ALL\ngchar *               g_strrstr_len    (const gchar  *haystack,\n\t\t\t\t\tgssize        haystack_len,\n\t\t\t\t\tconst gchar  *needle);\n\nGLIB_AVAILABLE_IN_ALL\ngboolean             (g_str_has_suffix) (const gchar *str,\n                                         const gchar *suffix);\nGLIB_AVAILABLE_IN_ALL\ngboolean             (g_str_has_prefix) (const gchar *str,\n                                         const gchar *prefix);\n\n#if G_GNUC_CHECK_VERSION (2, 0)\n#ifndef __GTK_DOC_IGNORE__\n#ifndef __GI_SCANNER__\n\n/* This macro is defeat a false -Wnonnull warning in GCC.\n * Without it, it thinks strlen and memcmp may be getting passed NULL\n * despite the explicit check for NULL right above the calls.\n */\n#define _G_STR_NONNULL(x) ((x) + !(x))\n\n#define g_str_has_prefix(STR, PREFIX)                                         \\\n  (__builtin_constant_p (PREFIX)?                                             \\\n    G_GNUC_EXTENSION ({                                                       \\\n       const char * const _str = (STR);                                       \\\n       const char * const _prefix = (PREFIX);                                 \\\n       gboolean _result = FALSE;                                              \\\n                                                                              \\\n       if G_UNLIKELY (_str == NULL || _prefix == NULL)                        \\\n           _result = (g_str_has_prefix) (_str, _prefix);                      \\\n       else                                                                   \\\n         {                                                                    \\\n            const size_t _str_len = strlen (_G_STR_NONNULL (_str));           \\\n            const size_t _prefix_len = strlen (_G_STR_NONNULL (_prefix));     \\\n            if (_str_len >= _prefix_len)                                      \\\n              _result = memcmp (_G_STR_NONNULL (_str),                        \\\n                                 _G_STR_NONNULL (_prefix),                    \\\n                                 _prefix_len) == 0;                           \\\n         }                                                                    \\\n         _result;                                                             \\\n    })                                                                        \\\n  :                                                                           \\\n    (g_str_has_prefix) (STR, PREFIX)                                          \\\n  )\n\n#define g_str_has_suffix(STR, SUFFIX)                                         \\\n  (__builtin_constant_p (SUFFIX)?                                             \\\n    G_GNUC_EXTENSION ({                                                       \\\n       const char * const _str = (STR);                                       \\\n       const char * const _suffix = (SUFFIX);                                 \\\n       gboolean _result = FALSE;                                              \\\n                                                                              \\\n       if G_UNLIKELY (_str == NULL || _suffix == NULL)                        \\\n         _result = (g_str_has_suffix) (_str, _suffix);                        \\\n       else                                                                   \\\n         {                                                                    \\\n            const size_t _str_len = strlen (_G_STR_NONNULL (_str));           \\\n            const size_t _suffix_len = strlen (_G_STR_NONNULL (_suffix));     \\\n            if (_str_len >= _suffix_len)                                      \\\n              _result = memcmp (_str + _str_len - _suffix_len,                \\\n                                 _G_STR_NONNULL (_suffix),                    \\\n                                 _suffix_len) == 0;                           \\\n         }                                                                    \\\n         _result;                                                             \\\n    })                                                                        \\\n  :                                                                           \\\n    (g_str_has_suffix) (STR, SUFFIX)                                          \\\n  )\n\n#endif /* !defined (__GI_SCANNER__) */\n#endif /* !defined (__GTK_DOC_IGNORE__) */\n#endif /* G_GNUC_CHECK_VERSION (2, 0) */\n\n/* String to/from double conversion functions */\n\nGLIB_AVAILABLE_IN_ALL\ngdouble\t              g_strtod         (const gchar  *nptr,\n\t\t\t\t\tgchar\t    **endptr);\nGLIB_AVAILABLE_IN_ALL\ngdouble\t              g_ascii_strtod   (const gchar  *nptr,\n\t\t\t\t\tgchar\t    **endptr);\nGLIB_AVAILABLE_IN_ALL\nguint64\t\t      g_ascii_strtoull (const gchar *nptr,\n\t\t\t\t\tgchar      **endptr,\n\t\t\t\t\tguint        base);\nGLIB_AVAILABLE_IN_ALL\ngint64\t\t      g_ascii_strtoll  (const gchar *nptr,\n\t\t\t\t\tgchar      **endptr,\n\t\t\t\t\tguint        base);\n/* 29 bytes should enough for all possible values that\n * g_ascii_dtostr can produce.\n * Then add 10 for good measure */\n#define G_ASCII_DTOSTR_BUF_SIZE (29 + 10)\nGLIB_AVAILABLE_IN_ALL\ngchar *               g_ascii_dtostr   (gchar        *buffer,\n\t\t\t\t\tgint          buf_len,\n\t\t\t\t\tgdouble       d);\nGLIB_AVAILABLE_IN_ALL\ngchar *               g_ascii_formatd  (gchar        *buffer,\n\t\t\t\t\tgint          buf_len,\n\t\t\t\t\tconst gchar  *format,\n\t\t\t\t\tgdouble       d);\n\n/* removes leading spaces */\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_strchug        (gchar        *string);\n/* removes trailing spaces */\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_strchomp       (gchar        *string);\n/* removes leading & trailing spaces */\n#define g_strstrip( string )\tg_strchomp (g_strchug (string))\n\nGLIB_AVAILABLE_IN_ALL\ngint                  g_ascii_strcasecmp  (const gchar *s1,\n\t\t\t\t\t   const gchar *s2);\nGLIB_AVAILABLE_IN_ALL\ngint                  g_ascii_strncasecmp (const gchar *s1,\n\t\t\t\t\t   const gchar *s2,\n\t\t\t\t\t   gsize        n);\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_ascii_strdown     (const gchar *str,\n\t\t\t\t\t   gssize       len) G_GNUC_MALLOC;\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_ascii_strup       (const gchar *str,\n\t\t\t\t\t   gssize       len) G_GNUC_MALLOC;\n\nGLIB_AVAILABLE_IN_2_40\ngboolean              g_str_is_ascii      (const gchar *str);\n\nGLIB_DEPRECATED\ngint                  g_strcasecmp     (const gchar *s1,\n                                        const gchar *s2);\nGLIB_DEPRECATED\ngint                  g_strncasecmp    (const gchar *s1,\n                                        const gchar *s2,\n                                        guint        n);\nGLIB_DEPRECATED\ngchar*                g_strdown        (gchar       *string);\nGLIB_DEPRECATED\ngchar*                g_strup          (gchar       *string);\n\n\n/* String utility functions that return a newly allocated string which\n * ought to be freed with g_free from the caller at some point.\n */\nGLIB_AVAILABLE_IN_ALL\ngchar*\t             (g_strdup)        (const gchar *str) G_GNUC_MALLOC;\nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strdup_printf  (const gchar *format,\n\t\t\t\t\t...) G_GNUC_PRINTF (1, 2) G_GNUC_MALLOC;\nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strdup_vprintf (const gchar *format,\n\t\t\t\t\tva_list      args) G_GNUC_PRINTF(1, 0) G_GNUC_MALLOC;\nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strndup\t       (const gchar *str,\n\t\t\t\t\tgsize        n) G_GNUC_MALLOC;  \nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strnfill       (gsize        length,  \n\t\t\t\t\tgchar        fill_char) G_GNUC_MALLOC;\nGLIB_AVAILABLE_IN_ALL\ngchar*\t              g_strconcat      (const gchar *string1,\n\t\t\t\t\t...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_strjoin\t       (const gchar  *separator,\n\t\t\t\t\t...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;\n\n#if G_GNUC_CHECK_VERSION(2, 0)\n#ifndef __GTK_DOC_IGNORE__\n#ifndef __GI_SCANNER__\n\nG_ALWAYS_INLINE static inline char *\ng_strdup_inline (const char *str)\n{\n  if (__builtin_constant_p (!str) && !str)\n    return NULL;\n\n  if (__builtin_constant_p (!!str) && !!str && __builtin_constant_p (strlen (str)))\n    {\n      const size_t len = strlen (str) + 1;\n      char *dup_str = (char *) g_malloc (len);\n      return (char *) memcpy (dup_str, str, len);\n    }\n\n  return g_strdup (str);\n}\n\n#define g_strdup(x) g_strdup_inline (x)\n\n#endif /* !defined (__GI_SCANNER__) */\n#endif /* !defined (__GTK_DOC_IGNORE__) */\n#endif /* G_GNUC_CHECK_VERSION (2, 0) */\n\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_strcompress    (const gchar *source) G_GNUC_MALLOC;\n\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_strescape      (const gchar *source,\n\t\t\t\t\tconst gchar *exceptions) G_GNUC_MALLOC;\n\nGLIB_DEPRECATED_IN_2_68_FOR (g_memdup2)\ngpointer              g_memdup         (gconstpointer mem,\n                                        guint         byte_size) G_GNUC_ALLOC_SIZE(2);\n\nGLIB_AVAILABLE_IN_2_68\ngpointer              g_memdup2        (gconstpointer mem,\n                                        gsize         byte_size) G_GNUC_ALLOC_SIZE(2);\n\n/* NULL terminated string arrays.\n * g_strsplit(), g_strsplit_set() split up string into max_tokens tokens\n * at delim and return a newly allocated string array.\n * g_strjoinv() concatenates all of str_array's strings, sliding in an\n * optional separator, the returned string is newly allocated.\n * g_strfreev() frees the array itself and all of its strings.\n * g_strdupv() copies a NULL-terminated array of strings\n * g_strv_length() returns the length of a NULL-terminated array of strings\n */\ntypedef gchar** GStrv;\nGLIB_AVAILABLE_IN_ALL\ngchar**\t              g_strsplit       (const gchar  *string,\n\t\t\t\t\tconst gchar  *delimiter,\n\t\t\t\t\tgint          max_tokens);\nGLIB_AVAILABLE_IN_ALL\ngchar **\t      g_strsplit_set   (const gchar *string,\n\t\t\t\t\tconst gchar *delimiters,\n\t\t\t\t\tgint         max_tokens);\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_strjoinv       (const gchar  *separator,\n\t\t\t\t\tgchar       **str_array) G_GNUC_MALLOC;\nGLIB_AVAILABLE_IN_ALL\nvoid                  g_strfreev       (gchar       **str_array);\nGLIB_AVAILABLE_IN_ALL\ngchar**               g_strdupv        (gchar       **str_array);\nGLIB_AVAILABLE_IN_ALL\nguint                 g_strv_length    (gchar       **str_array);\n\nGLIB_AVAILABLE_IN_ALL\ngchar*                g_stpcpy         (gchar        *dest,\n                                        const char   *src);\n\nGLIB_AVAILABLE_IN_2_40\ngchar *                 g_str_to_ascii                                  (const gchar   *str,\n                                                                         const gchar   *from_locale);\n\nGLIB_AVAILABLE_IN_2_40\ngchar **                g_str_tokenize_and_fold                         (const gchar   *string,\n                                                                         const gchar   *translit_locale,\n                                                                         gchar       ***ascii_alternates);\n\nGLIB_AVAILABLE_IN_2_40\ngboolean                g_str_match_string                              (const gchar   *search_term,\n                                                                         const gchar   *potential_hit,\n                                                                         gboolean       accept_alternates);\n\nGLIB_AVAILABLE_IN_2_44\ngboolean              g_strv_contains  (const gchar * const *strv,\n                                        const gchar         *str);\n\nGLIB_AVAILABLE_IN_2_60\ngboolean              g_strv_equal     (const gchar * const *strv1,\n                                        const gchar * const *strv2);\n\n/* Convenience ASCII string to number API */\n\n/**\n * GNumberParserError:\n * @G_NUMBER_PARSER_ERROR_INVALID: string was not a valid number\n * @G_NUMBER_PARSER_ERROR_OUT_OF_BOUNDS: string was a number, but out of bounds\n *\n * Error codes returned by functions converting a string to a number.\n *\n * Since: 2.54\n */\ntypedef enum\n  {\n    G_NUMBER_PARSER_ERROR_INVALID,\n    G_NUMBER_PARSER_ERROR_OUT_OF_BOUNDS,\n  } GNumberParserError;\n\n/**\n * G_NUMBER_PARSER_ERROR:\n *\n * Domain for errors returned by functions converting a string to a\n * number.\n *\n * Since: 2.54\n */\n#define G_NUMBER_PARSER_ERROR (g_number_parser_error_quark ())\n\nGLIB_AVAILABLE_IN_2_54\nGQuark                g_number_parser_error_quark  (void);\n\nGLIB_AVAILABLE_IN_2_54\ngboolean              g_ascii_string_to_signed     (const gchar  *str,\n                                                    guint         base,\n                                                    gint64        min,\n                                                    gint64        max,\n                                                    gint64       *out_num,\n                                                    GError      **error);\n\nGLIB_AVAILABLE_IN_2_54\ngboolean              g_ascii_string_to_unsigned   (const gchar  *str,\n                                                    guint         base,\n                                                    guint64       min,\n                                                    guint64       max,\n                                                    guint64      *out_num,\n                                                    GError      **error);\n\n/**\n * g_set_str: (skip)\n * @str_pointer: (inout) (not optional) (nullable): a pointer to either\n *   a string or `NULL`\n * @new_str: (nullable): a string to assign to @str_pointer\n *\n * Updates a pointer to a string to a copy of @new_str and returns whether the\n * string was changed.\n *\n * If @new_str matches the previous string, this function is a no-op. If\n * @new_str is different, a copy of it will be assigned to @str_pointer and\n * the previous string pointed to by @str_pointer will be freed with\n * [func@GLib.free].\n *\n * @str_pointer must not be `NULL`, but can point to a `NULL` value.\n *\n * One convenient usage of this function is in implementing property settings:\n * ```C\n * void\n * foo_set_bar (Foo        *foo,\n *              const char *new_bar)\n * {\n *   g_return_if_fail (IS_FOO (foo));\n *\n *   if (g_set_str (&foo->bar, new_bar))\n *     g_object_notify (foo, \"bar\");\n * }\n * ```\n *\n * See also [func@GLib.set_str_take] for a version of this which steals\n * ownership of @new_str.\n *\n * Returns: true if the value of @str_pointer changed, false otherwise\n *\n * Since: 2.76\n */\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_76\nstatic inline gboolean g_set_str (char       **str_pointer,\n                                  const char  *new_str);\n\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_76\nstatic inline gboolean\ng_set_str (char       **str_pointer,\n           const char  *new_str)\n{\n  char *copy;\n\n  if (*str_pointer == new_str ||\n      (*str_pointer && new_str && strcmp (*str_pointer, new_str) == 0))\n    return FALSE;\n\n  copy = g_strdup (new_str);\n  g_free (*str_pointer);\n  *str_pointer = copy;\n\n  return TRUE;\n}\n\n/**\n * g_set_str_take: (skip)\n * @str_pointer: (inout) (not optional) (nullable): a pointer to either\n *   a string or `NULL`\n * @new_str: (transfer full) (nullable): a string to assign to @str_pointer\n *\n * Updates a pointer to a string to @new_str and returns whether the\n * string was changed. Steals ownership of @new_str.\n *\n * If @new_str matches the previous string, this function will free @new_str and\n * leave @str_pointer unchanged. If @new_str is different, it will be assigned\n * to @str_pointer and the previous string pointed to by @str_pointer will be\n * freed with [func@GLib.free].\n *\n * @str_pointer must not be `NULL`, but can point to a `NULL` value.\n *\n * One convenient usage of this function is in implementing property settings:\n * ```C\n * void\n * foo_set_bar (Foo        *foo,\n *              const char *new_bar)\n * {\n *   g_autofree computed_new_bar = NULL;\n *\n *   g_return_if_fail (IS_FOO (foo));\n *\n *   computed_new_bar = g_strconcat (new_bar, \"some-suffix\", NULL);\n *\n *   if (g_set_str_take (&foo->bar, g_steal_pointer (&computed_new_bar)))\n *     g_object_notify (foo, \"bar\");\n * }\n * ```\n *\n * See also [func@GLib.set_str] for a version of this which takes a copy of\n * @new_str.\n *\n * Returns: true if the value of @str_pointer changed, false otherwise\n *\n * Since: 2.90\n */\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_90\nstatic inline gboolean g_set_str_take (char **str_pointer,\n                                       char  *new_str);\n\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_90\nstatic inline gboolean\ng_set_str_take (char **str_pointer,\n                char  *new_str)\n{\n  /* You could pass the value of `*str_pointer` in to this function, but you\n   * really should do it using g_steal_pointer() to document the ownership\n   * transfer. */\n  if (*str_pointer == new_str)\n    return FALSE;\n\n  if (*str_pointer != NULL &&\n      new_str != NULL &&\n      strcmp (*str_pointer, new_str) == 0)\n    {\n      g_free (new_str);\n      return FALSE;\n    }\n\n  g_free (*str_pointer);\n  *str_pointer = new_str;\n  new_str = NULL;  /* stolen */\n\n  return TRUE;\n}\n\n/**\n * g_set_strv: (skip)\n * @strv_pointer: (inout) (not optional) (nullable): a pointer to either\n *   a `NULL`-terminated string array or `NULL`\n * @new_strv: (nullable): a NULL-terminated string array to assign to\n *   @strv_pointer\n *\n * Safely replaces a string vector.\n *\n * Updates a pointer to a `NULL`-terminated string array to a copy of @new_strv\n * and returns whether the value was changed.\n *\n * If @new_strv matches the previous array, this function is a no-op. If\n * @new_strv is different, a copy of it will be assigned to @strv_pointer and\n * the previous array pointed to by @strv_pointer will be freed with\n * [func@GLib.strfreev].\n *\n * The contents of both string arrays are compared for equality before\n * replacing the value. In the worst case this requires O(N) time.\n *\n * This function avoids a potential use-after-free when @new_strv reuses\n * pointers from the original string array. This allows callers to build\n * a replacement array using existing strings without needing to copy\n * them beforehand.\n *\n * @strv_pointer must not be `NULL`, but can point to a `NULL` value.\n *\n * Returns: true if the value of @strv_pointer changed, false otherwise\n *\n * Since: 2.90\n */\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_90\nstatic inline gboolean g_set_strv (char               ***strv_pointer,\n                                   const char * const   *new_strv);\n\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_90\nstatic inline gboolean\ng_set_strv (char               ***strv_pointer,\n            const char * const   *new_strv)\n{\n  char **copy;\n\n  if ((const char * const *)*strv_pointer == new_strv)\n    return FALSE;\n\nG_GNUC_BEGIN_IGNORE_DEPRECATIONS\n  if (*strv_pointer && new_strv &&\n      g_strv_equal ((const char * const *)*strv_pointer, new_strv))\n    return FALSE;\nG_GNUC_END_IGNORE_DEPRECATIONS\n\n  copy = g_strdupv ((char **) (guintptr) new_strv);\n  g_strfreev (*strv_pointer);\n  *strv_pointer = copy;\n\n  return TRUE;\n}\n\n/**\n * g_set_strv_take: (skip)\n * @strv_pointer: (inout) (not optional) (nullable): a pointer to either\n *   a `NULL`-terminated string array or `NULL`\n * @new_strv: (transfer full) (nullable): a `NULL`-terminated string array to\n *   assign to @strv_pointer\n *\n * Safely replaces a string vector, taking ownership of the new value.\n *\n * Updates a pointer to a `NULL`-terminated string array to @new_strv and\n * returns whether the value was changed.\n *\n * If @new_strv contains the same strings as the previous array, this function\n * is a no-op. If @new_strv is different, it will be assigned to @strv_pointer\n * and the previous array pointed to by @strv_pointer will be freed with\n * [func@GLib.strfreev].\n *\n * If @new_strv does not replace the existing value, it will be freed with\n * [func@GLib.strfreev], unless it is `NULL`.\n *\n * The contents of both string arrays are compared for equality before\n * replacing the value. In the worst case this requires O(N) time.\n *\n * @strv_pointer must not be `NULL`, but can point to a `NULL` value.\n * @new_strv must be `NULL` or a string array not already stored in\n * @strv_pointer.\n *\n * Returns: true if the value of @strv_pointer changed, false otherwise\n *\n * Since: 2.90\n */\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_90\nstatic inline gboolean g_set_strv_take (char ***strv_pointer,\n                                        char  **new_strv);\n\nGLIB_AVAILABLE_STATIC_INLINE_IN_2_90\nstatic inline gboolean\ng_set_strv_take (char ***strv_pointer,\n                 char  **new_strv)\n{\n  if (*strv_pointer == NULL && new_strv == NULL)\n    return FALSE;\n\nG_GNUC_BEGIN_IGNORE_DEPRECATIONS\n  if (*strv_pointer && new_strv &&\n      g_strv_equal ((const char * const *)*strv_pointer,\n                    (const char * const *)new_strv))\n    {\n      g_strfreev (new_strv);\n      return FALSE;\n    }\nG_GNUC_END_IGNORE_DEPRECATIONS\n\n  g_strfreev (*strv_pointer);\n  *strv_pointer = new_strv;\n\n  return TRUE;\n}\n\nG_END_DECLS\n\n#endif /* __G_STRFUNCS_H__ */\n"},
                          "roles": ["tracedFile"]},
                         {"location": {"uri": "/usr/include/string.h"},
                          "sourceLanguage": "c",
                          "contents": {"text": "/* Copyright (C) 1991-2026 Free Software Foundation, Inc.\n   This file is part of the GNU C Library.\n\n   The GNU C Library is free software; you can redistribute it and/or\n   modify it under the terms of the GNU Lesser General Public\n   License as published by the Free Software Foundation; either\n   version 2.1 of the License, or (at your option) any later version.\n\n   The GNU C Library is distributed in the hope that it will be useful,\n   but WITHOUT ANY WARRANTY; without even the implied warranty of\n   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n   Lesser General Public License for more details.\n\n   You should have received a copy of the GNU Lesser General Public\n   License along with the GNU C Library; if not, see\n   <https://www.gnu.org/licenses/>.  */\n\n/*\n *\tISO C99 Standard: 7.21 String handling\t<string.h>\n */\n\n#ifndef\t_STRING_H\n#define\t_STRING_H\t1\n\n#define __GLIBC_INTERNAL_STARTING_HEADER_IMPLEMENTATION\n#include <bits/libc-header-start.h>\n\n__BEGIN_DECLS\n\n#if __GLIBC_USE (ISOC23)\n# define __STDC_VERSION_STRING_H__ 202311L\n#endif\n\n/* Get size_t and NULL from <stddef.h>.  */\n#define\t__need_size_t\n#define\t__need_NULL\n#include <stddef.h>\n\n/* Tell the caller that we provide correct C++ prototypes.  */\n#if defined __cplusplus && (__GNUC_PREREQ (4, 4) \\\n\t\t\t    || __glibc_clang_prereq (3, 5))\n# define __CORRECT_ISO_CPP_STRING_H_PROTO\n#endif\n\n\n/* Copy N bytes of SRC to DEST.  */\nextern void *memcpy (void *__restrict __dest, const void *__restrict __src,\n\t\t     size_t __n) __THROW __nonnull ((1, 2));\n/* Copy N bytes of SRC to DEST, guaranteeing\n   correct behavior for overlapping strings.  */\nextern void *memmove (void *__dest, const void *__src, size_t __n)\n     __THROW __nonnull ((1, 2));\n\n/* Copy no more than N bytes of SRC to DEST, stopping when C is found.\n   Return the position in DEST one byte past where C was copied,\n   or NULL if C was not found in the first N bytes of SRC.  */\n#if defined __USE_MISC || defined __USE_XOPEN || __GLIBC_USE (ISOC23)\nextern void *memccpy (void *__restrict __dest, const void *__restrict __src,\n\t\t      int __c, size_t __n)\n    __THROW __nonnull ((1, 2)) __attr_access ((__write_only__, 1, 4));\n#endif /* Misc || X/Open.  */\n\n\n/* Set N bytes of S to C.  */\nextern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));\n\n#if defined __USE_MISC || __GLIBC_USE (ISOC23)\n/* Like memset, but the compiler will not delete a call to this\n   function, even if S is dead after the call.  */\nextern void *memset_explicit (void *__s, int __c, size_t __n)\n     __THROW __nonnull ((1)) __fortified_attr_access (__write_only__, 1, 3);\n#endif\n\n/* Compare N bytes of S1 and S2.  */\nextern int memcmp (const void *__s1, const void *__s2, size_t __n)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n\n/* Compare N bytes of S1 and S2.  Return zero if S1 and S2 are equal.\n   Return some non-zero value otherwise.\n\n   Essentially __memcmpeq has the exact same semantics as memcmp\n   except the return value is less constrained.  memcmp is always a\n   correct implementation of __memcmpeq.  As well !!memcmp, -memcmp,\n   or bcmp are correct implementations.\n\n   __memcmpeq is meant to be used by compilers when memcmp return is\n   only used for its boolean value.\n\n   __memcmpeq is declared only for use by compilers.  Programs should\n   continue to use memcmp.  */\nextern int __memcmpeq (const void *__s1, const void *__s2, size_t __n)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n\n/* Search N bytes of S for C.  */\n#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\"\n{\nextern void *memchr (void *__s, int __c, size_t __n)\n      __THROW __asm (\"memchr\") __attribute_pure__ __nonnull ((1));\nextern const void *memchr (const void *__s, int __c, size_t __n)\n      __THROW __asm (\"memchr\") __attribute_pure__ __nonnull ((1));\n\n# ifdef __OPTIMIZE__\n__extern_always_inline void *\nmemchr (void *__s, int __c, size_t __n) __THROW\n{\n  return __builtin_memchr (__s, __c, __n);\n}\n\n__extern_always_inline const void *\nmemchr (const void *__s, int __c, size_t __n) __THROW\n{\n  return __builtin_memchr (__s, __c, __n);\n}\n# endif\n}\n#else\nextern void *memchr (const void *__s, int __c, size_t __n)\n      __THROW __attribute_pure__ __nonnull ((1));\n# if __GLIBC_USE (ISOC23) && defined __glibc_const_generic && !defined _LIBC\n#  define memchr(S, C, N)\t\t\t\t\t\\\n  __glibc_const_generic (S, const void *, memchr (S, C, N))\n# endif\n#endif\n\n#ifdef __USE_GNU\n/* Search in S for C.  This is similar to `memchr' but there is no\n   length limit.  */\n# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\" void *rawmemchr (void *__s, int __c)\n     __THROW __asm (\"rawmemchr\") __attribute_pure__ __nonnull ((1));\nextern \"C++\" const void *rawmemchr (const void *__s, int __c)\n     __THROW __asm (\"rawmemchr\") __attribute_pure__ __nonnull ((1));\n# else\nextern void *rawmemchr (const void *__s, int __c)\n     __THROW __attribute_pure__ __nonnull ((1));\n# endif\n\n/* Search N bytes of S for the final occurrence of C.  */\n# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\" void *memrchr (void *__s, int __c, size_t __n)\n      __THROW __asm (\"memrchr\") __attribute_pure__ __nonnull ((1))\n      __attr_access ((__read_only__, 1, 3));\nextern \"C++\" const void *memrchr (const void *__s, int __c, size_t __n)\n      __THROW __asm (\"memrchr\") __attribute_pure__ __nonnull ((1))\n      __attr_access ((__read_only__, 1, 3));\n# else\nextern void *memrchr (const void *__s, int __c, size_t __n)\n      __THROW __attribute_pure__ __nonnull ((1))\n      __attr_access ((__read_only__, 1, 3));\n# endif\n#endif\n\n\n/* Copy SRC to DEST.  */\nextern char *strcpy (char *__restrict __dest, const char *__restrict __src)\n     __THROW __nonnull ((1, 2));\n/* Copy no more than N characters of SRC to DEST.  */\nextern char *strncpy (char *__restrict __dest,\n\t\t      const char *__restrict __src, size_t __n)\n     __THROW __nonnull ((1, 2));\n\n/* Append SRC onto DEST.  */\nextern char *strcat (char *__restrict __dest, const char *__restrict __src)\n     __THROW __nonnull ((1, 2));\n/* Append no more than N characters from SRC onto DEST.  */\nextern char *strncat (char *__restrict __dest, const char *__restrict __src,\n\t\t      size_t __n) __THROW __nonnull ((1, 2));\n\n/* Compare S1 and S2.  */\nextern int strcmp (const char *__s1, const char *__s2)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n/* Compare N characters of S1 and S2.  */\nextern int strncmp (const char *__s1, const char *__s2, size_t __n)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n\n/* Compare the collated forms of S1 and S2.  */\nextern int strcoll (const char *__s1, const char *__s2)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n/* Put a transformation of SRC into no more than N bytes of DEST.  */\nextern size_t strxfrm (char *__restrict __dest,\n\t\t       const char *__restrict __src, size_t __n)\n    __THROW __nonnull ((2)) __attr_access ((__write_only__, 1, 3));\n\n#ifdef __USE_XOPEN2K8\n/* POSIX.1-2008 extended locale interface (see locale.h).  */\n# include <bits/types/locale_t.h>\n\n/* Compare the collated forms of S1 and S2, using sorting rules from L.  */\nextern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)\n     __THROW __attribute_pure__ __nonnull ((1, 2, 3));\n/* Put a transformation of SRC into no more than N bytes of DEST,\n   using sorting rules from L.  */\nextern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,\n\t\t\t locale_t __l) __THROW __nonnull ((2, 4))\n     __attr_access ((__write_only__, 1, 3));\n#endif\n\n#if (defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8\t\\\n     || __GLIBC_USE (LIB_EXT2) || __GLIBC_USE (ISOC23))\n/* Duplicate S, returning an identical malloc'd string.  */\nextern char *strdup (const char *__s)\n     __THROW __attribute_malloc__ __nonnull ((1));\n#endif\n\n/* Return a malloc'd copy of at most N bytes of STRING.  The\n   resultant string is terminated even if no null terminator\n   appears before STRING[N].  */\n#if defined __USE_XOPEN2K8 || __GLIBC_USE (LIB_EXT2) || __GLIBC_USE (ISOC23)\nextern char *strndup (const char *__string, size_t __n)\n     __THROW __attribute_malloc__ __nonnull ((1));\n#endif\n\n#if defined __USE_GNU && defined __GNUC__\n/* Duplicate S, returning an identical alloca'd string.  */\n# define strdupa(s)\t\t\t\t\t\t\t      \\\n  (__extension__\t\t\t\t\t\t\t      \\\n    ({\t\t\t\t\t\t\t\t\t      \\\n      const char *__old = (s);\t\t\t\t\t\t      \\\n      size_t __len = strlen (__old) + 1;\t\t\t\t      \\\n      char *__new = (char *) __builtin_alloca (__len);\t\t\t      \\\n      (char *) memcpy (__new, __old, __len);\t\t\t\t      \\\n    }))\n\n/* Return an alloca'd copy of at most N bytes of string.  */\n# define strndupa(s, n)\t\t\t\t\t\t\t      \\\n  (__extension__\t\t\t\t\t\t\t      \\\n    ({\t\t\t\t\t\t\t\t\t      \\\n      const char *__old = (s);\t\t\t\t\t\t      \\\n      size_t __len = strnlen (__old, (n));\t\t\t\t      \\\n      char *__new = (char *) __builtin_alloca (__len + 1);\t\t      \\\n      __new[__len] = '\\0';\t\t\t\t\t\t      \\\n      (char *) memcpy (__new, __old, __len);\t\t\t\t      \\\n    }))\n#endif\n\n/* Find the first occurrence of C in S.  */\n#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\"\n{\nextern char *strchr (char *__s, int __c)\n     __THROW __asm (\"strchr\") __attribute_pure__ __nonnull ((1));\nextern const char *strchr (const char *__s, int __c)\n     __THROW __asm (\"strchr\") __attribute_pure__ __nonnull ((1));\n\n# ifdef __OPTIMIZE__\n__extern_always_inline char *\nstrchr (char *__s, int __c) __THROW\n{\n  return __builtin_strchr (__s, __c);\n}\n\n__extern_always_inline const char *\nstrchr (const char *__s, int __c) __THROW\n{\n  return __builtin_strchr (__s, __c);\n}\n# endif\n}\n#else\nextern char *strchr (const char *__s, int __c)\n     __THROW __attribute_pure__ __nonnull ((1));\n# if __GLIBC_USE (ISOC23) && defined __glibc_const_generic && !defined _LIBC\n#  define strchr(S, C)\t\t\t\t\t\t\\\n  __glibc_const_generic (S, const char *, strchr (S, C))\n# endif\n#endif\n/* Find the last occurrence of C in S.  */\n#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\"\n{\nextern char *strrchr (char *__s, int __c)\n     __THROW __asm (\"strrchr\") __attribute_pure__ __nonnull ((1));\nextern const char *strrchr (const char *__s, int __c)\n     __THROW __asm (\"strrchr\") __attribute_pure__ __nonnull ((1));\n\n# ifdef __OPTIMIZE__\n__extern_always_inline char *\nstrrchr (char *__s, int __c) __THROW\n{\n  return __builtin_strrchr (__s, __c);\n}\n\n__extern_always_inline const char *\nstrrchr (const char *__s, int __c) __THROW\n{\n  return __builtin_strrchr (__s, __c);\n}\n# endif\n}\n#else\nextern char *strrchr (const char *__s, int __c)\n     __THROW __attribute_pure__ __nonnull ((1));\n# if __GLIBC_USE (ISOC23) && defined __glibc_const_generic && !defined _LIBC\n#  define strrchr(S, C)\t\t\t\t\t\t\\\n  __glibc_const_generic (S, const char *, strrchr (S, C))\n# endif\n#endif\n\n#ifdef __USE_MISC\n/* This function is similar to `strchr'.  But it returns a pointer to\n   the closing NUL byte in case C is not found in S.  */\n# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\" char *strchrnul (char *__s, int __c)\n     __THROW __asm (\"strchrnul\") __attribute_pure__ __nonnull ((1));\nextern \"C++\" const char *strchrnul (const char *__s, int __c)\n     __THROW __asm (\"strchrnul\") __attribute_pure__ __nonnull ((1));\n# else\nextern char *strchrnul (const char *__s, int __c)\n     __THROW __attribute_pure__ __nonnull ((1));\n# endif\n#endif\n\n/* Return the length of the initial segment of S which\n   consists entirely of characters not in REJECT.  */\nextern size_t strcspn (const char *__s, const char *__reject)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n/* Return the length of the initial segment of S which\n   consists entirely of characters in ACCEPT.  */\nextern size_t strspn (const char *__s, const char *__accept)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n/* Find the first occurrence in S of any character in ACCEPT.  */\n#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\"\n{\nextern char *strpbrk (char *__s, const char *__accept)\n     __THROW __asm (\"strpbrk\") __attribute_pure__ __nonnull ((1, 2));\nextern const char *strpbrk (const char *__s, const char *__accept)\n     __THROW __asm (\"strpbrk\") __attribute_pure__ __nonnull ((1, 2));\n\n# ifdef __OPTIMIZE__\n__extern_always_inline char *\nstrpbrk (char *__s, const char *__accept) __THROW\n{\n  return __builtin_strpbrk (__s, __accept);\n}\n\n__extern_always_inline const char *\nstrpbrk (const char *__s, const char *__accept) __THROW\n{\n  return __builtin_strpbrk (__s, __accept);\n}\n# endif\n}\n#else\nextern char *strpbrk (const char *__s, const char *__accept)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n# if __GLIBC_USE (ISOC23) && defined __glibc_const_generic && !defined _LIBC\n#  define strpbrk(S, ACCEPT)\t\t\t\t\t\\\n  __glibc_const_generic (S, const char *, strpbrk (S, ACCEPT))\n# endif\n#endif\n/* Find the first occurrence of NEEDLE in HAYSTACK.  */\n#ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\"\n{\nextern char *strstr (char *__haystack, const char *__needle)\n     __THROW __asm (\"strstr\") __attribute_pure__ __nonnull ((1, 2));\nextern const char *strstr (const char *__haystack, const char *__needle)\n     __THROW __asm (\"strstr\") __attribute_pure__ __nonnull ((1, 2));\n\n# ifdef __OPTIMIZE__\n__extern_always_inline char *\nstrstr (char *__haystack, const char *__needle) __THROW\n{\n  return __builtin_strstr (__haystack, __needle);\n}\n\n__extern_always_inline const char *\nstrstr (const char *__haystack, const char *__needle) __THROW\n{\n  return __builtin_strstr (__haystack, __needle);\n}\n# endif\n}\n#else\nextern char *strstr (const char *__haystack, const char *__needle)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n# if __GLIBC_USE (ISOC23) && defined __glibc_const_generic && !defined _LIBC\n#  define strstr(HAYSTACK, NEEDLE)\t\t\t\\\n  __glibc_const_generic (HAYSTACK, const char *,\t\\\n\t\t\t strstr (HAYSTACK, NEEDLE))\n# endif\n#endif\n\n\n/* Divide S into tokens separated by characters in DELIM.  */\nextern char *strtok (char *__restrict __s, const char *__restrict __delim)\n     __THROW __nonnull ((2));\n\n/* Divide S into tokens separated by characters in DELIM.  Information\n   passed between calls are stored in SAVE_PTR.  */\nextern char *__strtok_r (char *__restrict __s,\n\t\t\t const char *__restrict __delim,\n\t\t\t char **__restrict __save_ptr)\n     __THROW __nonnull ((2, 3));\n#ifdef __USE_POSIX\nextern char *strtok_r (char *__restrict __s, const char *__restrict __delim,\n\t\t       char **__restrict __save_ptr)\n     __THROW __nonnull ((2, 3));\n#endif\n\n#ifdef __USE_MISC\n/* Similar to `strstr' but this function ignores the case of both strings.  */\n# ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\" char *strcasestr (char *__haystack, const char *__needle)\n     __THROW __asm (\"strcasestr\") __attribute_pure__ __nonnull ((1, 2));\nextern \"C++\" const char *strcasestr (const char *__haystack,\n\t\t\t\t     const char *__needle)\n     __THROW __asm (\"strcasestr\") __attribute_pure__ __nonnull ((1, 2));\n# else\nextern char *strcasestr (const char *__haystack, const char *__needle)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n# endif\n#endif\n\n#ifdef __USE_MISC\n/* Find the first occurrence of NEEDLE in HAYSTACK.\n   NEEDLE is NEEDLELEN bytes long;\n   HAYSTACK is HAYSTACKLEN bytes long.  */\nextern void *memmem (const void *__haystack, size_t __haystacklen,\n\t\t     const void *__needle, size_t __needlelen)\n     __THROW __attribute_pure__ __nonnull ((1, 3))\n    __attr_access ((__read_only__, 1, 2))\n    __attr_access ((__read_only__, 3, 4));\n\n/* Copy N bytes of SRC to DEST, return pointer to bytes after the\n   last written byte.  */\nextern void *__mempcpy (void *__restrict __dest,\n\t\t\tconst void *__restrict __src, size_t __n)\n     __THROW __nonnull ((1, 2));\nextern void *mempcpy (void *__restrict __dest,\n\t\t      const void *__restrict __src, size_t __n)\n     __THROW __nonnull ((1, 2));\n#endif\n\n\n/* Return the length of S.  */\nextern size_t strlen (const char *__s)\n     __THROW __attribute_pure__ __nonnull ((1));\n\n#ifdef\t__USE_XOPEN2K8\n/* Find the length of STRING, but scan at most MAXLEN characters.\n   If no '\\0' terminator is found in that many characters, return MAXLEN.  */\nextern size_t strnlen (const char *__string, size_t __maxlen)\n     __THROW __attribute_pure__ __nonnull ((1));\n#endif\n\n\n/* Return a string describing the meaning of the `errno' code in ERRNUM.  */\nextern char *strerror (int __errnum) __THROW;\n#ifdef __USE_XOPEN2K\n/* Reentrant version of `strerror'.\n   There are 2 flavors of `strerror_r', GNU which returns the string\n   and may or may not use the supplied temporary buffer and POSIX one\n   which fills the string into the buffer.\n   To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L\n   without -D_GNU_SOURCE is needed, otherwise the GNU version is\n   preferred.  */\n# if defined __USE_XOPEN2K && !defined __USE_GNU\n/* Fill BUF with a string describing the meaning of the `errno' code in\n   ERRNUM.  */\n#  ifdef __REDIRECT_NTH\nextern int __REDIRECT_NTH (strerror_r,\n\t\t\t   (int __errnum, char *__buf, size_t __buflen),\n\t\t\t   __xpg_strerror_r) __nonnull ((2))\n    __attr_access ((__write_only__, 2, 3));\n#  else\nextern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen)\n     __THROW __nonnull ((2)) __attr_access ((__write_only__, 2, 3));\n#   define strerror_r __xpg_strerror_r\n#  endif\n# else\n/* If a temporary buffer is required, at most BUFLEN bytes of BUF will be\n   used.  */\nextern char *strerror_r (int __errnum, char *__buf, size_t __buflen)\n     __THROW __nonnull ((2)) __wur  __attr_access ((__write_only__, 2, 3));\n# endif\n\n# ifdef __USE_GNU\n/* Return a string describing the meaning of tthe error in ERR.  */\nextern const char *strerrordesc_np (int __err) __THROW;\n/* Return a string with the error name in ERR.  */\nextern const char *strerrorname_np (int __err) __THROW;\n# endif\n#endif\n\n#ifdef __USE_XOPEN2K8\n/* Translate error number to string according to the locale L.  */\nextern char *strerror_l (int __errnum, locale_t __l) __THROW;\n#endif\n\n#ifdef __USE_MISC\n# include <strings.h>\n\n/* Set N bytes of S to 0.  The compiler will not delete a call to this\n   function, even if S is dead after the call.  */\nextern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1))\n    __fortified_attr_access (__write_only__, 1, 2);\n\n/* Return the next DELIM-delimited token from *STRINGP,\n   terminating it with a '\\0', and update *STRINGP to point past it.  */\nextern char *strsep (char **__restrict __stringp,\n\t\t     const char *__restrict __delim)\n     __THROW __nonnull ((1, 2));\n#endif\n\n#ifdef\t__USE_XOPEN2K8\n/* Return a string describing the meaning of the signal number in SIG.  */\nextern char *strsignal (int __sig) __THROW;\n\n# ifdef __USE_GNU\n/* Return an abbreviation string for the signal number SIG.  */\nextern const char *sigabbrev_np (int __sig) __THROW;\n/* Return a string describing the meaning of the signal number in SIG,\n   the result is not translated.  */\nextern const char *sigdescr_np (int __sig) __THROW;\n# endif\n\n/* Copy SRC to DEST, returning the address of the terminating '\\0' in DEST.  */\nextern char *__stpcpy (char *__restrict __dest, const char *__restrict __src)\n     __THROW __nonnull ((1, 2));\nextern char *stpcpy (char *__restrict __dest, const char *__restrict __src)\n     __THROW __nonnull ((1, 2));\n\n/* Copy no more than N characters of SRC to DEST, returning the address of\n   the last character written into DEST.  */\nextern char *__stpncpy (char *__restrict __dest,\n\t\t\tconst char *__restrict __src, size_t __n)\n     __THROW __nonnull ((1, 2));\nextern char *stpncpy (char *__restrict __dest,\n\t\t      const char *__restrict __src, size_t __n)\n     __THROW __nonnull ((1, 2));\n#endif\n\n#ifdef __USE_MISC\n/* Copy at most N - 1 characters from SRC to DEST.  */\nextern size_t strlcpy (char *__restrict __dest,\n\t\t       const char *__restrict __src, size_t __n)\n  __THROW __nonnull ((1, 2)) __attr_access ((__write_only__, 1, 3));\n\n/* Append SRC to DEST, possibly with truncation to keep the total size\n   below N.  */\nextern size_t strlcat (char *__restrict __dest,\n\t\t       const char *__restrict __src, size_t __n)\n  __THROW __nonnull ((1, 2))  __attr_access ((__read_write__, 1, 3));\n#endif\n\n#ifdef\t__USE_GNU\n/* Compare S1 and S2 as strings holding name & indices/version numbers.  */\nextern int strverscmp (const char *__s1, const char *__s2)\n     __THROW __attribute_pure__ __nonnull ((1, 2));\n\n/* Sautee STRING briskly.  */\nextern char *strfry (char *__string) __THROW __nonnull ((1));\n\n/* Frobnicate N bytes of S.  */\nextern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1))\n    __attr_access ((__read_write__, 1, 2));\n\n# ifndef basename\n/* Return the file name within directory of FILENAME.  We don't\n   declare the function if the `basename' macro is available (defined\n   in <libgen.h>) which makes the XPG version of this function\n   available.  */\n#  ifdef __CORRECT_ISO_CPP_STRING_H_PROTO\nextern \"C++\" char *basename (char *__filename)\n     __THROW __asm (\"basename\") __nonnull ((1));\nextern \"C++\" const char *basename (const char *__filename)\n     __THROW __asm (\"basename\") __nonnull ((1));\n#  else\nextern char *basename (const char *__filename) __THROW __nonnull ((1));\n#  endif\n# endif\n#endif\n\n#if __GNUC_PREREQ (3,4)\n# if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function\n/* Functions with security checks.  */\n#  include <bits/string_fortified.h>\n# endif\n#endif\n\n__END_DECLS\n\n#endif /* string.h  */\n"},
                          "roles": ["resultFile"]},
                         {"location": {"uri": "/usr/include/glib-2.0/glib/gstring.h"},
                          "sourceLanguage": "c"},
                         {"location": {"uri": "/usr/include/glib-2.0/glib/giochannel.h"},
                          "sourceLanguage": "c"},
                         {"location": {"uri": "/usr/include/glib-2.0/glib.h"},
                          "sourceLanguage": "c"}],
           "results": [{"ruleId": "-Wanalyzer-null-argument",
                        "taxa": [{"id": "476",
                                  "toolComponent": {"name": "cwe"}}],
                        "properties": {"gcc/analyzer/saved_diagnostic/sm": "malloc",
                                       "gcc/analyzer/saved_diagnostic/ploc": {"enode": 1994},
                                       "gcc/analyzer/saved_diagnostic/var": "_194",
                                       "gcc/analyzer/saved_diagnostic/sval": "(char *)0B",
                                       "gcc/analyzer/saved_diagnostic/state": "null",
                                       "gcc/analyzer/saved_diagnostic/idx": 0,
                                       "gcc/analyzer/pending_diagnostic/kind": "null_arg"},
                        "level": "warning",
                        "message": {"text": "use of NULL where non-null expected"},
                        "locations": [{"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                 "uriBaseId": "PWD"},
                                                            "region": {"startLine": 3423,
                                                                       "startColumn": 56,
                                                                       "endColumn": 79},
                                                            "contextRegion": {"startLine": 3423,
                                                                              "snippet": {"text": "    cert = CERT_DecodeCertFromPackage (cert_data_copy, strlen (cert_data_copy));\n"}}},
                                       "logicalLocations": [{"index": 0,
                                                             "fullyQualifiedName": "bd_crypto_escrow_device"}]}],
                        "codeFlows": [{"threadFlows": [{"id": "main",
                                                        "locations": [{"properties": {"gcc/analyzer/checker_event/emission_id": "(1)",
                                                                                      "gcc/analyzer/checker_event/kind": "function_entry"},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3368,
                                                                                                                    "startColumn": 10,
                                                                                                                    "endColumn": 33},
                                                                                                         "contextRegion": {"startLine": 3368,
                                                                                                                           "snippet": {"text": "gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, const gchar *cert_data, const gchar *directory, const gchar *backup_passphrase, GError **error) {\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "entry to 'bd_crypto_escrow_device'"}},
                                                                       "kinds": ["enter",
                                                                                 "function"],
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 1},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(2)",
                                                                                      "gcc/analyzer/checker_event/kind": "start_cfg_edge",
                                                                                      "gcc/analyzer/superedge_event/superedge": {"src_id": 654,
                                                                                                                                 "dst_id": 661}},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3397,
                                                                                                                    "startColumn": 8,
                                                                                                                    "endColumn": 9},
                                                                                                         "contextRegion": {"startLine": 3397,
                                                                                                                           "snippet": {"text": "    if (!volume) {\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "following 'false' branch..."}},
                                                                       "kinds": ["branch",
                                                                                 "false"],
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 2},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(3)",
                                                                                      "gcc/analyzer/checker_event/kind": "end_cfg_edge",
                                                                                      "gcc/analyzer/superedge_event/superedge": {"src_id": 654,
                                                                                                                                 "dst_id": 661}},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3403,
                                                                                                                    "startColumn": 10,
                                                                                                                    "endColumn": 25},
                                                                                                         "contextRegion": {"startLine": 3403,
                                                                                                                           "snippet": {"text": "    ui = libvk_ui_new ();\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "...to here"}},
                                                                       "kinds": ["branch",
                                                                                 "false"],
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 3},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(4)",
                                                                                      "gcc/analyzer/checker_event/kind": "start_cfg_edge",
                                                                                      "gcc/analyzer/superedge_event/superedge": {"src_id": 693,
                                                                                                                                 "dst_id": 702}},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3413,
                                                                                                                    "startColumn": 8,
                                                                                                                    "endColumn": 9},
                                                                                                         "contextRegion": {"startLine": 3413,
                                                                                                                           "snippet": {"text": "    if (libvk_volume_get_secret (volume, LIBVK_SECRET_DEFAULT, ui, &l_error) != 0) {\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "following 'false' branch..."}},
                                                                       "kinds": ["branch",
                                                                                 "false"],
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 4},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(5)",
                                                                                      "gcc/analyzer/checker_event/kind": "inlined_call"},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3422,
                                                                                                                    "startColumn": 22,
                                                                                                                    "endColumn": 23},
                                                                                                         "contextRegion": {"startLine": 3422,
                                                                                                                           "snippet": {"text": "    cert_data_copy = g_strdup (cert_data);\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "inlined call to 'g_strdup_inline' from 'bd_crypto_escrow_device'"},
                                                                                    "id": 0,
                                                                                    "relationships": [{"target": 1,
                                                                                                       "kinds": ["isIncludedBy"]}]},
                                                                       "kinds": ["call",
                                                                                 "function"],
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 5},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(6)",
                                                                                      "gcc/analyzer/checker_event/kind": "end_cfg_edge",
                                                                                      "gcc/analyzer/checker_event/original_fndecl": {"index": 0,
                                                                                                                                     "fullyQualifiedName": "bd_crypto_escrow_device"},
                                                                                      "gcc/analyzer/checker_event/original_depth": 1,
                                                                                      "gcc/analyzer/superedge_event/superedge": {"src_id": 693,
                                                                                                                                 "dst_id": 702}},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "/usr/include/glib-2.0/glib/gstrfuncs.h"},
                                                                                                         "region": {"startLine": 311,
                                                                                                                    "startColumn": 7,
                                                                                                                    "endColumn": 34},
                                                                                                         "contextRegion": {"startLine": 311,
                                                                                                                           "snippet": {"text": "  if (__builtin_constant_p (!str) && !str)\n"}}},
                                                                                    "logicalLocations": [{"index": 1,
                                                                                                          "fullyQualifiedName": "g_strdup_inline"}],
                                                                                    "message": {"text": "...to here"},
                                                                                    "id": 2,
                                                                                    "relationships": [{"target": 1,
                                                                                                       "kinds": ["isIncludedBy"]}]},
                                                                       "kinds": ["branch",
                                                                                 "false"],
                                                                       "nestingLevel": 2,
                                                                       "executionOrder": 6},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(7)",
                                                                                      "gcc/analyzer/checker_event/kind": "start_consolidated_cfg_edges",
                                                                                      "gcc/analyzer/checker_event/original_depth": 2},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "/usr/include/glib-2.0/glib/gstrfuncs.h"},
                                                                                                         "region": {"startLine": 311,
                                                                                                                    "startColumn": 6,
                                                                                                                    "endColumn": 7},
                                                                                                         "contextRegion": {"startLine": 311,
                                                                                                                           "snippet": {"text": "  if (__builtin_constant_p (!str) && !str)\n"}}},
                                                                                    "logicalLocations": [{"index": 1,
                                                                                                          "fullyQualifiedName": "g_strdup_inline"}],
                                                                                    "message": {"text": "following 'true' branch..."},
                                                                                    "id": 3,
                                                                                    "relationships": [{"target": 1,
                                                                                                       "kinds": ["isIncludedBy"]}]},
                                                                       "kinds": ["branch",
                                                                                 "true"],
                                                                       "nestingLevel": 3,
                                                                       "executionOrder": 7},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(8)",
                                                                                      "gcc/analyzer/checker_event/kind": "end_consolidated_cfg_edges"},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3423,
                                                                                                                    "startColumn": 56,
                                                                                                                    "endColumn": 79},
                                                                                                         "contextRegion": {"startLine": 3423,
                                                                                                                           "snippet": {"text": "    cert = CERT_DecodeCertFromPackage (cert_data_copy, strlen (cert_data_copy));\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "...to here"}},
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 8},
                                                                      {"properties": {"gcc/analyzer/checker_event/emission_id": "(9)",
                                                                                      "gcc/analyzer/checker_event/kind": "warning"},
                                                                       "location": {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                                                              "uriBaseId": "PWD"},
                                                                                                         "region": {"startLine": 3423,
                                                                                                                    "startColumn": 56,
                                                                                                                    "endColumn": 79},
                                                                                                         "contextRegion": {"startLine": 3423,
                                                                                                                           "snippet": {"text": "    cert = CERT_DecodeCertFromPackage (cert_data_copy, strlen (cert_data_copy));\n"}}},
                                                                                    "logicalLocations": [{"index": 0,
                                                                                                          "fullyQualifiedName": "bd_crypto_escrow_device"}],
                                                                                    "message": {"text": "argument 1 ('<unknown>') NULL where non-null expected"}},
                                                                       "kinds": ["danger"],
                                                                       "nestingLevel": 1,
                                                                       "executionOrder": 9}]}]}],
                        "relatedLocations": [{"physicalLocation": {"artifactLocation": {"uri": "/usr/include/string.h"},
                                                                   "region": {"startLine": 439,
                                                                              "startColumn": 15,
                                                                              "endColumn": 21},
                                                                   "contextRegion": {"startLine": 439,
                                                                                     "snippet": {"text": "extern size_t strlen (const char *__s)\n"}}},
                                              "message": {"text": "argument 1 of 'strlen' must be non-null"},
                                              "properties": {"nestingLevel": 0},
                                              "id": 4,
                                              "relationships": [{"target": 5,
                                                                 "kinds": ["isIncludedBy"]}]},
                                             {"physicalLocation": {"artifactLocation": {"uri": "/usr/include/glib-2.0/glib/gstring.h"},
                                                                   "region": {"startLine": 37},
                                                                   "contextRegion": {"startLine": 37,
                                                                                     "snippet": {"text": "#include <glib/gstrfuncs.h>\n"}}},
                                              "relationships": [{"target": 0,
                                                                 "kinds": ["includes"]},
                                                                {"target": 2,
                                                                 "kinds": ["includes"]},
                                                                {"target": 3,
                                                                 "kinds": ["includes"]},
                                                                {"target": 6,
                                                                 "kinds": ["isIncludedBy"]}],
                                              "id": 1},
                                             {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                        "uriBaseId": "PWD"},
                                                                   "region": {"startLine": 20},
                                                                   "contextRegion": {"startLine": 20,
                                                                                     "snippet": {"text": "#include <string.h>\n"}}},
                                              "relationships": [{"target": 4,
                                                                 "kinds": ["includes"]}],
                                              "id": 5},
                                             {"physicalLocation": {"artifactLocation": {"uri": "/usr/include/glib-2.0/glib/giochannel.h"},
                                                                   "region": {"startLine": 36},
                                                                   "contextRegion": {"startLine": 36,
                                                                                     "snippet": {"text": "#include <glib/gstring.h>\n"}}},
                                              "relationships": [{"target": 1,
                                                                 "kinds": ["includes"]},
                                                                {"target": 7,
                                                                 "kinds": ["isIncludedBy"]}],
                                              "id": 6},
                                             {"physicalLocation": {"artifactLocation": {"uri": "/usr/include/glib-2.0/glib.h"},
                                                                   "region": {"startLine": 56},
                                                                   "contextRegion": {"startLine": 56,
                                                                                     "snippet": {"text": "#include <glib/giochannel.h>\n"}}},
                                              "relationships": [{"target": 6,
                                                                 "kinds": ["includes"]},
                                                                {"target": 8,
                                                                 "kinds": ["isIncludedBy"]}],
                                              "id": 7},
                                             {"physicalLocation": {"artifactLocation": {"uri": "crypto.c",
                                                                                        "uriBaseId": "PWD"},
                                                                   "region": {"startLine": 21},
                                                                   "contextRegion": {"startLine": 21,
                                                                                     "snippet": {"text": "#include <glib.h>\n"}}},
                                              "relationships": [{"target": 7,
                                                                 "kinds": ["includes"]}],
                                              "id": 8}]}],
           "logicalLocations": [{"name": "bd_crypto_escrow_device",
                                 "fullyQualifiedName": "bd_crypto_escrow_device",
                                 "decoratedName": "bd_crypto_escrow_device",
                                 "kind": "function",
                                 "index": 0},
                                {"name": "g_strdup_inline",
                                 "fullyQualifiedName": "g_strdup_inline",
                                 "decoratedName": "g_strdup_inline",
                                 "kind": "function",
                                 "index": 1}]}]}
