diff options
-rwxr-xr-x | configure.ac | 2 | ||||
-rw-r--r-- | sync_manager.cpp | 66 | ||||
-rw-r--r-- | sync_manager.hpp | 8 | ||||
-rw-r--r-- | sync_manager_main.cpp | 3 | ||||
-rw-r--r-- | sync_watch.cpp | 39 | ||||
-rw-r--r-- | sync_watch.hpp | 4 |
6 files changed, 115 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac index 1155cfe..0165e08 100755 --- a/configure.ac +++ b/configure.ac @@ -96,6 +96,8 @@ AC_DEFINE(MEDIA_DIR, "/media/", [The base dir where all RO partitions are mounted]) AC_DEFINE(BMC_ROFS_PREFIX, "/media/rofs-", [The prefix path for the versioned read-only bmc partitions]) +AC_DEFINE(ALT_RWFS, "/media/alt/var/persist", + [The path of the alt rwfs overlay]) AC_DEFINE(PERSIST_DIR, "/var/lib/obmc/phosphor-bmc-code-mgmt/", [The dir where activation data is stored in files]) AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1", diff --git a/sync_manager.cpp b/sync_manager.cpp index 6a50711..f83aebd 100644 --- a/sync_manager.cpp +++ b/sync_manager.cpp @@ -1,3 +1,9 @@ +#include <experimental/filesystem> +#include <phosphor-logging/log.hpp> +#include <sys/inotify.h> +#include <sys/wait.h> +#include <unistd.h> +#include "config.h" #include "sync_manager.hpp" namespace phosphor @@ -7,8 +13,66 @@ namespace software namespace manager { -int Sync::processEntry() +using namespace phosphor::logging; +namespace fs = std::experimental::filesystem; + +int Sync::processEntry(int mask, const fs::path& entryPath) { + int status{}; + pid_t pid = fork(); + + if (pid == 0) + { + fs::path dst(ALT_RWFS / entryPath); + + // rsync needs an additional --delete argument to handle file deletions + // so need to differentiate between the different file events. + if (mask & IN_CLOSE_WRITE) + { + if (!(fs::exists(dst))) + { + if (fs::is_directory(entryPath)) + { + // Source is a directory, create it at the destination. + fs::create_directories(dst); + } + else + { + // Source is a file, create the directory where this file + // resides at the destination. + fs::create_directories(dst.parent_path()); + } + } + + execl("/usr/bin/rsync", "rsync", "-a", entryPath.c_str(), + dst.c_str(), nullptr); + // execl only returns on fail + log<level::ERR>("Error occurred during the rsync call", + entry("ERRNO=%d", errno), + entry("PATH=%s", entryPath.c_str())); + return -1; + } + else if (mask & IN_DELETE) + { + execl("/usr/bin/rsync", "rsync", "-a", "--delete", + entryPath.c_str(), dst.c_str(), nullptr); + // execl only returns on fail + log<level::ERR>("Error occurred during the rsync delete call", + entry("ERRNO=%d", errno), + entry("PATH=%s", entryPath.c_str())); + return -1; + } + } + else if (pid > 0) + { + waitpid(pid, &status, 0); + } + else + { + log<level::ERR>("Error occurred during fork", entry("ERRNO=%d", errno)); + return -1; + } + return 0; } diff --git a/sync_manager.hpp b/sync_manager.hpp index a940461..45bfca4 100644 --- a/sync_manager.hpp +++ b/sync_manager.hpp @@ -1,5 +1,7 @@ #pragma once +#include <experimental/filesystem> + namespace phosphor { namespace software @@ -7,6 +9,8 @@ namespace software namespace manager { +namespace fs = std::experimental::filesystem; + /** @class Sync * @brief Contains filesystem sync functions. * @details The software manager class that contains functions to perform @@ -24,9 +28,11 @@ class Sync /** * @brief Process requested file or directory. + * @param[in] mask - The inotify mask. + * @param[in] entryPath - The file or directory to process. * @param[out] result - 0 if successful. */ - int processEntry(); + int processEntry(int mask, const fs::path& entryPath); }; } // namespace manager diff --git a/sync_manager_main.cpp b/sync_manager_main.cpp index 46a2d95..e1834b5 100644 --- a/sync_manager_main.cpp +++ b/sync_manager_main.cpp @@ -23,7 +23,8 @@ int main(int argc, char* argv[]) using namespace phosphor::software::manager; phosphor::software::manager::SyncWatch watch( - *loop, std::bind(std::mem_fn(&Sync::processEntry), &syncManager)); + *loop, std::bind(std::mem_fn(&Sync::processEntry), &syncManager, + std::placeholders::_1, std::placeholders::_2)); bus.attach_event(loop, SD_EVENT_PRIORITY_NORMAL); sd_event_loop(loop); } diff --git a/sync_watch.cpp b/sync_watch.cpp index 0fc61d8..a8b4eeb 100644 --- a/sync_watch.cpp +++ b/sync_watch.cpp @@ -17,7 +17,7 @@ using namespace phosphor::logging; namespace fs = std::experimental::filesystem; SyncWatch::SyncWatch(sd_event& loop, - std::function<int(fs::path&)> syncCallback) : + std::function<int(int, fs::path&)> syncCallback) : syncCallback(syncCallback) { auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME; @@ -37,7 +37,8 @@ SyncWatch::SyncWatch(sd_event& loop, continue; } - auto wd = inotify_add_watch(fd, line.c_str(), IN_CLOSE_WRITE); + auto wd = + inotify_add_watch(fd, line.c_str(), IN_CLOSE_WRITE | IN_DELETE); if (-1 == wd) { log<level::ERR>("inotify_add_watch failed", @@ -81,6 +82,40 @@ SyncWatch::~SyncWatch() int SyncWatch::callback(sd_event_source* s, int fd, uint32_t revents, void* userdata) { + if (!(revents & EPOLLIN)) + { + return 0; + } + + constexpr auto maxBytes = 1024; + uint8_t buffer[maxBytes]; + auto bytes = read(fd, buffer, maxBytes); + if (0 > bytes) + { + return 0; + } + + auto syncWatch = static_cast<SyncWatch*>(userdata); + auto offset = 0; + while (offset < bytes) + { + auto event = reinterpret_cast<inotify_event*>(&buffer[offset]); + + // fileMap<fd, std::map<wd, path>> + auto it1 = syncWatch->fileMap.find(fd); + if (it1 != syncWatch->fileMap.end()) + { + auto it2 = it1->second.begin(); + auto rc = syncWatch->syncCallback(event->mask, it2->second); + if (rc) + { + return rc; + } + } + + offset += offsetof(inotify_event, name) + event->len; + } + return 0; } diff --git a/sync_watch.hpp b/sync_watch.hpp index a7f8557..4303671 100644 --- a/sync_watch.hpp +++ b/sync_watch.hpp @@ -29,7 +29,7 @@ class SyncWatch * @param[in] syncCallback - The callback function for processing * files */ - SyncWatch(sd_event& loop, std::function<int(fs::path&)> syncCallback); + SyncWatch(sd_event& loop, std::function<int(int, fs::path&)> syncCallback); SyncWatch(const SyncWatch&) = delete; SyncWatch& operator=(const SyncWatch&) = delete; @@ -58,7 +58,7 @@ class SyncWatch std::map<fd, std::map<wd, fs::path>> fileMap; /** @brief The callback function for processing the inotify event */ - std::function<int(fs::path&)> syncCallback; + std::function<int(int, fs::path&)> syncCallback; }; } // namespace manager |