diff --git a/configs/ncsambawatcher.service b/configs/ncsambawatcher.service index c2330c1..f4f35f3 100644 --- a/configs/ncsambawatcher.service +++ b/configs/ncsambawatcher.service @@ -1,6 +1,7 @@ [Unit] Description=A service which scan Nextcloud folders -After=network.target +After=network.target docker.service +Requires=docker.service [Service] ExecStart=/usr/bin/ncsambawatcher diff --git a/src/main.cpp b/src/main.cpp index bd9b6d4..0a16c9a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,119 +1,102 @@ +#include +#include +#include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include "locations.h" +#include +#include +#include #include "usermanager.h" -#include "guarder.h" -#define MAXNAMESIZE 255 -#define SCAN_DONE_SIG SIGRTMIN #define SCAN_CMD_USR "docker exec --user www-data nextcloud /var/www/html/occ files:scan --path=" -int p1[2]; -guarder guard; userManager manager; +std::condition_variable cv; +std::mutex mtx; -void flushManagerToPipe() +void readingThreadFunc() { - if (!guard.isFlagOn()) - { - std::vector users = manager.getFlaggedUsers(); + FILE *logpipe = popen(LOGFILE, "r"); + std::array buffer; + + while (fgets(buffer.data(), buffer.size(), logpipe) != nullptr) + { + std::string line(buffer.data()); + + if (line.find('|') == std::string::npos) + continue; + + std::vector x = splitLogFile(line, '|'); + std::string user(x.at(USER_LOG_LOCATION)); - for (std::vector::iterator it = users.begin(); it != users.end(); ++it) { - int size = it->size(); - write(p1[1], &size, sizeof(int)); - write(p1[1], it->data(), size * sizeof(char)); + std::lock_guard lock(mtx); + manager.addUser(user); + manager.setUserFlagged(user); } - manager.unflagAllUsers(); + cv.notify_one(); + + std::cout << "User find: " << user << std::endl; } } -void handler(int sig) +void scannerThreadFunc() { - if (sig == SCAN_DONE_SIG) + std::unique_lock lock(mtx); + std::vector childrens; + while (true) { - flushManagerToPipe(); + cv.wait(lock, [] + { return manager.isAnybodyFlagged(); }); + + std::set scanUsers = manager.getFlaggedUsers(); + manager.unflagAllUsers(); + + lock.unlock(); + childrens.clear(); + + for (const std::string& user : scanUsers) + { + pid_t child = fork(); + + if (child < 0) + { + std::cerr << "Fork failed for: " << user << std::endl; + } + else if (child == 0) // child + { + std::string cmd = (std::string(SCAN_CMD_USR) + user); + execl("/bin/sh", "sh", "-c", cmd.c_str(), static_cast(nullptr)); + std::cerr << "Scan failed" << std::endl; + _exit(EXIT_FAILURE); + } + else // parent + { + childrens.push_back(child); + } + } + + for (const pid_t& pid : childrens) + { + waitpid(pid, nullptr, 0); + } + + lock.lock(); } } int main() { - openlog("ncsambawatcher", LOG_PID | LOG_CONS, LOG_USER); - pipe(p1); + std::thread readingThread(readingThreadFunc); + std::thread scannerThread(scannerThreadFunc); - pid_t parent = getpid(); - pid_t child = fork(); + readingThread.join(); + scannerThread.join(); - if (child > 0) // parent - { - signal(SCAN_DONE_SIG, handler); - close(p1[0]); // read - - FILE *logpipe = popen(LOGFILE, "r"); - std::array buffer; - - while (fgets(buffer.data(), buffer.size(), logpipe) != nullptr) - { - std::string line(buffer.data()); - - if (line.find('|') == std::string::npos) - continue; - - std::vector x = splitLogFile(line, '|'); - std::string user(x.at(USER_LOG_LOCATION)); - manager.addUser(user); - manager.setUserFlagged(user); - - std::cout << "User find: " << user << std::endl; - - flushManagerToPipe(); - } - - fclose(logpipe); - close(p1[1]); // write - } - else // child - { - close(p1[1]); // write - - int size; - char *buffer = nullptr; - - while (read(p1[0], &size, sizeof(int))) - { - if (buffer == nullptr) - buffer = new char[size]; - - read(p1[0], buffer, size * sizeof(char)); - std::string name(buffer); - - std::cout << "Scan received for: " << name << std::endl; - - guard.setFlagOn(); - system((std::string(SCAN_CMD_USR) + name).data()); - guard.setFlagOff(); - - kill(parent, SCAN_DONE_SIG); - - if (buffer != nullptr) - { - delete[] buffer; - buffer = nullptr; - } - } - - close(p1[0]); // read - } - - closelog(); - - return EXIT_SUCCESS; + return 0; } \ No newline at end of file diff --git a/src/usermanager.h b/src/usermanager.h index 972d358..5a7ea14 100644 --- a/src/usermanager.h +++ b/src/usermanager.h @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include "locations.h" std::vector splitLogFile(const std::string& input, char delimiter); @@ -13,6 +15,7 @@ class userManager { private: std::map users; + std::mutex mtx; public: @@ -23,6 +26,7 @@ public: void addUser(std::string &user) { + std::lock_guard lock(mtx); if (users.count(user) == 0) { users[user] = false; @@ -31,16 +35,19 @@ public: void removeUser(std::string &user) { + std::lock_guard lock(mtx); users.erase(user); } bool isContains(std::string &user) { + std::lock_guard lock(mtx); return users.count(user) == 1; } void setUserFlagged(std::string &user) { + std::lock_guard lock(mtx); if (users.count(user) == 1) { users[user] = true; @@ -49,6 +56,7 @@ public: void setUserUnflagged(std::string &user) { + std::lock_guard lock(mtx); if (users.count(user) == 1) { users[user] = false; @@ -57,38 +65,56 @@ public: void unflagAllUsers() { + std::lock_guard lock(mtx); for (std::map::iterator it = users.begin(); it != users.end(); ++it) { it->second = false; } } - std::vector getUsers() + std::set getUsers() { - std::vector ret; + std::set ret; + + std::lock_guard lock(mtx); for (std::map::iterator it = users.begin(); it != users.end(); ++it) { - ret.push_back(it->first); + ret.insert(it->first); } return ret; } - std::vector getFlaggedUsers() + std::set getFlaggedUsers() { - std::vector ret; + std::set ret; + + std::lock_guard lock(mtx); for (std::map::iterator it = users.begin(); it != users.end(); ++it) { if (it->second) { - ret.push_back(it->first); + ret.insert(it->first); } } return ret; } + + bool isAnybodyFlagged() + { + std::lock_guard lock(mtx); + + for (std::map::iterator it = users.begin(); it != users.end(); ++it) + { + if (it->second) + return true; + } + + return false; + } }; #endif // _USERMAN_H \ No newline at end of file