int crypt_init_by_name_and_header(struct crypt_device **cd,
				  const char *name,
				  const char *header_device)
{
	crypt_status_info ci;
	struct crypt_dm_active_device dmd;
	struct dm_target *tgt = &dmd.segment;
	int r;

	if (!cd || !name)
		return -EINVAL;

	log_dbg(NULL, "Allocating crypt device context by device %s.", name);

	ci = crypt_status(NULL, name);
	if (ci == CRYPT_INVALID)
		return -ENODEV;

	if (ci < CRYPT_ACTIVE) {
		log_err(NULL, _("Device %s is not active."), name);
		return -ENODEV;
	}

	r = dm_query_device(NULL, name, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &dmd);
	if (r < 0)
		return r;

	*cd = NULL;

	if (header_device) {
		r = crypt_init(cd, header_device);
	} else {
		r = crypt_init(cd, device_path(tgt->data_device));

		/* Underlying device disappeared but mapping still active */
		if (!tgt->data_device || r == -ENOTBLK)
			log_verbose(NULL, _("Underlying device for crypt device %s disappeared."),
				    name);

		/* Underlying device is not readable but crypt mapping exists */
		if (r == -ENOTBLK)
			r = crypt_init(cd, NULL);
	}

	if (r < 0)
		goto out;

	if (dmd.uuid) {
		if (!strncmp(CRYPT_PLAIN, dmd.uuid, sizeof(CRYPT_PLAIN)-1))
			(*cd)->type = strdup(CRYPT_PLAIN);
		else if (!strncmp(CRYPT_LOOPAES, dmd.uuid, sizeof(CRYPT_LOOPAES)-1))
			(*cd)->type = strdup(CRYPT_LOOPAES);
		else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1))
			(*cd)->type = strdup(CRYPT_LUKS1);
		else if (!strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1))
			(*cd)->type = strdup(CRYPT_LUKS2);
		else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1))
			(*cd)->type = strdup(CRYPT_VERITY);
		else if (!strncmp(CRYPT_TCRYPT, dmd.uuid, sizeof(CRYPT_TCRYPT)-1))
			(*cd)->type = strdup(CRYPT_TCRYPT);
		else if (!strncmp(CRYPT_INTEGRITY, dmd.uuid, sizeof(CRYPT_INTEGRITY)-1))
			(*cd)->type = strdup(CRYPT_INTEGRITY);
		else if (!strncmp(CRYPT_BITLK, dmd.uuid, sizeof(CRYPT_BITLK)-1))
			(*cd)->type = strdup(CRYPT_BITLK);
		else
			log_dbg(NULL, "Unknown UUID set, some parameters are not set.");
	} else
		log_dbg(NULL, "Active device has no UUID set, some parameters are not set.");

	if (header_device) {
		r = crypt_set_data_device(*cd, device_path(tgt->data_device));
		if (r < 0)
			goto out;
	}

	/* Try to initialize basic parameters from active device */

	if (tgt->type == DM_CRYPT || tgt->type == DM_LINEAR)
		r = _init_by_name_crypt(*cd, name);
	else if (tgt->type == DM_VERITY)
		r = _init_by_name_verity(*cd, name);
	else if (tgt->type == DM_INTEGRITY)
		r = _init_by_name_integrity(*cd, name);
out:
	if (r < 0) {
		crypt_free(*cd);
		*cd = NULL;
	} else if (!(*cd)->type) {
		/* For anonymous device (no header found) remember initialized name */
		(*cd)->u.none.active_name = strdup(name);
	}

	free(CONST_CAST(void*)dmd.uuid);
	dm_targets_free(NULL, &dmd);
	return r;
}
int crypt_init_by_name_and_header(struct crypt_device **cd,
				  const char *name,
				  const char *header_device)
{
	crypt_status_info ci;
	struct crypt_dm_active_device dmd;
	struct dm_target *tgt = &dmd.segment;
	int r;

	if (!cd || !name)
		return -EINVAL;

	log_dbg(NULL, "Allocating crypt device context by device %s.", name);

	ci = crypt_status(NULL, name);
	if (ci == CRYPT_INVALID)
		return -ENODEV;

	if (ci < CRYPT_ACTIVE) {
		log_err(NULL, _("Device %s is not active."), name);
		return -ENODEV;
	}

	r = dm_query_device(NULL, name, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &dmd);
	if (r < 0)
		return r;

	*cd = NULL;

	if (header_device) {
		r = crypt_init(cd, header_device);
	} else {
		r = crypt_init(cd, device_path(tgt->data_device));

		 
		if (!tgt->data_device || r == -ENOTBLK)
			log_verbose(NULL, _("Underlying device for crypt device %s disappeared."),
				    name);

		 
		if (r == -ENOTBLK)
			r = crypt_init(cd, NULL);
	}

	if (r < 0)
		goto out;

	if (dmd.uuid) {
		if (!strncmp(CRYPT_PLAIN, dmd.uuid, sizeof(CRYPT_PLAIN)-1))
			(*cd)->type = strdup(CRYPT_PLAIN);
		else if (!strncmp(CRYPT_LOOPAES, dmd.uuid, sizeof(CRYPT_LOOPAES)-1))
			(*cd)->type = strdup(CRYPT_LOOPAES);
		else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1))
			(*cd)->type = strdup(CRYPT_LUKS1);
		else if (!strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1))
			(*cd)->type = strdup(CRYPT_LUKS2);
		else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1))
			(*cd)->type = strdup(CRYPT_VERITY);
		else if (!strncmp(CRYPT_TCRYPT, dmd.uuid, sizeof(CRYPT_TCRYPT)-1))
			(*cd)->type = strdup(CRYPT_TCRYPT);
		else if (!strncmp(CRYPT_INTEGRITY, dmd.uuid, sizeof(CRYPT_INTEGRITY)-1))
			(*cd)->type = strdup(CRYPT_INTEGRITY);
		else if (!strncmp(CRYPT_BITLK, dmd.uuid, sizeof(CRYPT_BITLK)-1))
			(*cd)->type = strdup(CRYPT_BITLK);
		else
			log_dbg(NULL, "Unknown UUID set, some parameters are not set.");
	} else
		log_dbg(NULL, "Active device has no UUID set, some parameters are not set.");

	if (header_device) {
		r = crypt_set_data_device(*cd, device_path(tgt->data_device));
		if (r < 0)
			goto out;
	}

	 

	if (tgt->type == DM_CRYPT || tgt->type == DM_LINEAR)
		r = _init_by_name_crypt(*cd, name);
	else if (tgt->type == DM_VERITY)
		r = _init_by_name_verity(*cd, name);
	else if (tgt->type == DM_INTEGRITY)
		r = _init_by_name_integrity(*cd, name);
out:
	if (r < 0) {
		crypt_free(*cd);
		*cd = NULL;
	} else if (!(*cd)->type) {
		 
		(*cd)->u.none.active_name = strdup(name);
	}

	free(CONST_CAST(void*)dmd.uuid);
	dm_targets_free(NULL, &dmd);
	return r;
}