blob: f2cbadd0723731746c6a9ba5a56865bf504a2532 [file] [log] [blame]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <brillo/blkdev_utils/device_mapper_task.h>
#include <libdevmapper.h>
#include <string>
#include <utility>
#include <brillo/blkdev_utils/device_mapper.h>
namespace brillo {
DevmapperTaskImpl::DevmapperTaskImpl(int type)
: task_(DmTaskPtr(dm_task_create(type), &dm_task_destroy)) {}
bool DevmapperTaskImpl::SetName(const std::string& name) {
if (!task_ || !dm_task_set_name(task_.get(), name.c_str())) {
LOG(ERROR) << "SetName failed";
return false;
}
return true;
}
bool DevmapperTaskImpl::AddTarget(uint64_t start,
uint64_t length,
const std::string& type,
const SecureBlob& parameters) {
// Strings stored in SecureBlob don't end with '\0'. Unfortunately,
// this causes accesses beyond the allocated storage space if any
// of the functions expecting a c-string get passed a SecureBlob.data().
// Temporarily, assign to a string.
// TODO(sarthakkukreti): Evaluate creation of a SecureCString to keep
// string data safe.
std::string parameters_str = parameters.to_string();
if (!task_ ||
!dm_task_add_target(task_.get(), start, length, type.c_str(),
parameters_str.c_str())) {
LOG(ERROR) << "AddTarget failed";
return false;
}
// Clear the string.
parameters_str.clear();
return true;
}
bool DevmapperTaskImpl::GetNextTarget(uint64_t* start,
uint64_t* length,
std::string* type,
SecureBlob* parameters) {
if (!task_) {
LOG(ERROR) << "GetNextTarget: invalid task.";
return false;
}
char *type_cstr, *parameters_cstr;
next_target_ = dm_get_next_target(task_.get(), next_target_, start, length,
&type_cstr, &parameters_cstr);
if (type_cstr)
*type = std::string(type_cstr);
if (parameters_cstr) {
SecureBlob parameters_blob(parameters_cstr);
memset(parameters_cstr, 0, parameters_blob.size());
*parameters = std::move(parameters_blob);
}
return (next_target_ != nullptr);
}
bool DevmapperTaskImpl::Run(bool udev_sync) {
uint32_t cookie = 0;
if (!task_) {
LOG(ERROR) << "Invalid task.";
return false;
}
if (udev_sync && !dm_task_set_cookie(task_.get(), &cookie, 0)) {
LOG(ERROR) << "dm_task_set_cookie failed";
return false;
}
if (!dm_task_run(task_.get())) {
LOG(ERROR) << "dm_task_run failed";
return false;
}
// Make sure the node exists before continuing.
// TODO(sarthakkukreti): move to dm_udev_wait_immediate() on uprevving lvm2.
return udev_sync ? (dm_udev_wait(cookie) != 0) : true;
}
} // namespace brillo