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

12
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"configurations": [
{
"includePath": [
"${workspaceFolder}/srclib/libhelper/include",
"${workspaceFolder}/srclib/libpartition_map/include",
"${workspaceFolder}/include"
]
}
],
"version": 4
}

36
CMakeLists.txt Normal file
View File

@@ -0,0 +1,36 @@
#
# 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.
#
# Project info
cmake_minimum_required(VERSION 3.10)
project(pmt VERSION 1.0.0)
set(DEBUG_FLAGS -gdwarf-5 -fsanitize=address -fstack-protector -O0)
# Add compiler flag based on build type
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DEBUG_FLAGS}")
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} ${DEBUG_FLAGS}")
endif()
# Add include directories
include_directories(include srclib/libhelper/include srclib/libpartition_map/include)
# Add libraries
add_subdirectory(srclib/libhelper)
add_subdirectory(srclib/libpartition_map)
# NOTE: pmt is not ready, this CMakeFiles.txt only builds libraries

92
build.sh Normal file
View File

@@ -0,0 +1,92 @@
#!/usr/bin/bash
#
# 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.
#
set -e
BUILD_64="build_arm64-v8a"
BUILD_32="build_armeabi-v7a"
THIS="$(basename $0)"
echo()
{
command echo "[$THIS]: $*"
}
checks()
{
if [ -z "$ANDROID_NDK" ]; then
echo "Please set ANDROID_NDK variable as your NDK path."
exit 1
fi
if [ ! -f /usr/bin/cmake ] && [ ! -f /bin/cmake ]; then
echo "Please verify your CMake installation."
exit 1
fi
}
clean()
{
echo "Cleaning workspace."
rm -rf $BUILD_32 $BUILD_64 srclib/libhelper/tests/dir srclib/libhelper/tests/linkdir srclib/libhelper/tests/file.txt
}
build()
{
mkdir -p $BUILD_64 $BUILD_32
command echo -e "BUILD INFO:
ARCHS: arm64-v8a armeabi-v7a
ANDROID_PLATFORM: $ANDROID_PLATFORM
ANDROID_TOOLCHAIN_FILE: $ANDROID_NDK/build/cmake/android.toolchain.cmake\n"
echo "Configuring for arm64-v8a..."
cmake -B $BUILD_64 -S . $1 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=$ANDROID_PLATFORM
echo "Configuring for armeabi-v7a..."
cmake -B $BUILD_32 -S . $1 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=armeabi-v7a \
-DANDROID_PLATFORM=$ANDROID_PLATFORM
echo "Building arm64-v8a artifacts..."
cmake --build $BUILD_64
echo "arm64-v8a build complete, artifacts: $PWD/$BUILD_64"
echo "Building armeabi-v7a artifacts..."
cmake --build $BUILD_32
echo "armeabi-v7a build complete, artifacts: $PWD/$BUILD_32"
}
if [ $# -eq 0 ]; then
command echo "Usage: $0 build|rebuild|clean [EXTRA_CMAKE_FLAGS] [ANDROID_PLATFORM=SELECTED_ANDROID_PLATFORM]"
exit 1
fi
if [ -z $ANDROID_PLATFORM ]; then ANDROID_PLATFORM="android-21"; fi
checks
case $1 in
"build") build $2;;
"clean") clean ;;
"rebuild") clean; build $2;;
*)
command echo "$0: Unknown argument: $1"
exit 1 ;;
esac

View File

@@ -0,0 +1,30 @@
/*
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.
*/
#ifndef LIBPMT_LIB_HPP
#define LIBPMT_LIB_HPP
#include <list>
#include <string>
#include <string_view>
#include <functional>
#include <vector>
#include <libpartition_map/lib.hpp>
#include <libhelper/lib.hpp>
namespace PartitionManager {} // namespace PartitionManager
#endif // #ifndef LIBPMT_LIB_HPP

0
src/.placeholder Normal file
View File

View File

@@ -0,0 +1,41 @@
#
# 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.
#
set(LIBHELPER_FLAGS -Wall -DLIB_BUILD_MODE)
set(LIBHELPER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/Checkers.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Classes.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/FileUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Sha256.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Utilities.cpp
)
# Add targets
add_library(helper_shared SHARED ${LIBHELPER_SOURCES})
add_library(helper_static STATIC ${LIBHELPER_SOURCES})
add_executable(libhelper_test tests/test.cpp)
# Set compiler flags
target_compile_options(helper_shared PRIVATE ${LIBHELPER_FLAGS})
target_compile_options(helper_static PRIVATE ${LIBHELPER_FLAGS})
target_compile_options(libhelper_test PRIVATE ${LIBHELPER_FLAGS})
target_link_libraries(libhelper_test PRIVATE helper_shared)
target_link_options(libhelper_test PRIVATE "LINKER:-rpath,/data/data/com.termux/files/usr/lib")
target_link_options(helper_shared PRIVATE "LINKER:-rpath,/data/data/com.termux/files/usr/lib")
# Set appropriate output names
set_target_properties(helper_shared PROPERTIES OUTPUT_NAME "helper")
set_target_properties(helper_static PROPERTIES OUTPUT_NAME "helper")

View File

@@ -0,0 +1,186 @@
/*
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.
*/
#ifndef LIBHELPER_LIB_HPP
#define LIBHELPER_LIB_HPP
#define LIBHELPER_MAJOR 1
#define LIBHELPER_MINOR 0
#define LIBHELPER_PATCH 0
#include <string>
#include <string_view>
#include <sstream>
#include <exception>
#include <optional>
#ifndef ONLY_HELPER_MACROS
enum LogLevels {
INFO = (int)'I',
WARNING = (int)'W',
ERROR = (int)'E',
ABORT = (int)'A'
};
constexpr mode_t DEFAULT_FILE_PERMS = 0644;
constexpr mode_t DEFAULT_DIR_PERMS = 0755;
constexpr int YES = 1;
constexpr int NO = 0;
namespace Helper {
// Logging
class Logger {
private:
LogLevels _level;
std::ostringstream _oss;
const char *_logFile, *_program_name, *_file;
int _line;
public:
Logger(LogLevels level, const char* file, const char* name, const char* sfile, int line);
~Logger();
template <typename T>
Logger& operator<<(const T& msg)
{
_oss << msg;
return *this;
}
Logger& operator<<(std::ostream& (*msg)(std::ostream&));
};
class LoggingProperties {
public:
static std::string_view FILE, NAME;
static bool PRINT;
static void set(std::string_view name, std::string_view file);
static void setProgramName(std::string_view name);
static void setLogFile(std::string_view file);
static void setPrinting(int state);
static void reset();
};
// Throwable error class
class Error : public std::exception {
private:
std::string _message;
public:
Error(const char* format, ...);
const char* what() const noexcept override;
};
// Checkers
bool hasSuperUser();
bool isExists(const std::string_view entry);
bool fileIsExists(const std::string_view file);
bool directoryIsExists(const std::string_view directory);
bool linkIsExists(const std::string_view entry);
bool isLink(const std::string_view entry);
bool isSymbolicLink(const std::string_view entry);
bool isHardLink(const std::string_view entry);
bool areLinked(const std::string_view entry1, const std::string_view entry2);
// File I/O
bool writeFile(const std::string_view file, const std::string_view text);
std::optional<std::string> readFile(const std::string_view file);
// Creators
bool makeDirectory(const std::string_view path);
bool makeRecursiveDirectory(const std::string_view paths);
bool createFile(const std::string_view path);
bool createSymlink(const std::string_view entry1, const std::string_view entry2);
// Removers
bool eraseEntry(const std::string_view entry);
bool eraseDirectoryRecursive(const std::string_view directory);
// Getters
size_t fileSize(const std::string_view file);
std::string_view readSymlink(const std::string_view entry);
// SHA-256
bool sha256Compare(const std::string_view file1, const std::string_view file2);
std::optional<std::string_view> sha256Of(const std::string_view path);
// Utilities
bool copyFile(const std::string_view file, const std::string_view dest);
bool runCommand(const std::string_view cmd);
bool confirmPropt(const std::string_view message);
std::string currentWorkingDirectory();
std::string currentDate();
std::string currentTime();
std::string runCommandWithOutput(const std::string_view cmd);
std::string pathJoin(std::string base, std::string relative);
std::string pathBasename(const std::string_view entry);
std::string pathDirname(const std::string_view entry);
// Library-specif
std::string getLibVersion();
} // namespace Helper
#endif // #ifndef ONLY_HELPER_MACROS
#define KB(x) (x * 1024) // KB(8) = 8192 (8 * 1024)
#define MB(x) (KB(x) * 1024) // MB(4) = 4194304 (KB(4) * 1024)
#define GB(x) (MB(x) * 1024) // GB(1) = 1073741824 (MB(1) * 1024)
#define STYLE_RESET "\033[0m"
#define BOLD "\033[1m"
#define FAINT "\033[2m"
#define ITALIC "\033[3m"
#define UNDERLINE "\033[4m"
#define BLINC "\033[5m"
#define FAST_BLINC "\033[6m"
#define STRIKE_THROUGHT "\033[9m"
#define NO_UNDERLINE "\033[24m"
#define NO_BLINC "\033[25m"
#define RED "\033[31m"
#define GREEN "\033[32m"
#define YELLOW "\033[33m"
#ifndef NO_C_TYPE_HANDLERS
// ABORT(message), ex: ABORT("memory error!\n")
#define ABORT(msg) \
do { \
fprintf(stderr, "%s%sCRITICAL ERROR%s: %s\nAborting...\n", BOLD, RED, STYLE_RESET, msg); \
abort(); \
} while (0)
// ERROR(message, exit), ex: ERROR("an error occured.\n", 1)
#define ERROR(msg, code) \
do { \
fprintf(stderr, "%s%sERROR%s: %s", BOLD, RED, STYLE_RESET, msg); \
exit(code); \
} while (0)
// WARNING(message), ex: WARNING("using default setting.\n")
#define WARNING(msg) \
fprintf(stderr, "%s%sWARNING%s: %s", BOLD, YELLOW, STYLE_RESET, msg);
// INFO(message), ex: INFO("operation ended.\n")
#define INFO(msg) \
fprintf(stdout, "%s%sINFO%s: %s", BOLD, GREEN, STYLE_RESET, msg);
#endif // #ifndef NO_C_TYPE_HANDLERS
#define LOG(level) Helper::Logger(level, Helper::LoggingProperties::FILE.data(), Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
#endif // #ifndef LIBHELPER_LIB_HPP

View File

@@ -0,0 +1,377 @@
/*
The MIT License (MIT)
Copyright (C) 2017 okdshin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef PICOSHA2_H
#define PICOSHA2_H
// picosha2:20140213
#ifndef PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR
#define PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR \
1048576 //=1024*1024: default is 1MB memory
#endif
#include <algorithm>
#include <cassert>
#include <iterator>
#include <sstream>
#include <vector>
#include <fstream>
namespace picosha2 {
typedef unsigned long word_t;
typedef unsigned char byte_t;
static const size_t k_digest_size = 32;
namespace detail {
inline byte_t mask_8bit(byte_t x) { return x & 0xff; }
inline word_t mask_32bit(word_t x) { return x & 0xffffffff; }
const word_t add_constant[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
const word_t initial_message_digest[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372,
0xa54ff53a, 0x510e527f, 0x9b05688c,
0x1f83d9ab, 0x5be0cd19};
inline word_t ch(word_t x, word_t y, word_t z) { return (x & y) ^ ((~x) & z); }
inline word_t maj(word_t x, word_t y, word_t z) {
return (x & y) ^ (x & z) ^ (y & z);
}
inline word_t rotr(word_t x, std::size_t n) {
assert(n < 32);
return mask_32bit((x >> n) | (x << (32 - n)));
}
inline word_t bsig0(word_t x) { return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); }
inline word_t bsig1(word_t x) { return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); }
inline word_t shr(word_t x, std::size_t n) {
assert(n < 32);
return x >> n;
}
inline word_t ssig0(word_t x) { return rotr(x, 7) ^ rotr(x, 18) ^ shr(x, 3); }
inline word_t ssig1(word_t x) { return rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10); }
template <typename RaIter1, typename RaIter2>
void hash256_block(RaIter1 message_digest, RaIter2 first, RaIter2 last) {
assert(first + 64 == last);
static_cast<void>(last); // for avoiding unused-variable warning
word_t w[64];
std::fill(w, w + 64, word_t(0));
for (std::size_t i = 0; i < 16; ++i) {
w[i] = (static_cast<word_t>(mask_8bit(*(first + i * 4))) << 24) |
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 1))) << 16) |
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 2))) << 8) |
(static_cast<word_t>(mask_8bit(*(first + i * 4 + 3))));
}
for (std::size_t i = 16; i < 64; ++i) {
w[i] = mask_32bit(ssig1(w[i - 2]) + w[i - 7] + ssig0(w[i - 15]) +
w[i - 16]);
}
word_t a = *message_digest;
word_t b = *(message_digest + 1);
word_t c = *(message_digest + 2);
word_t d = *(message_digest + 3);
word_t e = *(message_digest + 4);
word_t f = *(message_digest + 5);
word_t g = *(message_digest + 6);
word_t h = *(message_digest + 7);
for (std::size_t i = 0; i < 64; ++i) {
word_t temp1 = h + bsig1(e) + ch(e, f, g) + add_constant[i] + w[i];
word_t temp2 = bsig0(a) + maj(a, b, c);
h = g;
g = f;
f = e;
e = mask_32bit(d + temp1);
d = c;
c = b;
b = a;
a = mask_32bit(temp1 + temp2);
}
*message_digest += a;
*(message_digest + 1) += b;
*(message_digest + 2) += c;
*(message_digest + 3) += d;
*(message_digest + 4) += e;
*(message_digest + 5) += f;
*(message_digest + 6) += g;
*(message_digest + 7) += h;
for (std::size_t i = 0; i < 8; ++i) {
*(message_digest + i) = mask_32bit(*(message_digest + i));
}
}
} // namespace detail
template <typename InIter>
void output_hex(InIter first, InIter last, std::ostream& os) {
os.setf(std::ios::hex, std::ios::basefield);
while (first != last) {
os.width(2);
os.fill('0');
os << static_cast<unsigned int>(*first);
++first;
}
os.setf(std::ios::dec, std::ios::basefield);
}
template <typename InIter>
void bytes_to_hex_string(InIter first, InIter last, std::string& hex_str) {
std::ostringstream oss;
output_hex(first, last, oss);
hex_str.assign(oss.str());
}
template <typename InContainer>
void bytes_to_hex_string(const InContainer& bytes, std::string& hex_str) {
bytes_to_hex_string(bytes.begin(), bytes.end(), hex_str);
}
template <typename InIter>
std::string bytes_to_hex_string(InIter first, InIter last) {
std::string hex_str;
bytes_to_hex_string(first, last, hex_str);
return hex_str;
}
template <typename InContainer>
std::string bytes_to_hex_string(const InContainer& bytes) {
std::string hex_str;
bytes_to_hex_string(bytes, hex_str);
return hex_str;
}
class hash256_one_by_one {
public:
hash256_one_by_one() { init(); }
void init() {
buffer_.clear();
std::fill(data_length_digits_, data_length_digits_ + 4, word_t(0));
std::copy(detail::initial_message_digest,
detail::initial_message_digest + 8, h_);
}
template <typename RaIter>
void process(RaIter first, RaIter last) {
add_to_data_length(static_cast<word_t>(std::distance(first, last)));
std::copy(first, last, std::back_inserter(buffer_));
std::size_t i = 0;
for (; i + 64 <= buffer_.size(); i += 64) {
detail::hash256_block(h_, buffer_.begin() + i,
buffer_.begin() + i + 64);
}
buffer_.erase(buffer_.begin(), buffer_.begin() + i);
}
void finish() {
byte_t temp[64];
std::fill(temp, temp + 64, byte_t(0));
std::size_t remains = buffer_.size();
std::copy(buffer_.begin(), buffer_.end(), temp);
temp[remains] = 0x80;
if (remains > 55) {
std::fill(temp + remains + 1, temp + 64, byte_t(0));
detail::hash256_block(h_, temp, temp + 64);
std::fill(temp, temp + 64 - 4, byte_t(0));
} else {
std::fill(temp + remains + 1, temp + 64 - 4, byte_t(0));
}
write_data_bit_length(&(temp[56]));
detail::hash256_block(h_, temp, temp + 64);
}
template <typename OutIter>
void get_hash_bytes(OutIter first, OutIter last) const {
for (const word_t* iter = h_; iter != h_ + 8; ++iter) {
for (std::size_t i = 0; i < 4 && first != last; ++i) {
*(first++) = detail::mask_8bit(
static_cast<byte_t>((*iter >> (24 - 8 * i))));
}
}
}
private:
void add_to_data_length(word_t n) {
word_t carry = 0;
data_length_digits_[0] += n;
for (std::size_t i = 0; i < 4; ++i) {
data_length_digits_[i] += carry;
if (data_length_digits_[i] >= 65536u) {
carry = data_length_digits_[i] >> 16;
data_length_digits_[i] &= 65535u;
} else {
break;
}
}
}
void write_data_bit_length(byte_t* begin) {
word_t data_bit_length_digits[4];
std::copy(data_length_digits_, data_length_digits_ + 4,
data_bit_length_digits);
// convert byte length to bit length (multiply 8 or shift 3 times left)
word_t carry = 0;
for (std::size_t i = 0; i < 4; ++i) {
word_t before_val = data_bit_length_digits[i];
data_bit_length_digits[i] <<= 3;
data_bit_length_digits[i] |= carry;
data_bit_length_digits[i] &= 65535u;
carry = (before_val >> (16 - 3)) & 65535u;
}
// write data_bit_length
for (int i = 3; i >= 0; --i) {
(*begin++) = static_cast<byte_t>(data_bit_length_digits[i] >> 8);
(*begin++) = static_cast<byte_t>(data_bit_length_digits[i]);
}
}
std::vector<byte_t> buffer_;
word_t data_length_digits_[4]; // as 64bit integer (16bit x 4 integer)
word_t h_[8];
};
inline void get_hash_hex_string(const hash256_one_by_one& hasher,
std::string& hex_str) {
byte_t hash[k_digest_size];
hasher.get_hash_bytes(hash, hash + k_digest_size);
return bytes_to_hex_string(hash, hash + k_digest_size, hex_str);
}
inline std::string get_hash_hex_string(const hash256_one_by_one& hasher) {
std::string hex_str;
get_hash_hex_string(hasher, hex_str);
return hex_str;
}
namespace impl {
template <typename RaIter, typename OutIter>
void hash256_impl(RaIter first, RaIter last, OutIter first2, OutIter last2, int,
std::random_access_iterator_tag) {
hash256_one_by_one hasher;
// hasher.init();
hasher.process(first, last);
hasher.finish();
hasher.get_hash_bytes(first2, last2);
}
template <typename InputIter, typename OutIter>
void hash256_impl(InputIter first, InputIter last, OutIter first2,
OutIter last2, int buffer_size, std::input_iterator_tag) {
std::vector<byte_t> buffer(buffer_size);
hash256_one_by_one hasher;
// hasher.init();
while (first != last) {
int size = buffer_size;
for (int i = 0; i != buffer_size; ++i, ++first) {
if (first == last) {
size = i;
break;
}
buffer[i] = *first;
}
hasher.process(buffer.begin(), buffer.begin() + size);
}
hasher.finish();
hasher.get_hash_bytes(first2, last2);
}
}
template <typename InIter, typename OutIter>
void hash256(InIter first, InIter last, OutIter first2, OutIter last2,
int buffer_size = PICOSHA2_BUFFER_SIZE_FOR_INPUT_ITERATOR) {
picosha2::impl::hash256_impl(
first, last, first2, last2, buffer_size,
typename std::iterator_traits<InIter>::iterator_category());
}
template <typename InIter, typename OutContainer>
void hash256(InIter first, InIter last, OutContainer& dst) {
hash256(first, last, dst.begin(), dst.end());
}
template <typename InContainer, typename OutIter>
void hash256(const InContainer& src, OutIter first, OutIter last) {
hash256(src.begin(), src.end(), first, last);
}
template <typename InContainer, typename OutContainer>
void hash256(const InContainer& src, OutContainer& dst) {
hash256(src.begin(), src.end(), dst.begin(), dst.end());
}
template <typename InIter>
void hash256_hex_string(InIter first, InIter last, std::string& hex_str) {
byte_t hashed[k_digest_size];
hash256(first, last, hashed, hashed + k_digest_size);
std::ostringstream oss;
output_hex(hashed, hashed + k_digest_size, oss);
hex_str.assign(oss.str());
}
template <typename InIter>
std::string hash256_hex_string(InIter first, InIter last) {
std::string hex_str;
hash256_hex_string(first, last, hex_str);
return hex_str;
}
inline void hash256_hex_string(const std::string& src, std::string& hex_str) {
hash256_hex_string(src.begin(), src.end(), hex_str);
}
template <typename InContainer>
void hash256_hex_string(const InContainer& src, std::string& hex_str) {
hash256_hex_string(src.begin(), src.end(), hex_str);
}
template <typename InContainer>
std::string hash256_hex_string(const InContainer& src) {
return hash256_hex_string(src.begin(), src.end());
}
template<typename OutIter>void hash256(std::ifstream& f, OutIter first, OutIter last){
hash256(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>(), first,last);
}
}// namespace picosha2
#endif // PICOSHA2_H

View File

@@ -0,0 +1,83 @@
/*
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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <unistd.h>
#include <libhelper/lib.hpp>
namespace Helper {
bool hasSuperUser()
{
return (getuid() == 0);
}
bool isExists(const std::string_view entry)
{
struct stat st;
return (stat(entry.data(), &st) == 0);
}
bool fileIsExists(const std::string_view file)
{
struct stat st;
if (stat(file.data(), &st) != 0) return false;
return S_ISREG(st.st_mode);
}
bool directoryIsExists(const std::string_view directory)
{
struct stat st;
if (stat(directory.data(), &st) != 0) return false;
return S_ISDIR(st.st_mode);
}
bool linkIsExists(const std::string_view entry)
{
return (isLink(entry) || isHardLink(entry));
}
bool isLink(const std::string_view entry)
{
struct stat st;
if (lstat(entry.data(), &st) != 0) return false;
return S_ISLNK(st.st_mode);
}
bool isSymbolicLink(const std::string_view entry)
{
return isLink(entry);
}
bool isHardLink(const std::string_view entry)
{
struct stat st;
if (lstat(entry.data(), &st) != 0) return false;
return (st.st_nlink >= 2);
}
bool areLinked(const std::string_view entry1, const std::string_view entry2)
{
const std::string_view st1 = (isSymbolicLink(entry1)) ? readSymlink(entry1) : entry1;
const std::string_view st2 = (isSymbolicLink(entry2)) ? readSymlink(entry2) : entry2;
return (st1 == st2);
}
} // namespace Helper

View File

@@ -0,0 +1,96 @@
/*
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 <exception>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <stdarg.h>
#include <libhelper/lib.hpp>
namespace Helper {
std::string_view LoggingProperties::FILE = "last_logs.log", LoggingProperties::NAME = "main";
bool LoggingProperties::PRINT = NO;
Error::Error(const char* format, ...)
{
char buf[1024];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
_message = std::string(buf);
}
const char* Error::what() const noexcept
{
return _message.data();
}
Logger::Logger(LogLevels level, const char* file, const char* name, const char* sfile, int line) : _level(level), _logFile(file), _program_name(name), _file(sfile), _line(line) {}
Logger::~Logger()
{
char str[1024];
snprintf(str, sizeof(str), "<%c> [ <prog %s> <on %s:%d> %s %s] %s",
(char)_level,
_program_name,
basename((char*)_file),
_line,
currentDate().data(),
currentTime().data(),
_oss.str().data());
if (!isExists(_logFile)) createFile(_logFile);
FILE* fp = fopen(_logFile, "a");
if (fp != NULL) {
fprintf(fp, "%s", str);
fclose(fp);
}
if (LoggingProperties::PRINT) printf("%s\n", str);
if (_level == ERROR) exit(1);
else if (_level == ABORT) abort();
}
Logger& Logger::operator<<(std::ostream& (*msg)(std::ostream&))
{
_oss << msg;
return *this;
}
void LoggingProperties::reset()
{
FILE = "last_logs.log";
NAME = "main";
PRINT = NO;
}
void LoggingProperties::set(std::string_view file, std::string_view name)
{
FILE = file;
NAME = name;
}
void LoggingProperties::setProgramName(std::string_view name) { NAME = name; }
void LoggingProperties::setLogFile(std::string_view file) { FILE = file; }
void LoggingProperties::setPrinting(int state) { PRINT = state; }
} // namespace Helper

View File

@@ -0,0 +1,246 @@
/*
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>
#include <libhelper/lib.hpp>
static FILE* open_file(const std::string_view file, const char* mode)
{
FILE* fp = fopen(file.data(), mode);
if (fp == nullptr) {
throw Helper::Error("Cannot open %s: %s", file.data(), strerror(errno));
return fp;
}
return fp;
}
namespace Helper {
bool writeFile(const std::string_view file, const std::string_view text)
{
FILE* fp = open_file(file, "a");
if (fp == nullptr) return false;
fprintf(fp, "%s", text.data());
fclose(fp);
return true;
}
std::optional<std::string> readFile(const std::string_view file)
{
FILE* fp = open_file(file, "r");
if (fp == nullptr) return std::nullopt;
char buffer[1024];
std::string str;
while (fgets(buffer, sizeof(buffer), fp)) str += buffer;
fclose(fp);
return str;
}
bool copyFile(const std::string_view file, const std::string_view dest)
{
int src_fd = open(file.data(), O_RDONLY);
if (src_fd == - 1) {
throw Error("Cannot open %s: %s", file.data(), strerror(errno));
return false;
}
int dst_fd = open(dest.data(), O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_FILE_PERMS);
if (dst_fd == - 1) {
throw Error("Cannot create/open %s: %s", dest.data(), strerror(errno));
return false;
}
char buffer[512];
ssize_t br;
while ((br = read(src_fd, buffer, 512)) > 0) {
ssize_t bw = write(dst_fd, buffer, br);
if (bw != br) {
throw Error("Cannot write %s: %s", dest.data(), strerror(errno));
close(src_fd);
close(dst_fd);
return false;
}
}
close(src_fd);
close(dst_fd);
if (br == -1) {
throw Error("Cannot read %s: %s", file.data(), strerror(errno));
return false;
}
return true;
}
bool makeDirectory(const std::string_view path)
{
if (isExists(path)) return false;
return (mkdir(path.data(), DEFAULT_DIR_PERMS) == 0) ? true : false;
}
bool makeRecursiveDirectory(const std::string_view paths)
{
char tmp[PATH_MAX], *p;
size_t len;
snprintf(tmp, sizeof(tmp), "%s", paths.data());
len = strlen(tmp);
if (tmp[len - 1] == '/') tmp[len - 1] = '\0';
for (p = tmp + 1; *p; p++) {
if (*p == '/') {
*p = '\0';
if (access(tmp, F_OK) != 0) {
if (mkdir(tmp, DEFAULT_DIR_PERMS) != 0
&& errno != EEXIST) {
throw Error("Cannot create directory: %s: %s", tmp, strerror(errno));
return false;
}
}
*p = '/';
}
}
if (access(tmp, F_OK) != 0) {
if (mkdir(tmp, DEFAULT_DIR_PERMS) != 0 && errno != EEXIST) {
throw Error("Cannot create directory: %s: %s", tmp, strerror(errno));
return false;
}
}
return true;
}
bool createFile(const std::string_view path)
{
if (isExists(path)) {
throw Error("%s: is exists", path.data());
return false;
}
int fd = open(path.data(), O_RDONLY | O_CREAT, DEFAULT_FILE_PERMS);
if (fd == -1) {
throw Error("Cannot create %s: %s", path.data(), strerror(errno));
return false;
}
close(fd);
return true;
}
bool createSymlink(const std::string_view entry1, const std::string_view entry2)
{
int ret = symlink(entry1.data(), entry2.data());
if (ret != 0)
throw Error("Cannot symlink %s: %s", entry2.data(), strerror(errno));
return (ret == 0);
}
bool eraseEntry(const std::string_view entry)
{
int ret = remove(entry.data());
if (ret != 0)
throw Error("Cannot remove %s: %s", entry.data(), strerror(errno));
return (ret == 0);
}
bool eraseDirectoryRecursive(const std::string_view directory)
{
struct stat buf;
struct dirent *entry;
DIR *dir = opendir(directory.data());
if (dir == nullptr) {
throw Error("Cannot open directory %s: %s", directory.data(), strerror(errno));
return false;
}
while ((entry = readdir(dir)) != NULL) {
char fullpath[PATH_MAX];
if (strcmp(entry->d_name, ".") == 0
|| strcmp(entry->d_name, "..") == 0)
continue;
snprintf(fullpath, sizeof(fullpath), "%s/%s", directory.data(), entry->d_name);
if (lstat(fullpath, &buf) == -1) {
throw Error("Cannot stat %s: %s", fullpath, strerror(errno));
closedir(dir);
return false;
}
if (S_ISDIR(buf.st_mode)) {
if (!eraseDirectoryRecursive(fullpath)) {
closedir(dir);
return false;
}
} else {
if (unlink(fullpath) == -1) {
throw Error("Cannot unlink %s: %s", fullpath, strerror(errno));
closedir(dir);
return false;
}
}
}
closedir(dir);
if (rmdir(directory.data()) == -1) {
throw Error("Cannot remove directory %s: %s", directory.data(), strerror(errno));
return false;
}
return true;
}
std::string_view readSymlink(const std::string_view entry)
{
char target[PATH_MAX];
ssize_t len = readlink(entry.data(), target, (sizeof(target) - 1));
if (len == -1) {
throw Error("Cannot read symlink %s: %s", entry.data(), strerror(errno));
return entry;
}
target[len] = '\0';
return target;
}
size_t fileSize(const std::string_view file)
{
struct stat st;
if (stat(file.data(), &st) != 0) return false;
return static_cast<size_t>(st.st_size);
}
} // namespace Helper

View File

@@ -0,0 +1,54 @@
/*
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 <fstream>
#include <vector>
#include <string>
#include <iostream>
#include <optional>
#include <picosha2.h>
#include <sys/stat.h>
#include <libhelper/lib.hpp>
namespace Helper {
std::optional<std::string_view> sha256Of(const std::string_view path)
{
if (!fileIsExists(path)) {
throw Error("Is not exists or not file: %s", path.data());
return std::nullopt;
}
std::ifstream file(path, std::ios::binary);
if (!file) {
throw Error("Cannot open file: %s", path.data());
return std::nullopt;
}
std::vector<unsigned char> hash(picosha2::k_digest_size);
picosha2::hash256(path, hash.begin(), hash.end());
return picosha2::bytes_to_hex_string(hash.begin(), hash.end());
}
bool sha256Compare(const std::string_view file1, const std::string_view file2)
{
auto f1 = sha256Of(file1);
auto f2 = sha256Of(file2);
if (f1->empty() || f2->empty()) return false;
return (*f1 == *f2);
}
} // namespace Helper

View File

@@ -0,0 +1,140 @@
/*
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 <memory>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <libgen.h>
#include <libhelper/lib.hpp>
namespace Helper {
bool runCommand(const std::string_view cmd)
{
return (system(cmd.data()) == 0) ? true : false;
}
bool confirmPropt(const std::string_view message)
{
char p;
printf("%s [ y / n ]: ", message.data());
std::cin >> p;
if (p == 'y' || p == 'Y') return true;
else if (p == 'n' || p == 'N') return false;
else {
printf("Unexpected answer: '%c'. Try again.\n", p);
return confirmPropt(message);
}
return false;
}
std::string currentWorkingDirectory()
{
char cwd[1024];
if (getcwd(cwd, sizeof(cwd)) == nullptr) return std::string();
return cwd;
}
std::string currentDate()
{
time_t t = time(nullptr);
struct tm *date = localtime(&t);
if (date)
return std::string(
std::to_string(date->tm_mday) + "/" +
std::to_string(date->tm_mon + 1) + "/" +
std::to_string(date->tm_year + 1900));
return "--/--/----";
}
std::string currentTime()
{
time_t t = time(nullptr);
struct tm *date = localtime(&t);
if (date)
return std::string(
std::to_string(date->tm_hour) + ":" +
std::to_string(date->tm_min) + ":" +
std::to_string(date->tm_sec));
return "--:--:--";
}
std::string runCommandWithOutput(const std::string_view cmd)
{
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.data(), "r"), pclose);
if (!pipe) {
throw Error("Cannot run command: %s", cmd.data());
return {};
}
std::string end;
char buffer[1024];
while (fgets(buffer, sizeof(buffer), pipe.get()) != nullptr) end += buffer;
return end;
}
std::string pathJoin(std::string base, std::string relative)
{
if (base.back() != '/') base += '/';
if (relative[0] == '/') relative.erase(0, 1);
base += relative;
return base;
}
std::string pathBasename(const std::string_view entry)
{
if (!isExists(entry)) {
throw Error("No such file or directory: %s", entry.data());
return {};
}
char* base = basename((char*)entry.data());
return (base == nullptr) ? std::string() : std::string(base);
}
std::string pathDirname(const std::string_view entry)
{
if (!isExists(entry)) {
throw Error("No such file or directory: %s", entry.data());
return {};
}
char* base = dirname((char*)entry.data());
return (base == nullptr) ? std::string() : std::string(base);
}
std::string getLibVersion()
{
return std::string(
std::to_string(LIBHELPER_MAJOR) + "."
+ std::to_string(LIBHELPER_MINOR) + "."
+ std::to_string(LIBHELPER_PATCH)
);
}
} // namespace Helper

View File

@@ -0,0 +1,101 @@
/*
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.
*/
#define PROGRAM_NAME "helper_test"
#include <iostream>
#include <libhelper/lib.hpp>
char* TEST_DIR = nullptr;
std::string test_path(const char* file)
{
std::string end = std::string(TEST_DIR) + "/" + file;
return end;
}
int main(int argc, char** argv)
{
if (argc < 2) return 2;
else TEST_DIR = argv[1];
try {
std::cout << "Has super user?; " << std::boolalpha << Helper::hasSuperUser() << std::endl;
std::cout << "file.txt is exists?; " << std::boolalpha << Helper::isExists(test_path("file.txt")) << std::endl;
std::cout << "'file.txt' file is exists?; " << std::boolalpha << Helper::fileIsExists(test_path("file")) << std::endl;
std::cout << "'dir' directory is exists?; " << std::boolalpha << Helper::directoryIsExists(test_path("dir")) << std::endl;
std::cout << "'linkdir' is link?; " << std::boolalpha << Helper::isLink(test_path("linkdir")) << std::endl;
std::cout << "'linkdir' is symlink?; " << std::boolalpha << Helper::isSymbolicLink(test_path("linkdir")) << std::endl;
std::cout << "'linkdir' is hardlink?; " << std::boolalpha << Helper::isHardLink(test_path("linkdir")) << std::endl;
std::cout << "'linkdir' is symlink to 'dir'?; " << std::boolalpha << Helper::areLinked(test_path("linkdir"), test_path("dir")) << std::endl;
if (!Helper::writeFile("file.txt", "hello world"))
throw Helper::Error("Cannor write \"hello world\" in 'file.txt'");
else
std::cout << "file.txt writed." << std::endl;
auto content = Helper::readFile("file.txt");
if (!content)
throw Helper::Error("Cannot read 'file.txt'");
else
std::cout << "'file.txt': " << *content << std::endl;
std::cout << "Making directory 'dir2': " << std::boolalpha << Helper::makeDirectory(test_path("dir2")) << std::endl;
std::cout << "Making recursive directories 'dir3/x/y': " << std::boolalpha << Helper::makeRecursiveDirectory(test_path("dir3/x/y")) << std::endl;
std::cout << "Create 'file2.txt': " << std::boolalpha << Helper::createFile(test_path("file2.txt")) << std::endl;
std::cout << "Create symlink 'file2.txt' to 'file2lnk.txt': " << std::boolalpha << Helper::createSymlink(test_path("file2.txt"), test_path("file2lnk.txt")) << std::endl;
std::cout << "Size of 'file2.txt': " << Helper::fileSize(test_path("file2.txt")) << std::endl;
std::cout << "Erasing 'file.txt': " << std::boolalpha << Helper::eraseEntry(test_path("file.txt")) << std::endl;
std::cout << "Erasing 'dir2': " << std::boolalpha << Helper::eraseEntry(test_path("dir2")) << std::endl;
std::cout << "Read link of 'file2lnk.txt': " << Helper::readSymlink(test_path("file2lnk.txt")) << std::endl;
auto sha256 = Helper::sha256Of(test_path("file2.txt"));
if (!sha256)
throw Helper::Error("Cannot get sha256 of 'file2.txt'");
else
std::cout << "SHA256 of 'file2.txt': " << *sha256 << std::endl;
std::cout << "'file2.txt' and 'file2lnk.txt' same? (SHA256): " << std::boolalpha << Helper::sha256Compare(test_path("file2.txt"), test_path("file2lnk.txt")) << std::endl;
std::cout << "Copy 'file2.txt' as 'file2cpy.txt': " << std::boolalpha << Helper::copyFile(test_path("file2.txt"), test_path("file2cpy.txt")) << std::endl;
std::cout << "Run command: 'ls': " << std::boolalpha << Helper::runCommand("ls") << std::endl;
std::cout << "Spawn confirm propt..." << std::endl;
bool p = Helper::confirmPropt("Please answer");
std::cout << "Result of confirm propt: " << std::boolalpha << p << std::endl;
std::cout << "Working directory: " << Helper::currentWorkingDirectory() << std::endl;
std::cout << "Current date: " << Helper::currentDate() << std::endl;
std::cout << "Current time: " << Helper::currentTime() << std::endl;
std::cout << "Output of 'ls' command: " << Helper::runCommandWithOutput("ls") << std::endl;
std::cout << "Basename of " << test_path("file2.txt") << ": " << Helper::pathBasename(test_path("file2.txt")) << std::endl;
std::cout << "Dirname of " << test_path("file2.txt") << ": " << Helper::pathDirname(test_path("file2.txt")) << std::endl;
std::cout << "pathJoin() test 1: " << Helper::pathJoin("mydir", "dir2") << std::endl;
std::cout << "pathJoin() test 2: " << Helper::pathJoin("mydir/", "dir2") << std::endl;
std::cout << "pathJoin() test 3: " << Helper::pathJoin("mydir/", "/dir2") << std::endl;
std::cout << "pathJoin() test 4: " << Helper::pathJoin("mydir", "/dir2") << std::endl;
LOG(INFO) << "Info message" << std::endl;
LOG(WARNING) << "Warning message" << std::endl;
LOG(ERROR) << "Error message" << std::endl;
LOG(ABORT) << "Abort message" << std::endl;
} catch (Helper::Error& err) {
std::cout << err.what() << std::endl;
return 1;
}
return 0;
}

View File

@@ -0,0 +1,23 @@
#!/usr/bin/bash
#
# 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.
#
set -e
if [ -z $1 ]; then echo "$0: Provide test path!"; exit 1; fi
if [ ! -d "$1/dir" ]; then mkdir $1/dir; fi
touch "$1/file.txt"
ln -s $1/dir $1/linkdir &>/dev/null

View File

@@ -0,0 +1,41 @@
#
# 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.
#
# Sources
set(LIBPARTITION_MAP_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/Getters.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/PartitionMap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Type.cpp
)
set(LIBPARTITION_MAP_FLAGS -Wall -Werror -DLOG_FILE="/storage/emulated/0/.last_pmt.log" -DPROGRAM_NAME="libpartition_map")
# Add targets
add_library(partition_map_shared SHARED ${LIBPARTITION_MAP_SOURCES})
add_library(partition_map_static STATIC ${LIBPARTITION_MAP_SOURCES})
add_executable(libpartition_map_test tests/test.cpp)
# Set appropriate output names
set_target_properties(partition_map_shared PROPERTIES OUTPUT_NAME "partition_map")
set_target_properties(partition_map_static PROPERTIES OUTPUT_NAME "partition_map")
# Set compiler flags
target_compile_options(partition_map_shared PRIVATE ${LIBPARTITION_MAP_FLAGS})
target_compile_options(partition_map_static PRIVATE ${LIBPARTITION_MAP_FLAGS})
target_compile_options(libpartition_map_test PRIVATE ${LIBPARTITION_MAP_FLAGS})
target_link_options(libpartition_map_test PRIVATE "LINKER:-rpath,/data/data/com.termux/files/usr/lib")
target_link_options(partition_map_shared PRIVATE "LINKER:-rpath,/data/data/com.termux/files/usr/lib")
target_link_libraries(libpartition_map_test PRIVATE partition_map_shared PRIVATE helper_shared)
target_link_libraries(partition_map_shared PRIVATE helper_shared)

View File

@@ -0,0 +1,332 @@
/*
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.
*/
#ifndef LIBPARTITION_MAP_LIB_HPP
#define LIBPARTITION_MAP_LIB_HPP
#define LIBPARTITION_MAP_MAJOR 1
#define LIBPARTITION_MAP_MINOR 0
#define LIBPARTITION_MAP_PATCH 0
#include <string>
#include <string_view>
#include <optional>
#include <exception>
#include <list>
#include <memory>
#include <utility> // for std::pair
#include <cstdint> // for uint64_t
#include <libhelper/lib.hpp>
namespace PartitionMap {
struct _entry {
std::string name;
struct {
uint64_t size;
bool isLogical;
} props;
};
class basic_partition_map {
private:
void _resize_map();
int _index_of(const std::string_view name) const;
public:
_entry* _data;
size_t _count, _capacity;
struct _returnable_entry {
uint64_t size;
bool isLogical;
};
using BasicInf = _returnable_entry;
basic_partition_map(const std::string name, uint64_t size, bool logical);
basic_partition_map(const basic_partition_map& other);
basic_partition_map();
~basic_partition_map();
bool insert(const std::string name, uint64_t size, bool logical);
void merge(const basic_partition_map& map);
uint64_t get_size(const std::string_view name) const;
bool is_logical(const std::string_view name) const;
_returnable_entry get_all(const std::string_view name) const;
bool find(const std::string_view name) const;
std::string find_(const std::string name) const;
size_t size() const;
bool empty() const;
void clear();
basic_partition_map& operator=(const basic_partition_map& map);
bool operator==(const basic_partition_map& other) const;
bool operator!=(const basic_partition_map& other) const;
class iterator {
public:
_entry* ptr;
iterator(_entry* p);
auto operator*() -> std::pair<std::string&, decltype(_entry::props)&>;
_entry* operator->();
iterator& operator++();
iterator operator++(int);
bool operator!=(const iterator& other) const;
bool operator==(const iterator& other) const;
};
class constant_iterator {
public:
const _entry* ptr;
constant_iterator(const _entry* p);
auto operator*() const -> std::pair<const std::string&, const decltype(_entry::props)&>;
const _entry* operator->() const;
constant_iterator& operator++();
constant_iterator operator++(int);
bool operator!=(const constant_iterator& other) const;
bool operator==(const constant_iterator& other) const;
};
/* for-each support */
iterator begin();
iterator end();
constant_iterator begin() const;
constant_iterator cbegin() const;
constant_iterator end() const;
constant_iterator cend() const;
};
using Map_t = basic_partition_map;
class basic_partition_map_builder {
private:
Map_t _current_map;
std::string _workdir;
bool _any_generating_error, _map_builded;
bool _is_real_block_dir(const std::string_view path) const;
Map_t _build_map(std::string_view path, bool logical = false);
void _insert_logicals(Map_t&& logicals);
void _map_build_check() const;
uint64_t _get_size(const std::string path);
public:
/**
* Default constructor
* -------------------
* By default, it searches the directories in the
* defaultEntryList in PartitionMap.cpp in order and
* uses the directory it finds.
*/
basic_partition_map_builder();
/**
* Secondary constructor
* ---------------------
* It has two arguments:
* - Directory path to search
*/
basic_partition_map_builder(const std::string_view path);
/**
* getAll()
* ------
* WARNING: Learn about std::optional before using this function.
*
* Returns the current list content in Map_t type.
* If no list is created, returns std::nullopt.
*/
Map_t getAll() const;
/**
* get(name)
* ---------
* WARNING: Learn about std::optional before using this function.
*
* Returns information of a specific partition in
* Map_temp_t type. If the partition is not in the
* currently created list, returns std::nullopt.
*/
std::optional<std::pair<uint64_t, bool>> get(const std::string_view name) const;
/**
* getLogicalPartitionList()
* -------------------------
* WARNING: Learn about std::optional before using this function.
*
* If there is a logical partition(s) in the created
* list, it returns a list of type std::list (containing
* data of type std::string). If there is no logical
* partition in the created list, it returns std::nullopt.
*/
std::optional<std::list<std::string>> getLogicalPartitionList() const;
/**
* getPhysicalPartitionList()
* --------------------------
* WARNING: Learn about std::optional before using this function.
*
* The physical partitions in the created list are
* returned as std::list type. If there is no content
* due to any problem, returns std::nullopt.
*/
std::optional<std::list<std::string>> getPhysicalPartitionList() const;
/**
* getRealLinkPathOf(name)
* -----------------------
* WARNING: Learn about std::optional before using this function.
*
* Returns the full link path of the entered partition
* name in the current search directory as std::string.
* If the partition is not in the list, an empty
* std::string is returned.
*/
std::string getRealLinkPathOf(const std::string_view name) const;
/**
* getRealPathOf(name)
* -------------------
* WARNING: Learn about std::optional before using this function.
*
* Returns the actual path of the partition as
* std::string. Like /dev/block/sda5
*/
std::string getRealPathOf(const std::string_view name) const;
/**
* getCurrentWorkDir()
* -------------------
* WARNING: Learn about std::optional before using this function.
*
* If it exists, the path to the search string is
* returned as std::string. If it does not exist,
* an empty std::string is returned.
*/
std::string getCurrentWorkDir() const;
/**
* hasPartition(name)
* ------------------
* Returns whether the entered partition name is in the
* created partition list as a bool.
*/
bool hasPartition(const std::string_view name) const;
/**
* isLogical(name)
* ---------------
* Returns the bool type status of whether the
* entered section name is marked as logical in the
* created list. Alternatively, the current section
* information can be retrieved with the Get() function
* and checked for logicality.
*/
bool isLogical(const std::string_view name) const;
/**
* clear()
* -------
* The created list and the current search index name are cleared.
*/
void clear();
/**
* readDirectory(path)
* -------------------
* The entered path is defined as the new search
* directory and the search is performed in the entered
* directory. If everything goes well, true is returned.
*/
bool readDirectory(const std::string_view path);
/**
* empty()
* -------
* Whether the current list is empty or not is returned
* as bool type. If there is content in the list, true
* is returned, otherwise false is returned.
*/
bool empty() const;
/**
* sizeOf(name)
* ------------
* WARNING: Learn about std::optional before using this function.
*
* If it exists, the size of the partition with the
* entered name is returned as uint64_t type.
* If it does not exist, 0 is returned.
*/
uint64_t sizeOf(const std::string_view name) const;
/**
* == operator
* -----------
* If the content lists of the two created objects are
* the same (checked only according to the partition
* names), true is returned, otherwise false is returned
*/
friend bool operator==(basic_partition_map_builder& lhs, basic_partition_map_builder& rhs);
/**
* != operator
* -----------
* The opposite logic of the == operator.
*/
friend bool operator!=(basic_partition_map_builder& lhs, basic_partition_map_builder& rhs);
/**
* Boolean operator
* ----------------
* You can check whether the object was created
* successfully. If the problem did not occur, true is
* returned, if it did, false is returned.
*/
operator bool() const;
/**
* ! operator
* ----------
* Returns true if the object creation failed (i.e., there's a problem),
* and false if the object is correctly created.
*/
bool operator!() const;
};
using Error = Helper::Error;
/**
* getLibVersion()
* ---------------
* To get the version information of libpartition_map
* library. It is returned as std::string type.
*/
std::string getLibVersion();
using BuildMap = basic_partition_map_builder;
using Map = basic_partition_map_builder;
} // namespace PartitionMap
#endif // #ifndef LIBPARTITION_MAP_LIB_HPP

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

View File

@@ -0,0 +1,78 @@
/*
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 <unistd.h>
#include <libpartition_map/lib.hpp>
int main(void) {
if (getuid() != 0) return 2;
try {
PartitionMap::BuildMap MyMap;
if (!MyMap) {
MyMap.readDirectory("/dev/block/by-name");
if (!MyMap) throw PartitionMap::Error("Cannot generate object!");
}
auto map = MyMap.getAll();
if (map.empty()) throw PartitionMap::Error("getAll() empty");
for (const auto& [name, props] : map) {
std::cout << "Partition: " << name << ", size: "
<< props.size << ", logical: "
<< props.isLogical << std::endl;
}
auto boot = MyMap.get("boot");
if (!boot) throw PartitionMap::Error("get(\"boot\") returned nullopt");
std::cout << "Name: boot" << ", size: "
<< boot->first << ", logical: "
<< boot->second << std::endl;
auto logicals = MyMap.getLogicalPartitionList();
if (!logicals) throw PartitionMap::Error("getLogicalPartitionList() returned nullopt");
std::cout << "Logical partitions: " << std::endl;
for (const auto& name : *logicals)
std::cout << " - " << name << std::endl;
auto physicals = MyMap.getPhysicalPartitionList();
if (!physicals) throw PartitionMap::Error("getPhysicalPartitionList() returned nullopt");
std::cout << "Physical partitions: " << std::endl;
for (const auto& name : *physicals)
std::cout << " - " << name << std::endl;
std::cout << "Boot: " << MyMap.getRealLinkPathOf("boot") << std::endl;
std::cout << "Boot (realpath): " << MyMap.getRealPathOf("boot") << std::endl;
std::cout << "Search dir: " << MyMap.getCurrentWorkDir() << std::endl;
std::cout << "Has partition cache? = " << MyMap.hasPartition("cache") << std::endl;
std::cout << "system partition is logical? = " << MyMap.isLogical("system") << std::endl;
std::cout << "Size of system partition: " << MyMap.sizeOf("system") << std::endl;
MyMap.clear();
if (!MyMap.empty()) throw PartitionMap::Error("map cleaned but check fail");
MyMap.readDirectory("/dev/block/by-name");
PartitionMap::BuildMap MyMap2;
if (MyMap == MyMap2) std::cout << "map1 = map2" << std::endl;
if (MyMap != MyMap2) std::cout << "map1 != map2" << std::endl;
} catch (PartitionMap::Error& error) {
std::cerr << error.what() << std::endl;
return 1;
}
return 0;
}

0
tests/test.cpp Normal file
View File