diff options
author | Adrian Kummerlaender | 2016-02-17 21:58:38 +0100 |
---|---|---|
committer | Adrian Kummerlaender | 2016-02-17 21:58:38 +0100 |
commit | 3294bfe789ff354ca372f7c32275316bf4491ca5 (patch) | |
tree | 0ee3f580402b87edb57129d2ca56460657d5d609 /src/main.cc | |
parent | af756d78ac042a2eed2417c5250d4b675d43bf93 (diff) | |
download | change-3294bfe789ff354ca372f7c32275316bf4491ca5.tar change-3294bfe789ff354ca372f7c32275316bf4491ca5.tar.gz change-3294bfe789ff354ca372f7c32275316bf4491ca5.tar.bz2 change-3294bfe789ff354ca372f7c32275316bf4491ca5.tar.lz change-3294bfe789ff354ca372f7c32275316bf4491ca5.tar.xz change-3294bfe789ff354ca372f7c32275316bf4491ca5.tar.zst change-3294bfe789ff354ca372f7c32275316bf4491ca5.zip |
Separate static allocator from payload function interpositions
Diffstat (limited to 'src/main.cc')
-rw-r--r-- | src/main.cc | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..8b6ca23 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,173 @@ +#include "actual.h" + +#include "utility/io.h" +#include "utility/logger.h" + +#include "tracking/path_matcher.h" +#include "tracking/change_tracker.h" + +// `true` signals the interposed functions to execute tracking logic +// `false` signals the interposed functions to do plain forwarding +static bool enabled = false; + +static std::unique_ptr<utility::FileDescriptorGuard> fd_guard; +static std::unique_ptr<utility::Logger> logger; +static std::unique_ptr<tracking::PathMatcher> matcher; +static std::unique_ptr<tracking::ChangeTracker> tracker; + +void initialize() __attribute__ ((constructor)); +void initialize() { + if ( getenv("CHANGE_LOG_TARGET") != NULL ) { + fd_guard = std::make_unique<utility::FileDescriptorGuard>( + getenv("CHANGE_LOG_TARGET") + ); + logger = std::make_unique<utility::Logger>(*fd_guard); + } else { + logger = std::make_unique<utility::Logger>(STDERR_FILENO); + } + + if ( getenv("CHANGE_LOG_DIFF_CMD") != NULL ) { + tracker = std::make_unique<tracking::ChangeTracker>( + logger.get(), getenv("CHANGE_LOG_DIFF_CMD") + ); + } else { + tracker = std::make_unique<tracking::ChangeTracker>(logger.get()); + } + + if ( getenv("CHANGE_LOG_IGNORE_PATTERN_PATH") != NULL ) { + matcher = std::make_unique<tracking::PathMatcher>( + getenv("CHANGE_LOG_IGNORE_PATTERN_PATH") + ); + } else { + matcher = std::make_unique<tracking::PathMatcher>(); + } + + // tracking is only enabled when everything is initialized as both + // the actual tracking and the decision if a event should be tracked + // depend on `logger` and `tracker` being fully instantiated. + // In most cases this library will work correctly without delayed + // activation but e.g. `nvim` crashes as it performs tracked syscalls + // before `init` has been called. + enabled = true; +} + +inline void track_write(const int fd) { + if ( enabled && fd != *fd_guard && utility::is_regular_file(fd) ) { + const auto path = utility::get_file_path(fd); + + if ( !matcher->isMatching(path) ) { + tracker->track(path); + } + } +} + +inline void track_rename( + const std::string& old_path, const std::string& new_path) { + if ( enabled ) { + if ( !matcher->isMatching(old_path) ) { + tracker->track(old_path); + + if ( !matcher->isMatching(new_path) ) { + logger->append("renamed '", old_path, "' to '", new_path, "'"); + } + } + } +} + +inline void track_remove(const std::string& path) { + if ( enabled && utility::is_regular_file(path.c_str()) ) { + if ( !matcher->isMatching(path) ) { + logger->append("removed '", path, "'"); + } + } +} + +ssize_t write(int fd, const void* buffer, size_t count) { + static actual::ptr<ssize_t, int, const void*, size_t> actual_write{}; + + if ( !actual_write ) { + actual_write = actual::get_ptr<decltype(actual_write)>("write"); + } + + track_write(fd); + + return actual_write(fd, buffer, count); +} + +ssize_t writev(int fd, const iovec* iov, int iovcnt) { + static actual::ptr<ssize_t, int, const iovec*, int> actual_writev{}; + + if ( !actual_writev ) { + actual_writev = actual::get_ptr<decltype(actual_writev)>("writev"); + } + + track_write(fd); + + return actual_writev(fd, iov, iovcnt); +} + +void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { + static actual::ptr<void*, void*, size_t, int, int, int, off_t> actual_mmap{}; + + if ( !actual_mmap ) { + actual_mmap = actual::get_ptr<decltype(actual_mmap)>("mmap"); + } + + if ( prot & PROT_WRITE ) { + track_write(fd); + } + + return actual_mmap(addr, length, prot, flags, fd, offset); +} + +int rename(const char* old_path, const char* new_path) { + static actual::ptr<int, const char*, const char*> actual_rename{}; + + if ( !actual_rename ) { + actual_rename = actual::get_ptr<decltype(actual_rename)>("rename"); + } + + track_rename(old_path, new_path); + + return actual_rename(old_path, new_path); +} + +int rmdir(const char* path) { + static actual::ptr<int, const char*> actual_rmdir{}; + + if ( !actual_rmdir ) { + actual_rmdir = actual::get_ptr<decltype(actual_rmdir)>("rmdir"); + } + + track_remove(path); + + return actual_rmdir(path); +} + +int unlink(const char* path) { + static actual::ptr<int, const char*> actual_unlink{}; + + if ( !actual_unlink ) { + actual_unlink = actual::get_ptr<decltype(actual_unlink)>("unlink"); + } + + track_remove(path); + + return actual_unlink(path); +} + +int unlinkat(int dirfd, const char* path, int flags) { + static actual::ptr<int, int, const char*, int> actual_unlinkat{}; + + if ( !actual_unlinkat ) { + actual_unlinkat = actual::get_ptr<decltype(actual_unlinkat)>("unlinkat"); + } + + if ( dirfd == AT_FDCWD ) { + track_remove(path); + } else { + track_remove(utility::get_file_path(dirfd) + path); + } + + return actual_unlinkat(dirfd, path, flags); +} |