| // 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, ¶meters_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 |