Pump up lptools

- Add `free` command to know how big a partition can be created
- `create` command now properly return errors
- Add lptools_static, suitable for use from recovery
- Add clear-cow and unlimited-group to help expand current group's
  beyond original expectations
This commit is contained in:
Pierre-Hugues Husson 2021-03-20 19:57:52 +01:00
parent 29154150b0
commit abec25d226
2 changed files with 122 additions and 5 deletions

View File

@ -198,6 +198,8 @@ cc_binary {
"libfs_mgr", "libfs_mgr",
"libutils", "libutils",
"libcutils", "libcutils",
"android.hardware.boot@1.1",
"libhidlbase",
], ],
static_libs: [ static_libs: [
"libdm", "libdm",
@ -210,6 +212,36 @@ cc_binary {
], ],
} }
cc_binary {
name: "lptools_static",
cflags: [
"-Werror",
"-Wextra",
"-DLPTOOLS_STATIC",
],
device_supported: true,
shared_libs: [
"libcrypto",
],
static_libs: [
"libbase",
"liblog",
"liblp",
"libsparse",
"libfs_mgr",
"libutils",
"libcutils",
"libdm",
"libext4_utils",
],
srcs: [
"lptools.cc",
],
cppflags: [
"-D_FILE_OFFSET_BITS=64",
],
}
cc_binary { cc_binary {
name: "sec-camera-list", name: "sec-camera-list",
srcs: [ srcs: [

View File

@ -40,6 +40,11 @@
#include <fs_mgr_dm_linear.h> #include <fs_mgr_dm_linear.h>
#include <libdm/dm.h> #include <libdm/dm.h>
#ifndef LPTOOLS_STATIC
#include <android/hardware/boot/1.1/IBootControl.h>
#include <android/hardware/boot/1.1/types.h>
#endif
using namespace android; using namespace android;
using namespace android::fs_mgr; using namespace android::fs_mgr;
@ -77,8 +82,25 @@ void saveToDisk(std::unique_ptr<MetadataBuilder> builder) {
} }
} }
inline bool ends_with(std::string const & value, std::string const & ending)
{
if (ending.size() > value.size()) return false;
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
std::string findGroup(std::unique_ptr<MetadataBuilder>& builder) { std::string findGroup(std::unique_ptr<MetadataBuilder>& builder) {
auto groups = builder->ListGroups(); auto groups = builder->ListGroups();
auto partitionName = "system" + ::android::base::GetProperty("ro.boot.slot_suffix", "");
for(auto groupName: groups) {
auto partitions = builder->ListPartitionsInGroup(groupName);
for (const auto& partition : partitions) {
if(partition->name() == partitionName) {
return groupName;
}
}
}
std::string maxGroup = ""; std::string maxGroup = "";
uint64_t maxGroupSize = 0; uint64_t maxGroupSize = 0;
for(auto groupName: groups) { for(auto groupName: groups) {
@ -116,7 +138,9 @@ int main(int argc, char **argv) {
exit(1); exit(1);
} }
partition = builder->AddPartition(partName, group, 0); partition = builder->AddPartition(partName, group, 0);
std::cout << "Growing partition " << builder->ResizePartition(partition, size) << std::endl; auto result = builder->ResizePartition(partition, size);
std::cout << "Growing partition " << result << std::endl;
if(!result) return 1;
saveToDisk(std::move(builder)); saveToDisk(std::move(builder));
std::string dmPath; std::string dmPath;
@ -163,13 +187,19 @@ int main(int argc, char **argv) {
auto src = argv[2]; auto src = argv[2];
auto dst = argv[3]; auto dst = argv[3];
auto srcPartition = builder->FindPartition(src); auto srcPartition = builder->FindPartition(src);
if(srcPartition == nullptr) {
srcPartition = builder->FindPartition(src + ::android::base::GetProperty("ro.boot.slot_suffix", ""));
}
auto dstPartition = builder->FindPartition(dst);
if(dstPartition == nullptr) {
dstPartition = builder->FindPartition(dst + ::android::base::GetProperty("ro.boot.slot_suffix", ""));
}
std::vector<std::unique_ptr<Extent>> originalExtents; std::vector<std::unique_ptr<Extent>> originalExtents;
const auto& extents = srcPartition->extents(); const auto& extents = srcPartition->extents();
for(unsigned i=0; i<extents.size(); i++) { for(unsigned i=0; i<extents.size(); i++) {
const auto& extend = extents[i]; const auto& extend = extents[i];
auto linear = extend->AsLinearExtent(); auto linear = extend->AsLinearExtent();
std::cerr << (linear != nullptr) << std::endl;
if(linear != nullptr) { if(linear != nullptr) {
auto copyLinear = std::make_unique<LinearExtent>(linear->num_sectors(), linear->device_index(), linear->physical_sector()); auto copyLinear = std::make_unique<LinearExtent>(linear->num_sectors(), linear->device_index(), linear->physical_sector());
originalExtents.push_back(std::move(copyLinear)); originalExtents.push_back(std::move(copyLinear));
@ -178,9 +208,9 @@ int main(int argc, char **argv) {
originalExtents.push_back(std::move(copyZero)); originalExtents.push_back(std::move(copyZero));
} }
} }
builder->RemovePartition(src); builder->RemovePartition(srcPartition->name());
builder->RemovePartition(dst); builder->RemovePartition(dstPartition->name());
auto newDstPartition = builder->AddPartition(dst, group, 0); auto newDstPartition = builder->AddPartition(dstPartition->name(), group, 0);
for(auto&& extent: originalExtents) { for(auto&& extent: originalExtents) {
newDstPartition->AddExtent(std::move(extent)); newDstPartition->AddExtent(std::move(extent));
} }
@ -214,6 +244,61 @@ int main(int argc, char **argv) {
android::fs_mgr::DestroyLogicalPartition(partName); android::fs_mgr::DestroyLogicalPartition(partName);
} }
exit(0); exit(0);
} else if(strcmp(argv[1], "free") == 0) {
if(argc != 2) {
std::cerr << "Usage: " << argv[0] << " free" << std::endl;
exit(1);
}
auto groupO = builder->FindGroup(group);
uint64_t maxSize = groupO->maximum_size();
uint64_t total = 0;
auto partitions = builder->ListPartitionsInGroup(group);
for (const auto& partition : partitions) {
total += partition->BytesOnDisk();
}
uint64_t groupAllocatable = maxSize - total;
uint64_t superFreeSpace = builder->AllocatableSpace() - builder->UsedSpace();
if(groupAllocatable > superFreeSpace || maxSize == 0)
groupAllocatable = superFreeSpace;
printf("Free space: %" PRIu64 "\n", groupAllocatable);
exit(0);
} else if(strcmp(argv[1], "unlimited-group") == 0) {
builder->ChangeGroupSize(group, 0);
saveToDisk(std::move(builder));
return 0;
} else if(strcmp(argv[1], "clear-cow") == 0) {
#ifndef LPTOOLS_STATIC
// Ensure this is a V AB device, and that no merging is taking place (merging? in gsi? uh)
auto svc1_1 = ::android::hardware::boot::V1_1::IBootControl::tryGetService();
if(svc1_1 == nullptr) {
std::cerr << "Couldn't get a bootcontrol HAL. You can clear cow only on V AB devices" << std::endl;
return 1;
}
auto mergeStatus = svc1_1->getSnapshotMergeStatus();
if(mergeStatus != ::android::hardware::boot::V1_1::MergeStatus::NONE) {
std::cerr << "Merge status is NOT none, meaning a merge is pending. Clearing COW isn't safe" << std::endl;
return 1;
}
#endif
uint64_t superFreeSpace = builder->AllocatableSpace() - builder->UsedSpace();
std::cerr << "Super allocatable " << superFreeSpace << std::endl;
uint64_t total = 0;
auto partitions = builder->ListPartitionsInGroup("cow");
for (const auto& partition : partitions) {
std::cout << "Deleting partition? " << partition->name() << std::endl;
if(ends_with(partition->name(), "-cow")) {
std::cout << "Deleting partition " << partition->name() << std::endl;
builder->RemovePartition(partition->name());
}
}
saveToDisk(std::move(builder));
return 0;
} }
return 0; return 0;