Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,045 changes: 1,045 additions & 0 deletions Khamidullin.Ilsaf/lab1/.gitignore

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions Khamidullin.Ilsaf/lab1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.0.0)
project(lab1)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-Wall -Werror")

add_executable(lab1 main.cpp daemon.cpp)
12 changes: 12 additions & 0 deletions Khamidullin.Ilsaf/lab1/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DIR_NAME="build_tmp"
EXE_NAME="lab1"
PID_PATH="/var/run/deep_deletion_daemon.pid"

sudo touch $PID_PATH; sudo chmod 0666 $PID_PATH

mkdir $DIR_NAME
cd $DIR_NAME
cmake ..; make
cd ..
cp $DIR_NAME/$EXE_NAME .
rm -r $DIR_NAME
2 changes: 2 additions & 0 deletions Khamidullin.Ilsaf/lab1/config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/home/ilsaf/repos/Operating-Systems-labs-2024/Khamidullin.Ilsaf/lab1/dir
5
191 changes: 191 additions & 0 deletions Khamidullin.Ilsaf/lab1/daemon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#include "daemon.hpp"
#include <limits.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/stat.h>
#include <csignal>
#include <fstream>
#include <fcntl.h>
#include <filesystem>
#include <queue>
#include <thread>

static void handleSignal(int signal)
{
switch (signal)
{
case SIGTERM:
syslog(LOG_INFO, "Daemon process terminated");
DeepCleanerDaemon::Get().Terminate();
break;
case SIGHUP:
syslog(LOG_INFO, "Reloading configuration");
DeepCleanerDaemon::Get().ReloadConfig();
break;
default:
break;
}
}

void deleteDirectoriesByDepth(const std::string& rootPathStr, int depth)
{
std::filesystem::path rootPath(rootPathStr);

if (depth < 0) {
syslog(LOG_ERR, "Error: depth cannot be negative.");
return;
}

for (const auto& entry : std::filesystem::directory_iterator(rootPath)) {
if (std::filesystem::is_directory(entry)) {
if (depth > 0) {
deleteDirectoriesByDepth(entry.path().string(), depth - 1);
}
syslog(LOG_INFO, "Removing directory: %s", entry.path().c_str());
std::filesystem::remove_all(entry.path());
}
}
}

void DeepCleanerDaemon::KillExistingDaemon()
{
syslog(LOG_INFO, "Checking for any existing daemon processes");
std::ifstream pidFile(pidPath);
if (pidFile.is_open())
{
int runningDaemonPid = 0;
if (pidFile >> runningDaemonPid && kill(runningDaemonPid, 0) == 0)
{
syslog(LOG_WARNING, "Stopping the existing daemon with PID: %i", runningDaemonPid);
kill(runningDaemonPid, SIGTERM);
}
}
}

void DeepCleanerDaemon::WritePid()
{
syslog(LOG_INFO, "Writing PID to file");
std::ofstream pidFile(pidPath.c_str());
if (!pidFile.is_open())
{
syslog(LOG_ERR, "Error writing PID to file");
exit(EXIT_FAILURE);
}
pidFile << getpid();
syslog(LOG_INFO, "PID written successfully");
}

void DeepCleanerDaemon::Daemonize()
{
syslog(LOG_INFO, "Starting daemonization process");

pid_t processId = fork();
syslog(LOG_INFO, "Forked process with PID: %i", processId);
if (processId < 0)
{
syslog(LOG_ERR, "Error during fork");
exit(EXIT_FAILURE);
}
if (processId > 0)
{
exit(EXIT_SUCCESS);
}

umask(0);
if (setsid() < 0)
{
syslog(LOG_ERR, "Error setting group ID");
exit(EXIT_FAILURE);
}
if (chdir("/") < 0)
{
syslog(LOG_ERR, "Error switching to root directory");
exit(EXIT_FAILURE);
}
for (int x = sysconf(_SC_OPEN_MAX); x >= 0; --x)
{
close(x);
}

int devNull = open("/dev/null", O_RDWR);
dup2(devNull, STDIN_FILENO);
dup2(devNull, STDOUT_FILENO);
dup2(devNull, STDERR_FILENO);
syslog(LOG_INFO, "Daemonization process completed");
}

void DeepCleanerDaemon::Initialize(const std::string& configLocalPath)
{
configAbsPath = std::filesystem::absolute(configLocalPath);

openlog("DeepCleanerDaemon", LOG_NDELAY | LOG_PID | LOG_PERROR, LOG_USER);
syslog(LOG_INFO, "Initializing daemon");

KillExistingDaemon();
Daemonize();

syslog(LOG_INFO, "Setting up signal handlers");
std::signal(SIGHUP, handleSignal);
std::signal(SIGTERM, handleSignal);

WritePid();

ReloadConfig();
syslog(LOG_INFO, "Daemon initialization finished");
}

void DeepCleanerDaemon::Run()
{
while (!isTerminateReceived)
{
if (!std::filesystem::is_directory(targetDirPath))
{
syslog(LOG_WARNING, "Warning: Target directory path from config does not exist, continuing to wait");
}
else
{
deleteDirectoriesByDepth(targetDirPath, depth);
}
std::this_thread::sleep_for(sleepDuration);
}
}

void DeepCleanerDaemon::Terminate()
{
isTerminateReceived = true;
closelog();
syslog(LOG_INFO, "Daemon termination initiated");
}

void DeepCleanerDaemon::ReloadConfig()
{
std::ifstream configFile(configAbsPath);
if (!configFile.is_open())
{
syslog(LOG_ERR, "Error: Invalid config file");
exit(EXIT_FAILURE);
}
if (!std::getline(configFile, targetDirPath))
{
syslog(LOG_ERR, "Error: Cannot read target directory path from config file");
exit(EXIT_FAILURE);
}
syslog(LOG_INFO, "Target directory path set to \"%s\"", targetDirPath.c_str());

int sleepTimeSeconds = -1;
if (!(configFile >> sleepTimeSeconds))
{
syslog(LOG_WARNING, "Warning: Cannot read sleep time from config file, using default value");
sleepDuration = defaultSleepDuration;
}
else if (sleepTimeSeconds <= 0)
{
syslog(LOG_WARNING, "Warning: Sleep time from config file is not positive, using default value");
sleepDuration = defaultSleepDuration;
}
else
{
sleepDuration = std::chrono::seconds(sleepTimeSeconds);
}
syslog(LOG_INFO, "Sleep time set to %li seconds", static_cast<long>(sleepDuration.count()));
}
40 changes: 40 additions & 0 deletions Khamidullin.Ilsaf/lab1/daemon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <string>
#include <chrono>

class DeepCleanerDaemon
{
private:
const std::string pidPath = "/var/run/deep_deletion_daemon.pid";
const int depth = 3;
const std::chrono::seconds defaultSleepDuration = std::chrono::seconds(10);

std::string configAbsPath;
std::string targetDirPath;
std::chrono::seconds sleepDuration;
bool isTerminateReceived = false;

DeepCleanerDaemon() {};
DeepCleanerDaemon(const DeepCleanerDaemon &) = delete;
DeepCleanerDaemon &operator=(const DeepCleanerDaemon &) = delete;

void WritePid();
void Daemonize();
void KillExistingDaemon();

public:
static DeepCleanerDaemon &Get()
{
static DeepCleanerDaemon instance;
return instance;
}

void Initialize(const std::string& configLocalPath);

void Terminate();

void ReloadConfig();

void Run();
};
16 changes: 16 additions & 0 deletions Khamidullin.Ilsaf/lab1/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "daemon.hpp"
#include <iostream>

int main(int argc, char** argv)
{
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " <configuration_file>" << std::endl;
return EXIT_FAILURE;
}

DeepCleanerDaemon::Get().Initialize(argv[1]);
DeepCleanerDaemon::Get().Run();

return EXIT_SUCCESS;
}
33 changes: 33 additions & 0 deletions Khamidullin.Ilsaf/lab2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
cmake_minimum_required(VERSION 3.14)

project(WolfAndGoats VERSION 0.1 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_compile_options(-Wall -Werror -DCMAKE_EXE_LINKER_FLAGS=-latomic)

find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick REQUIRED)
find_package (Threads)
find_library (LIBRT rt)

set(CLIENT goat)
set(HOST wolf)
set(CONNECTION connections)
set(UTILS utils)

foreach(CONN mq fifo sock)
add_executable(host_${CONN} ${HOST}/wolf.cpp ${HOST}/wolf.h ${HOST}/host.cpp
${CLIENT}/goat.cpp ${CLIENT}/goat.h
${UTILS}/configuration.h ${UTILS}/message.h
${CONNECTION}/conn.h ${CONNECTION}/conn_${CONN}.cpp ${CONNECTION}/conn_${CONN}.h
gui/gui.cpp gui/gui.h
gui/qml.qrc)
target_link_libraries(host_${CONN} PUBLIC rt pthread Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Quick)
endforeach(CONN mq fifo sock)
12 changes: 12 additions & 0 deletions Khamidullin.Ilsaf/lab2/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mkdir build
cd build

apt install qml-module-qtquick-window2
apt install qml-module-qtquick-layouts
apt install qml-module-qtquick-controls2

cmake ..
make -j2
mv host_sock host_mq host_fifo ..
cd ..
rm -r build
18 changes: 18 additions & 0 deletions Khamidullin.Ilsaf/lab2/connections/conn.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "sys/types.h"
#include "utils/message.h"
#include <memory>

class Connection
{
public:
virtual ~Connection() = default;

static std::unique_ptr<Connection> create();

virtual bool open(pid_t pid, bool isHost) = 0;
virtual bool read(Message &msg) const = 0;
virtual bool write(const Message &msg) = 0;
virtual bool close() = 0;
};
Loading