pmt: first codes.
This commit is contained in:
12
.vscode/c_cpp_properties.json
vendored
Normal file
12
.vscode/c_cpp_properties.json
vendored
Normal 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
36
CMakeLists.txt
Normal 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
92
build.sh
Normal 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
|
||||
30
include/PartitionManager/lib.hpp
Normal file
30
include/PartitionManager/lib.hpp
Normal 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
0
src/.placeholder
Normal file
41
srclib/libhelper/CMakeLists.txt
Normal file
41
srclib/libhelper/CMakeLists.txt
Normal 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")
|
||||
186
srclib/libhelper/include/libhelper/lib.hpp
Normal file
186
srclib/libhelper/include/libhelper/lib.hpp
Normal 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
|
||||
377
srclib/libhelper/include/picosha2.h
Normal file
377
srclib/libhelper/include/picosha2.h
Normal 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
|
||||
83
srclib/libhelper/src/Checkers.cpp
Normal file
83
srclib/libhelper/src/Checkers.cpp
Normal 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
|
||||
96
srclib/libhelper/src/Classes.cpp
Normal file
96
srclib/libhelper/src/Classes.cpp
Normal 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
|
||||
246
srclib/libhelper/src/FileUtil.cpp
Normal file
246
srclib/libhelper/src/FileUtil.cpp
Normal 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
|
||||
54
srclib/libhelper/src/Sha256.cpp
Normal file
54
srclib/libhelper/src/Sha256.cpp
Normal 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
|
||||
140
srclib/libhelper/src/Utilities.cpp
Normal file
140
srclib/libhelper/src/Utilities.cpp
Normal 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
|
||||
101
srclib/libhelper/tests/test.cpp
Normal file
101
srclib/libhelper/tests/test.cpp
Normal 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;
|
||||
}
|
||||
23
srclib/libhelper/tests/test.sh
Normal file
23
srclib/libhelper/tests/test.sh
Normal 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
|
||||
41
srclib/libpartition_map/CMakeLists.txt
Normal file
41
srclib/libpartition_map/CMakeLists.txt
Normal 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)
|
||||
332
srclib/libpartition_map/include/libpartition_map/lib.hpp
Normal file
332
srclib/libpartition_map/include/libpartition_map/lib.hpp
Normal 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
|
||||
87
srclib/libpartition_map/src/Getters.cpp
Normal file
87
srclib/libpartition_map/src/Getters.cpp
Normal 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
|
||||
209
srclib/libpartition_map/src/PartitionMap.cpp
Normal file
209
srclib/libpartition_map/src/PartitionMap.cpp
Normal 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
|
||||
278
srclib/libpartition_map/src/Type.cpp
Normal file
278
srclib/libpartition_map/src/Type.cpp
Normal 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
|
||||
78
srclib/libpartition_map/tests/test.cpp
Normal file
78
srclib/libpartition_map/tests/test.cpp
Normal 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
0
tests/test.cpp
Normal file
Reference in New Issue
Block a user