+ /* data blocks */
+ val64 = strtoull(params, ¶ms, 10);
+ if (*params != ' ')
+ return -EINVAL;
+ if (vp)
+ vp->data_size = val64;
+ params++;
+
+ /* hash start */
+ val64 = strtoull(params, ¶ms, 10);
+ if (*params != ' ')
+ return -EINVAL;
+ dmd->u.verity.hash_offset = val64;
+ params++;
+
+ /* hash algorithm */
+ str = strsep(¶ms, " ");
+ if (!params)
+ return -EINVAL;
+ if (vp)
+ vp->hash_name = strdup(str);
+
+ /* root digest */
+ str = strsep(¶ms, " ");
+ if (!params)
+ return -EINVAL;
+ len = crypt_hex_to_bytes(str, &str2, 0);
+ if (len < 0)
+ return len;
+ dmd->u.verity.root_hash_size = len;
+ if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH)
+ dmd->u.verity.root_hash = str2;
+ else
+ free(str2);
+
+ /* salt */
+ str = strsep(¶ms, " ");
+ if (params)
+ return -EINVAL;
+ if (vp) {
+ if (!strcmp(str, "-")) {
+ vp->salt_size = 0;
+ vp->salt = NULL;
+ } else {
+ len = crypt_hex_to_bytes(str, &str2, 0);
+ if (len < 0)
+ return len;
+ vp->salt_size = len;
+ vp->salt = str2;
+ }
+ }
+
+ return 0;
+}
+
+int dm_query_device(struct crypt_device *cd, const char *name,
+ uint32_t get_flags, struct crypt_dm_active_device *dmd)
+{
+ struct dm_task *dmt;
+ struct dm_info dmi;
+ uint64_t start, length;
+ char *target_type, *params;
+ const char *tmp_uuid;
+ void *next = NULL;
+ int r = -EINVAL;
+
+ if (dm_init_context(cd))
+ return -ENOTSUP;
+ if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+ goto out;
+ if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
+ goto out;
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+ r = -ENODEV;
+ if (!dm_task_run(dmt))
+ goto out;
+
+ r = -EINVAL;
+ if (!dm_task_get_info(dmt, &dmi))
+ goto out;
+
+ if (!dmi.exists) {
+ r = -ENODEV;
+ goto out;
+ }
+
+ next = dm_get_next_target(dmt, next, &start, &length,
+ &target_type, ¶ms);
+
+ if (!target_type || start != 0 || next)
+ goto out;
+
+ if (!strcmp(target_type, DM_CRYPT_TARGET)) {
+ r = _dm_query_crypt(get_flags, &dmi, params, dmd);
+ } else if (!strcmp(target_type, DM_VERITY_TARGET)) {
+ r = _dm_query_verity(get_flags, &dmi, params, dmd);
+ if (r < 0)
+ goto out;
+ r = _dm_status_verity_ok(name);
+ if (r < 0)
+ goto out;
+ if (r == 0)
+ dmd->flags |= CRYPT_ACTIVATE_CORRUPTED;
+ r = 0;
+ } else
+ r = -EINVAL;
+
+ if (r < 0)
+ goto out;
+
+ dmd->size = length;
+
+ if (dmi.read_only)
+ dmd->flags |= CRYPT_ACTIVATE_READONLY;
+
+ tmp_uuid = dm_task_get_uuid(dmt);
+ if (!tmp_uuid)
+ dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
+ else if (get_flags & DM_ACTIVE_UUID) {
+ if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
+ dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
+ }
+
+ r = (dmi.open_count > 0);