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 change: 1 addition & 0 deletions AsanovDamir/laba1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
7 changes: 7 additions & 0 deletions AsanovDamir/laba1/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.5)

project(DamirAsanov)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")

add_executable(DamirAsanov main.cpp Deamon.cpp Config.cpp)
37 changes: 37 additions & 0 deletions AsanovDamir/laba1/Config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "Config.hpp"
#include <fstream>
#include <filesystem>

std::string Config::get_absolute_path(const char* pathStr)
{
std::filesystem::path absPath = std::filesystem::absolute(pathStr);
if (std::filesystem::exists(absPath))
return absPath.c_str();
else
return "";

return std::filesystem::absolute(pathStr).c_str();
}

Config::Config() : pathToConfig{get_absolute_path("Config.txt")}
{}

bool Config::read_config()
{
std::ifstream config(pathToConfig.c_str());
if (!config) return false;

std::getline(config, folder1);
folder1 = get_absolute_path(folder1.c_str());
std::getline(config, folder2);
folder2 = get_absolute_path(folder2.c_str());
config >> seconds;

if (folder1.empty() || folder2.empty() || seconds == 0 || pathToConfig.empty()) return false;
return true;
}

void Config::set_path_to_config(const char* path_to_config)
{
pathToConfig = get_absolute_path(path_to_config);
}
23 changes: 23 additions & 0 deletions AsanovDamir/laba1/Config.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <string>

class Config
{
public:
Config();
bool read_config();

const std::string& get_folder1() const { return folder1; }
const std::string& get_folder2() const { return folder2; }
int get_seconds() const { return seconds; }
void set_path_to_config(const char* path_to_config);

private:
std::string get_absolute_path(const char* path);

std::string pathToConfig;
std::string folder1;
std::string folder2;
int seconds;
};
3 changes: 3 additions & 0 deletions AsanovDamir/laba1/Config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FirstFolder
SecondFolder
10
167 changes: 167 additions & 0 deletions AsanovDamir/laba1/Deamon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#include "Deamon.hpp"
#include <signal.h>
#include <sys/stat.h>
#include <filesystem>
#include <fstream>

Config Deamon::config;

const char* PID = "/var/run/Deamon.pid";

Deamon& Deamon::get_instance()
{
static Deamon instance;
return instance;
}

void Deamon::destroy_prev_deamon_if_exist()
{
if (std::ifstream pid_file(PID); pid_file) {
pid_t pid;
pid_file >> pid;
if (kill(pid, 0) == 0) {
Logger::get_instance().log(Status::INFO, "Deamon is already running. Killing the old instance...");
if (kill(pid, SIGTERM) != 0) {
Logger::get_instance().log(Status::ERROR, "Failed to terminate the existing daemon process.");
unlink(PID);
}
}
}
}

bool Deamon::crate_pid_file()
{
std::ofstream new_pid_file(PID);
if (!new_pid_file) {
Logger::get_instance().log(Status::ERROR, "Failed to create PID file.");
return false;
}

new_pid_file << getpid();
return true;
}

void Deamon::daemonize()
{
pid_t pid = fork();
if (pid < 0)
exit(EXIT_FAILURE);
if (pid > 0)
exit(EXIT_SUCCESS);

if (setsid() < 0)
exit(EXIT_FAILURE);

signal(SIGHUP, SIG_IGN);

pid = fork();
if (pid < 0)
exit(EXIT_FAILURE);
if (pid > 0)
exit(EXIT_SUCCESS);

umask(0);
chdir("/");

close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}

bool Deamon::coping()
{
namespace fs = std::filesystem;

const std::string& folder1 = config.get_folder1();
const std::string& folder2 = config.get_folder2();

const std::string imgDir = folder2 + "/IMG";
const std::string othersDir = folder2 + "/OTHERS";

try {
// Clear folder 2
if (fs::exists(folder2)) {
for (const auto& entry : fs::directory_iterator(folder2)) {
fs::remove_all(entry.path());
}
} else {
fs::create_directories(folder2);
}

// Craate IMG and OTHERS folders
fs::create_directories(imgDir);
fs::create_directories(othersDir);

// coping
for (const auto& entry : fs::directory_iterator(folder1)) {
if (entry.is_regular_file()) {
std::string fileName = entry.path().filename().string();
std::string destPath;
if (entry.path().extension() == ".png") {
destPath = imgDir + "/" + fileName;
} else {
destPath = othersDir + "/" + fileName;
}
fs::copy(entry.path(), destPath);
}
}
} catch (const std::exception& ex) {
Logger::get_instance().log(Status::ERROR, "Error during copying: " + std::string(ex.what()));
return false;
}

Logger::get_instance().log(Status::INFO, "Copied files from" + folder1 + " to " + folder2);
return true;
}

void Deamon::start(const char* config_path)
{
config.set_path_to_config(config_path);

destroy_prev_deamon_if_exist();
daemonize();

Logger::get_instance().open_log();
Logger::get_instance().log(Status::INFO, "Start deamon");

if (!config.read_config()) {

Logger::get_instance().log(Status::ERROR, std::string("Failed to read config"));
exit(EXIT_FAILURE);
}

if (!crate_pid_file())
exit(EXIT_FAILURE);

handle_signals();

while (true) {
coping();
sleep(config.get_seconds());
}
}

void Deamon::handle_signals()
{
signal(SIGHUP, sighup_handler);
signal(SIGTERM, sigterm_handler);
}

void Deamon::sighup_handler(int)
{
Logger::get_instance().log(Status::INFO, "Re-reading config");
if (!config.read_config()) {
Logger::get_instance().log(Status::ERROR, "Failed to read config");
Logger::get_instance().close_log();
unlink(PID);
exit(EXIT_FAILURE);
}
}

void Deamon::sigterm_handler(int)
{
Logger::get_instance().log(Status::INFO, "Terminating");
Logger::get_instance().close_log();
unlink(PID);
exit(0);
}
27 changes: 27 additions & 0 deletions AsanovDamir/laba1/Deamon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include "Logger.hpp"
#include "Config.hpp"

class Deamon
{
public:
static Deamon& get_instance();
void start(const char* config_path);
bool coping();

private:
Deamon() = default;
Deamon(const Deamon&) = delete;
Deamon& operator=(const Deamon&) = delete;

void handle_signals();
static void sighup_handler(int signum);
static void sigterm_handler(int signum);

void daemonize();
bool crate_pid_file();
void destroy_prev_deamon_if_exist();

static Config config;
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
35 changes: 35 additions & 0 deletions AsanovDamir/laba1/Logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include <string>
#include <syslog.h>

enum class Status : short
{
INFO = LOG_INFO,
ERROR = LOG_ERR
};

class Logger
{
public:
static Logger& get_instance()
{
static Logger instance;
return instance;
}

void open_log()
{
openlog("Deamon", LOG_PID, LOG_DAEMON);
}
void log(Status status, const std::string& message)
{
syslog(static_cast<int>(status), "%s", message.c_str());
}
void close_log() { closelog(); }

private:
Logger() = default;
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
};
22 changes: 22 additions & 0 deletions AsanovDamir/laba1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Проект: Demon

# Автор

Асанов Дамир Русланович 5030102/10201 Лабораторная работа №1 вариант №9:

## Описание

Копировать содержимое папки 1 в папку 2(предварительно очищая содержимое папки 2) следующим образом: файлы с расширением “*.png”
должны помещаться в подпапку “IMG” папки 2, остальные — в подпапку “OTHERS”

## Запуск

введите команду ```bash build.sh```, чтобы собрать проект
введите команду ```bash run.sh```, чтобы запустить демона
введите команду ```bash kill```, чтобы остановить демона
введите команду ```bash reconfig```, чтобы демон перепрочитал конфиг

форма конфига:
первая строчка - путь к первой папке, откуда будет происоходить копирование
вторая строчка - путь ко второй папке, куда будет копироваться
третья строчка - целое число - количество секунд между операцией копирования
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
11 changes: 11 additions & 0 deletions AsanovDamir/laba1/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
mkdir -p build
cd build
cmake ..
make

find . -type f -name '*.o' -delete
find . -type f -name '*.cmake' -delete
find . -type f -name 'CMakeCache.txt' -delete
find . -type f -name 'Makefile' -delete
rm -rf CMakeFiles
2 changes: 2 additions & 0 deletions AsanovDamir/laba1/kill
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
sudo kill -SIGTERM $(cat /var/run/Deamon.pid)
14 changes: 14 additions & 0 deletions AsanovDamir/laba1/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "Deamon.hpp"
#include <iostream>

int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cout << "Wrong count of argument. Expected path to config" << std::endl;
return 1;
}
const char* config_path = argv[1];
Deamon::get_instance().start(config_path);
return 0;
}
2 changes: 2 additions & 0 deletions AsanovDamir/laba1/reconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
sudo kill -SIGHUP $(cat /var/run/Deamon.pid)
1 change: 1 addition & 0 deletions AsanovDamir/laba1/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sudo ./build/DamirAsanov Config.txt
1 change: 1 addition & 0 deletions AsanovDamir/laba2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
9 changes: 9 additions & 0 deletions AsanovDamir/laba2/Book.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <string>

struct Book
{
std::string name;
int count;
};
Loading