fs_mgr: device mapper: Add libdm and 'dmctl' tool to use it.
libdm is small static library that is intended to be the one source to control device mapper. It is intended to have APIs to create, control and destroy device mapper targets. Eventually, all fs_mgr implementation that talks to device mapper will be moved to using libdm APIs. Added 'dmctl', a command line tool that lists the registered device mapper targets and their corresponding version. The tool will continue to get new features to exemplify new APIs implemented in libdm. The library is intentionally static and folds into libfs_mgr. All clients must link to libfs_mgr as a result. Test: dmctl list Bug: 110035986 Change-Id: I71e7146073a74e7523524bf3b20d0be6d06f9fad Signed-off-by: Sandeep Patil <sspatil@google.com>
This commit is contained in:
parent
ec9b6b73ff
commit
59f04ee74c
|
@ -56,12 +56,15 @@ cc_library_static {
|
|||
"libselinux",
|
||||
"libavb",
|
||||
"libfstab",
|
||||
"libdm",
|
||||
],
|
||||
export_static_lib_headers: [
|
||||
"libfstab",
|
||||
"libdm",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"liblogwrap",
|
||||
"libdm",
|
||||
"libfstab",
|
||||
],
|
||||
cppflags: [
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Copyright (C) 2018 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
cc_library_static {
|
||||
name: "libdm",
|
||||
recovery_available: true,
|
||||
|
||||
export_include_dirs: ["include"],
|
||||
cflags: [
|
||||
// TODO(b/110035986): Allows us to create a skeleton of required classes
|
||||
"-Wno-unused-private-field",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"dm_table.cpp",
|
||||
"dm_target.cpp",
|
||||
"dm.cpp"
|
||||
],
|
||||
|
||||
header_libs: [
|
||||
"libbase_headers",
|
||||
"liblog_headers",
|
||||
],
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/macros.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
#include "dm.h"
|
||||
|
||||
namespace android {
|
||||
namespace dm {
|
||||
|
||||
DeviceMapper& DeviceMapper::Instance() {
|
||||
static DeviceMapper instance;
|
||||
return instance;
|
||||
}
|
||||
// Creates a new device mapper device
|
||||
bool DeviceMapper::CreateDevice(const std::string& /* name */) {
|
||||
// Creates a new device mapper device with the name passed in
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeviceMapper::DeleteDevice(const std::string& /* name */) {
|
||||
// Destroy device here first
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::unique_ptr<DmTable> DeviceMapper::table(const std::string& /* name */) const {
|
||||
// TODO(b/110035986): Return the table, as read from the kernel instead
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DmDeviceState DeviceMapper::state(const std::string& /* name */) const {
|
||||
// TODO(b/110035986): Return the state, as read from the kernel instead
|
||||
return DmDeviceState::INVALID;
|
||||
}
|
||||
|
||||
bool DeviceMapper::LoadTableAndActivate(const std::string& /* name */, const DmTable& /* table */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reads all the available device mapper targets and their corresponding
|
||||
// versions from the kernel and returns in a vector
|
||||
bool DeviceMapper::GetAvailableTargets(std::vector<DmTarget>* targets) {
|
||||
targets->clear();
|
||||
|
||||
// calculate the space needed to read a maximum of kMaxPossibleDmTargets
|
||||
uint32_t payload_size = sizeof(struct dm_target_versions);
|
||||
payload_size += DM_MAX_TYPE_NAME;
|
||||
// device mapper wants every target spec to be aligned at 8-byte boundary
|
||||
payload_size = DM_ALIGN(payload_size);
|
||||
payload_size *= kMaxPossibleDmTargets;
|
||||
|
||||
uint32_t data_size = sizeof(struct dm_ioctl) + payload_size;
|
||||
auto buffer = std::unique_ptr<void, void (*)(void*)>(calloc(1, data_size), free);
|
||||
if (buffer == nullptr) {
|
||||
LOG(ERROR) << "failed to allocate memory";
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get());
|
||||
io->data_start = sizeof(*io);
|
||||
io->data_size = data_size;
|
||||
io->version[0] = 4;
|
||||
io->version[1] = 0;
|
||||
io->version[2] = 0;
|
||||
|
||||
if (ioctl(fd_, DM_LIST_VERSIONS, io)) {
|
||||
PLOG(ERROR) << "Failed to get DM_LIST_VERSIONS from kernel";
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the provided buffer wasn't enough to list all targets, note that
|
||||
// any data beyond sizeof(*io) must not be read in this case
|
||||
if (io->flags & DM_BUFFER_FULL_FLAG) {
|
||||
LOG(INFO) << data_size << " is not enough memory to list all dm targets";
|
||||
return false;
|
||||
}
|
||||
|
||||
// if there are no targets registered, return success with empty vector
|
||||
if (io->data_size == sizeof(*io)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse each target and list the name and version
|
||||
// TODO(b/110035986): Templatize this
|
||||
uint32_t next = sizeof(*io);
|
||||
data_size = io->data_size - next;
|
||||
struct dm_target_versions* vers =
|
||||
reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) + next);
|
||||
while (next && data_size) {
|
||||
targets->emplace_back((vers));
|
||||
if (vers->next == 0) {
|
||||
break;
|
||||
}
|
||||
next += vers->next;
|
||||
data_size -= vers->next;
|
||||
vers = reinterpret_cast<struct dm_target_versions*>(static_cast<char*>(buffer.get()) + next);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Accepts a device mapper device name (like system_a, vendor_b etc) and
|
||||
// returns the path to it's device node (or symlink to the device node)
|
||||
std::string DeviceMapper::GetDmDevicePathByName(const std::string& /* name */) {
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace dm
|
||||
} // namespace android
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/macros.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dm_table.h"
|
||||
|
||||
namespace android {
|
||||
namespace dm {
|
||||
|
||||
bool DmTable::AddTarget(std::unique_ptr<DmTarget>&& /* target */) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DmTable::RemoveTarget(std::unique_ptr<DmTarget>&& /* target */) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DmTable::valid() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t DmTable::size() const {
|
||||
return valid() ? size_ : 0;
|
||||
}
|
||||
|
||||
// Returns a string represnetation of the table that is ready to be passed
|
||||
// down to the kernel for loading
|
||||
//
|
||||
// Implementation must verify there are no gaps in the table, table starts
|
||||
// with sector == 0, and iterate over each target to get its table
|
||||
// serialized.
|
||||
std::string DmTable::Serialize() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace dm
|
||||
} // namespace android
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/macros.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dm_target.h"
|
||||
|
||||
namespace android {
|
||||
namespace dm {} // namespace dm
|
||||
} // namespace android
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright 2018 Google, Inc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBDM_DM_H_
|
||||
#define _LIBDM_DM_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <dm_table.h>
|
||||
|
||||
#define DM_ALIGN_MASK (7)
|
||||
#define DM_ALIGN(x) ((x + DM_ALIGN_MASK) & ~DM_ALIGN_MASK)
|
||||
|
||||
namespace android {
|
||||
namespace dm {
|
||||
|
||||
enum class DmDeviceState { INVALID, SUSPENDED, ACTIVE };
|
||||
|
||||
class DeviceMapper final {
|
||||
public:
|
||||
// Creates a device mapper device with given name.
|
||||
// Return 'true' on success and 'false' on failure to
|
||||
// create OR if a device mapper device with the same name already
|
||||
// exists.
|
||||
// TODO(b/110035986): Make this method private and to be only
|
||||
// called through LoadTableAndActivate() below.
|
||||
bool CreateDevice(const std::string& name);
|
||||
|
||||
// Removes a device mapper device with the given name.
|
||||
// Returns 'true' on success, false otherwise.
|
||||
bool DeleteDevice(const std::string& name);
|
||||
|
||||
// Reads the device mapper table from the device with given anme and
|
||||
// returns it in a DmTable object.
|
||||
const std::unique_ptr<DmTable> table(const std::string& name) const;
|
||||
|
||||
// Returns the current state of the underlying device mapper device
|
||||
// with given name.
|
||||
// One of INVALID, SUSPENDED or ACTIVE.
|
||||
DmDeviceState state(const std::string& name) const;
|
||||
|
||||
// Loads the device mapper table from parameter into the underlying
|
||||
// device mapper device with given name and activate / resumes the device in the process.
|
||||
// If a device mapper device with the 'name', doesn't exist, it will be created.
|
||||
// Returns 'true' on success, false otherwise.
|
||||
bool LoadTableAndActivate(const std::string& name, const DmTable& table);
|
||||
|
||||
// Returns true if a list of available device mapper targets registered in the kernel was
|
||||
// successfully read and stored in 'targets'. Returns 'false' otherwise.
|
||||
bool GetAvailableTargets(std::vector<DmTarget>* targets);
|
||||
|
||||
// Returns the path to the device mapper device node in '/dev' corresponding to
|
||||
// 'name'.
|
||||
std::string GetDmDevicePathByName(const std::string& name);
|
||||
|
||||
// The only way to create a DeviceMapper object.
|
||||
static DeviceMapper& Instance();
|
||||
|
||||
~DeviceMapper() {
|
||||
if (fd_ != -1) {
|
||||
::close(fd_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Maximum possible device mapper targets registered in the kernel.
|
||||
// This is only used to read the list of targets from kernel so we allocate
|
||||
// a finite amount of memory. This limit is in no way enforced by the kernel.
|
||||
static constexpr uint32_t kMaxPossibleDmTargets = 256;
|
||||
|
||||
DeviceMapper() : fd_(-1) {
|
||||
fd_ = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
|
||||
if (fd_ < 0) {
|
||||
PLOG(ERROR) << "Failed to open device-mapper";
|
||||
}
|
||||
}
|
||||
|
||||
int fd_;
|
||||
// Non-copyable & Non-movable
|
||||
DeviceMapper(const DeviceMapper&) = delete;
|
||||
DeviceMapper& operator=(const DeviceMapper&) = delete;
|
||||
DeviceMapper& operator=(DeviceMapper&&) = delete;
|
||||
DeviceMapper(DeviceMapper&&) = delete;
|
||||
};
|
||||
|
||||
} // namespace dm
|
||||
} // namespace android
|
||||
|
||||
#endif /* _LIBDM_DM_H_ */
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2018 Google, Inc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBDM_DMTABLE_H_
|
||||
#define _LIBDM_DMTABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "dm_target.h"
|
||||
|
||||
namespace android {
|
||||
namespace dm {
|
||||
|
||||
class DmTable {
|
||||
public:
|
||||
DmTable() : size_(0){};
|
||||
|
||||
// Adds a target to the device mapper table for a range specified in the target object.
|
||||
// The function will return 'true' if the target was successfully added and doesn't overlap with
|
||||
// any of the existing targets in the table. Gaps are allowed. The final check, including
|
||||
// overlaps and gaps are done before loading the table. Returns 'false' on failure.
|
||||
bool AddTarget(std::unique_ptr<DmTarget>&& target);
|
||||
|
||||
// Removes a target from the table for the range specified in the target object. Returns 'false'
|
||||
// if the target name doesn't match with the one in the table. Returns 'true' if target is
|
||||
// successfully removed.
|
||||
bool RemoveTarget(std::unique_ptr<DmTarget>&& target);
|
||||
|
||||
// Checks the table to make sure it is valid. i.e. Checks for range overlaps, range gaps
|
||||
// and returns 'true' if the table is ready to be loaded into kernel. Returns 'false' if the
|
||||
// table is malformed.
|
||||
bool valid() const;
|
||||
|
||||
// Returns the total size represented by the table in terms of number of 512-byte sectors.
|
||||
// NOTE: This function will overlook if there are any gaps in the targets added in the table.
|
||||
uint64_t size() const;
|
||||
|
||||
// Returns the string represntation of the table that is ready to be passed into the kernel
|
||||
// as part of the DM_TABLE_LOAD ioctl.
|
||||
std::string Serialize() const;
|
||||
|
||||
~DmTable() = default;
|
||||
|
||||
private:
|
||||
// list of targets defined in this table sorted by
|
||||
// their start and end sectors.
|
||||
// Note: Overlapping targets MUST never be added in this list.
|
||||
std::vector<std::unique_ptr<DmTarget>> targets_;
|
||||
|
||||
// Total size in terms of # of sectors, as calculated by looking at the last and the first
|
||||
// target in 'target_'.
|
||||
uint64_t size_;
|
||||
};
|
||||
|
||||
} // namespace dm
|
||||
} // namespace android
|
||||
|
||||
#endif /* _LIBDM_DMTABLE_H_ */
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2018 Google, Inc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LIBDM_DMTARGET_H_
|
||||
#define _LIBDM_DMTARGET_H_
|
||||
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace android {
|
||||
namespace dm {
|
||||
|
||||
class DmTarget {
|
||||
public:
|
||||
DmTarget(const std::string& name, uint64_t start = 0, uint64_t length = 0)
|
||||
: name_(name), v0_(0), v1_(0), v2_(0), start_(start), length_(length){};
|
||||
|
||||
// Creates a DmTarget object from dm_target_version as read from kernel
|
||||
// with DM_LIST_VERSION ioctl.
|
||||
DmTarget(const struct dm_target_versions* vers) : start_(0), length_(0) {
|
||||
CHECK(vers != nullptr) << "Can't create DmTarget with dm_target_versions set to nullptr";
|
||||
v0_ = vers->version[0];
|
||||
v1_ = vers->version[1];
|
||||
v2_ = vers->version[2];
|
||||
name_ = vers->name;
|
||||
}
|
||||
|
||||
virtual ~DmTarget() = default;
|
||||
|
||||
// Returns name of the target.
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
// Returns size in number of sectors when this target is part of
|
||||
// a DmTable, return 0 otherwise.
|
||||
uint64_t size() const { return length_; }
|
||||
|
||||
// Return string representation of the device mapper target version.
|
||||
std::string version() const {
|
||||
return std::to_string(v0_) + "." + std::to_string(v1_) + "." + std::to_string(v2_);
|
||||
}
|
||||
|
||||
// Function that converts this object to a string of arguments that can
|
||||
// be passed to the kernel for adding this target in a table. Each target (e.g. verity, linear)
|
||||
// must implement this, for it to be used on a device.
|
||||
virtual std::string Serialize() const { return ""; }
|
||||
|
||||
private:
|
||||
// Name of the target.
|
||||
std::string name_;
|
||||
// Target version.
|
||||
uint32_t v0_, v1_, v2_;
|
||||
// logical sector number start and total length (in terms of 512-byte sectors) represented
|
||||
// by this target within a DmTable.
|
||||
uint64_t start_, length_;
|
||||
};
|
||||
|
||||
} // namespace dm
|
||||
} // namespace android
|
||||
|
||||
#endif /* _LIBDM_DMTARGET_H_ */
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Copyright (C) 2018 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
cc_binary {
|
||||
name: "dmctl",
|
||||
srcs: ["dmctl.cpp"],
|
||||
|
||||
static_libs: [
|
||||
"libfs_mgr",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"liblog",
|
||||
],
|
||||
|
||||
cflags: ["-Werror"],
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <dm.h>
|
||||
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using DeviceMapper = ::android::dm::DeviceMapper;
|
||||
using DmTarget = ::android::dm::DmTarget;
|
||||
|
||||
static int Usage(void) {
|
||||
std::cerr << "usage: dmctl <command> [command options]";
|
||||
std::cerr << "commands:";
|
||||
std::cerr << " create <dm-name> <dm-target> [-lo <filename>] <dm-target-args>";
|
||||
std::cerr, " delete <dm-device>";
|
||||
std::cerr, " list";
|
||||
std::cerr, " help";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int DmCreateCmdHandler(int argc, char** argv) {
|
||||
if (argc <= 1) {
|
||||
std::cerr << "DmCreateCmdHandler: Invalid arguments";
|
||||
if (argc > 0) std::cerr << " args: " << argv[0];
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Parse Everything first to make sure we have everything we need.
|
||||
std::string devname = argv[0];
|
||||
DeviceMapper& dm = DeviceMapper::Instance();
|
||||
std::vector<DmTarget> targets;
|
||||
if (!dm.GetAvailableTargets(&targets)) {
|
||||
std::cerr << "Failed to read available device mapper targets";
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (targets.empty()) {
|
||||
std::cerr << "zero device mapper targets available";
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
for (const auto& target : targets) {
|
||||
if (target.name() == argv[1]) {
|
||||
// TODO(b/110035986) : Create the target here, return success for now.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << "Invalid or non-existing target : " << argv[1];
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int DmDeleteCmdHandler(int argc, char** argv) {
|
||||
std::cout << "DmDeleteCmdHandler:" << std::endl;
|
||||
std::cout << " args:" << std::endl;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
std::cout << " " << argv[i] << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DmListCmdHandler(int /* argc */, char** /* argv */) {
|
||||
std::cout << "Available Device Mapper Targets:" << std::endl;
|
||||
|
||||
DeviceMapper& dm = DeviceMapper::Instance();
|
||||
std::vector<DmTarget> targets;
|
||||
if (!dm.GetAvailableTargets(&targets)) {
|
||||
std::cerr << "Failed to read available device mapper targets";
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (targets.empty()) {
|
||||
std::cout << " <empty>" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const auto& target : targets) {
|
||||
std::cout << std::left << std::setw(20) << target.name() << " : " << target.version()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HelpCmdHandler(int /* argc */, char** /* argv */) {
|
||||
Usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
|
||||
{"create", DmCreateCmdHandler},
|
||||
{"delete", DmDeleteCmdHandler},
|
||||
{"list", DmListCmdHandler},
|
||||
{"help", HelpCmdHandler},
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
android::base::InitLogging(argv, &android::base::StderrLogger);
|
||||
if (argc < 2) {
|
||||
return Usage();
|
||||
}
|
||||
|
||||
for (const auto& cmd : cmdmap) {
|
||||
if (cmd.first == argv[1]) {
|
||||
return cmd.second(argc - 2, argv + 2);
|
||||
}
|
||||
}
|
||||
|
||||
return Usage();
|
||||
}
|
Loading…
Reference in New Issue