pmt: first codes.

This commit is contained in:
2025-07-21 12:08:45 +03:00
commit d65867c249
22 changed files with 2542 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
/*
Copyright 2025 Yağız Zengin
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 <string>
#include <optional>
#include <filesystem>
#include <libpartition_map/lib.hpp>
namespace PartitionMap {
Map_t basic_partition_map_builder::getAll() const
{
_map_build_check();
return _current_map;
}
std::optional<std::pair<uint64_t, bool>> basic_partition_map_builder::get(const std::string_view name) const
{
_map_build_check();
if (!_current_map.find(name)) return std::nullopt;
return std::make_pair(_current_map.get_size(name), _current_map.is_logical(name));
}
std::optional<std::list<std::string>> basic_partition_map_builder::getLogicalPartitionList() const
{
_map_build_check();
std::list<std::string> logicals;
for (const auto& [name, props] : _current_map)
if (props.isLogical) logicals.push_back(name);
if (logicals.empty()) return std::nullopt;
return logicals;
}
std::optional<std::list<std::string>> basic_partition_map_builder::getPhysicalPartitionList() const
{
_map_build_check();
std::list<std::string> physicals;
for (const auto& [name, props] : _current_map)
if (!props.isLogical) physicals.push_back(name);
if (physicals.empty()) return std::nullopt;
return physicals;
}
std::string basic_partition_map_builder::getRealLinkPathOf(const std::string_view name) const
{
_map_build_check();
if (!_current_map.find(name)) return {};
return std::string(_workdir + "/" + name.data());
}
std::string basic_partition_map_builder::getRealPathOf(const std::string_view name) const
{
_map_build_check();
std::string full = _workdir + "/" + name.data();
if (!_current_map.find(name)
|| !std::filesystem::is_symlink(full))
return {};
return std::filesystem::read_symlink(full);
}
std::string basic_partition_map_builder::getCurrentWorkDir() const
{
return _workdir;
}
} // namespace PartitionMap

View File

@@ -0,0 +1,209 @@
/*
Copyright 2025 Yağız Zengin
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 <iostream>
#include <vector>
#include <filesystem>
#include <memory>
#include <vector>
#include <algorithm>
#include <array>
#include <string>
#include <string_view>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <libpartition_map/lib.hpp>
#include <string.h>
#include <unistd.h>
static constexpr std::array<std::string_view, 3> defaultEntryList = {
"/dev/block/by-name",
"/dev/block/bootdevice/by-name",
"/dev/block/platform/bootdevice/by-name"
};
namespace PartitionMap {
bool basic_partition_map_builder::_is_real_block_dir(const std::string_view path) const
{
if (path.find("/block/") == std::string::npos) return false;
return true;
}
Map_t basic_partition_map_builder::_build_map(std::string_view path, bool logical)
{
Map_t map;
std::vector<std::filesystem::directory_entry> entries{std::filesystem::directory_iterator(path), std::filesystem::directory_iterator()};
std::sort(entries.begin(), entries.end(), [](const auto& a, const auto& b) {
return a.path().filename() < b.path().filename();
});
for (const auto& entry : entries) {
if (entry.path().filename() != "by-uuid"
&& std::string(entry.path()).find("com.") == std::string::npos)
map.insert(entry.path().filename().string(), _get_size(entry.path()), logical);
}
return map;
}
void basic_partition_map_builder::_insert_logicals(Map_t&& logicals)
{
_current_map.merge(logicals);
}
void basic_partition_map_builder::_map_build_check() const
{
if (!_map_builded)
throw Error("Please build partition map before!");
}
uint64_t basic_partition_map_builder::_get_size(const std::string path)
{
std::string real = std::filesystem::read_symlink(path);
int fd = open(real.data(), O_RDONLY);
if (fd < 0)
throw Error("Cannot open %s: %s", real.data(), strerror(errno));
uint64_t size = 0;
if (ioctl(fd, BLKGETSIZE64, &size) != 0) {
close(fd);
throw Error("ioctl() process failed for %s: %s", real.data(), strerror(errno));
}
close(fd);
return size;
}
basic_partition_map_builder::basic_partition_map_builder()
{
for (const auto& path : defaultEntryList) {
if (std::filesystem::exists(path)) {
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
continue;
} else {
_workdir = path;
break;
}
}
}
if (_current_map.empty())
throw Error("Cannot build map by any default search entry.");
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
basic_partition_map_builder::basic_partition_map_builder(const std::string_view path)
{
if (std::filesystem::exists(path)) {
_is_real_block_dir(path);
_current_map = _build_map(path);
if (_current_map.empty()) _any_generating_error = true;
else _workdir = path;
} else
throw Error("Cannot find directory: %s. Cannot build partition map!", path.data());
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
}
bool basic_partition_map_builder::hasPartition(const std::string_view name) const
{
_map_build_check();
return _current_map.find(name);
}
bool basic_partition_map_builder::isLogical(const std::string_view name) const
{
_map_build_check();
return _current_map.is_logical(name);
}
void basic_partition_map_builder::clear()
{
_current_map.clear();
_workdir.clear();
_any_generating_error = false;
}
bool basic_partition_map_builder::readDirectory(const std::string_view path)
{
_map_builded = false;
if (std::filesystem::exists(path)) {
if (!_is_real_block_dir(path)) return false;
_current_map = _build_map(path);
if (_current_map.empty()) {
_any_generating_error = true;
return false;
} else _workdir = path;
} else
throw Error("Cannot find directory: %s. Cannot build partition map!", path.data());
_insert_logicals(_build_map("/dev/block/mapper", true));
_map_builded = true;
return true;
}
bool basic_partition_map_builder::empty() const
{
_map_build_check();
return _current_map.empty();
}
uint64_t basic_partition_map_builder::sizeOf(const std::string_view name) const
{
_map_build_check();
return _current_map.get_size(name);
}
bool operator==(basic_partition_map_builder& lhs, basic_partition_map_builder& rhs)
{
return lhs._current_map == rhs._current_map;
}
bool operator!=(basic_partition_map_builder& lhs, basic_partition_map_builder& rhs)
{
return !(lhs == rhs);
}
basic_partition_map_builder::operator bool() const
{
return !this->_any_generating_error;
}
bool basic_partition_map_builder::operator!() const
{
return this->_any_generating_error;
}
std::string getLibVersion()
{
return std::string(
std::to_string(LIBPARTITION_MAP_MAJOR) + "."
+ std::to_string(LIBPARTITION_MAP_MINOR) + "."
+ std::to_string(LIBPARTITION_MAP_PATCH)
);
}
} // namespace PartitionMap

View File

@@ -0,0 +1,278 @@
/*
Copyright 2025 Yağız Zengin
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 <string>
#include <cstdint>
#include <utility>
#include <libpartition_map/lib.hpp>
namespace PartitionMap {
basic_partition_map::iterator::iterator(_entry* p) : ptr(p) {}
auto basic_partition_map::iterator::operator*() -> std::pair<std::string&, decltype(_entry::props)&>
{
return {ptr->name, ptr->props};
}
_entry* basic_partition_map::iterator::operator->()
{
return ptr;
}
basic_partition_map::iterator& basic_partition_map::iterator::operator++()
{
++ptr;
return *this;
}
basic_partition_map::iterator basic_partition_map::iterator::operator++(int)
{
basic_partition_map::iterator tmp = *this;
++ptr;
return tmp;
}
bool basic_partition_map::iterator::operator==(const basic_partition_map::iterator& other) const
{
return ptr == other.ptr;
}
bool basic_partition_map::iterator::operator!=(const basic_partition_map::iterator& other) const
{
return ptr != other.ptr;
}
basic_partition_map::constant_iterator::constant_iterator(const _entry* p) : ptr(p) {}
auto basic_partition_map::constant_iterator::operator*() const -> std::pair<const std::string&, const decltype(_entry::props)&> {
return {ptr->name, ptr->props};
}
const _entry* basic_partition_map::constant_iterator::operator->() const
{
return ptr;
}
basic_partition_map::constant_iterator& basic_partition_map::constant_iterator::operator++()
{
++ptr;
return *this;
}
basic_partition_map::constant_iterator basic_partition_map::constant_iterator::operator++(int)
{
basic_partition_map::constant_iterator tmp = *this;
++ptr;
return tmp;
}
bool basic_partition_map::constant_iterator::operator==(const basic_partition_map::constant_iterator& other) const
{
return ptr == other.ptr;
}
bool basic_partition_map::constant_iterator::operator!=(const basic_partition_map::constant_iterator& other) const
{
return ptr != other.ptr;
}
void basic_partition_map::_resize_map()
{
size_t new_capacity = _capacity * 2;
_entry* new_data = new _entry[new_capacity];
for (size_t i = 0; i < _count; i++) new_data[i] = _data[i];
delete[] _data;
_data = new_data;
_capacity = new_capacity;
}
int basic_partition_map::_index_of(const std::string_view name) const
{
for (size_t i = 0; i < _count; i++) {
if (name == _data[i].name) return (int)i;
}
return 0;
}
basic_partition_map::basic_partition_map(const std::string name, uint64_t size, bool logical)
{
_data = new _entry[_capacity];
insert(name, size, logical);
}
basic_partition_map::basic_partition_map(const basic_partition_map& other) :
_data(new _entry[other._capacity]),
_count(other._count),
_capacity(other._capacity)
{
std::copy(other._data, other._data + _count, _data);
}
basic_partition_map::basic_partition_map() : _count(0), _capacity(6)
{
_data = new _entry[_capacity];
}
basic_partition_map::~basic_partition_map()
{
delete[] _data;
}
bool basic_partition_map::insert(const std::string name, uint64_t size, bool logical)
{
if (name == _data[_index_of(name)].name) return false;
if (_count == _capacity) _resize_map();
_data[_count++] = {name, {size, logical}};
return true;
}
void basic_partition_map::merge(const basic_partition_map& map)
{
for (const auto& [name, props] : map)
insert(name, props.size, props.isLogical);
}
uint64_t basic_partition_map::get_size(const std::string_view name) const
{
int pos = _index_of(name);
if (name == _data[pos].name) return _data[pos].props.size;
return 0;
}
bool basic_partition_map::is_logical(const std::string_view name) const
{
int pos = _index_of(name);
if (name == _data[pos].name) return _data[pos].props.isLogical;
return false;
}
basic_partition_map::_returnable_entry basic_partition_map::get_all(const std::string_view name) const
{
int pos = _index_of(name);
if (name == _data[pos].name)
return _returnable_entry{_data[pos].props.size, _data[pos].props.isLogical};
return _returnable_entry{};
}
bool basic_partition_map::find(const std::string_view name) const
{
if (name == _data[_index_of(name)].name) return true;
return false;
}
std::string basic_partition_map::find_(const std::string name) const
{
if (name == _data[_index_of(name)].name) return name;
return {};
}
size_t basic_partition_map::size() const
{
return _count;
}
bool basic_partition_map::empty() const
{
if (_count > 0) return false;
return true;
}
void basic_partition_map::clear()
{
delete[] _data;
_count = 0;
_capacity = 6;
_data = new _entry[_capacity];
}
basic_partition_map& basic_partition_map::operator=(const basic_partition_map& map)
{
if (this != &map) {
delete[] _data;
_capacity = map._capacity;
_count = map._count;
_data = new _entry[_capacity];
std::copy(map._data, map._data + _count, _data);
}
return *this;
}
bool basic_partition_map::operator==(const basic_partition_map& other) const
{
if (this->_capacity != other._capacity
|| this->_count != other._count)
return false;
for (size_t i = 0; i < _count; i++)
if (_data[i].name == other._data[i].name
&& _data[i].props.size == other._data[i].props.size
&& _data[i].props.isLogical == other._data[i].props.isLogical)
continue;
else
return false;
return true;
}
bool basic_partition_map::operator!=(const basic_partition_map& other) const
{
return !(*this == other);
}
basic_partition_map::iterator basic_partition_map::begin()
{
return basic_partition_map::iterator(_data);
}
basic_partition_map::iterator basic_partition_map::end()
{
return basic_partition_map::iterator(_data + _count);
}
basic_partition_map::constant_iterator basic_partition_map::begin() const
{
return basic_partition_map::constant_iterator(_data);
}
basic_partition_map::constant_iterator basic_partition_map::cbegin() const
{
return basic_partition_map::constant_iterator(_data);
}
basic_partition_map::constant_iterator basic_partition_map::end() const
{
return basic_partition_map::constant_iterator(_data + _count);
}
basic_partition_map::constant_iterator basic_partition_map::cend() const
{
return basic_partition_map::constant_iterator(_data + _count);
}
} // namespace PartitionMap