pmt: first codes.

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

View File

@@ -0,0 +1,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