From baf30b7b83822b7d6efd0c16761b8e42a1e96101 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Thu, 24 Dec 2015 00:11:06 +0100 Subject: Match namespace and directory structure --- src/change_log.cc | 29 ++++++------- src/change_tracker.cc | 94 ------------------------------------------ src/change_tracker.h | 32 -------------- src/io.h | 68 ------------------------------ src/tracking/change_tracker.cc | 92 +++++++++++++++++++++++++++++++++++++++++ src/tracking/change_tracker.h | 32 ++++++++++++++ src/utility.h | 44 -------------------- src/utility/io.h | 68 ++++++++++++++++++++++++++++++ src/utility/logger.h | 44 ++++++++++++++++++++ 9 files changed, 251 insertions(+), 252 deletions(-) delete mode 100644 src/change_tracker.cc delete mode 100644 src/change_tracker.h delete mode 100644 src/io.h create mode 100644 src/tracking/change_tracker.cc create mode 100644 src/tracking/change_tracker.h delete mode 100644 src/utility.h create mode 100644 src/utility/io.h create mode 100644 src/utility/logger.h (limited to 'src') diff --git a/src/change_log.cc b/src/change_log.cc index e128383..5d16449 100644 --- a/src/change_log.cc +++ b/src/change_log.cc @@ -5,19 +5,20 @@ #include #include -#include "io.h" -#include "utility.h" #include "actual_function.h" -#include "change_tracker.h" -static std::unique_ptr fd_guard; -static std::unique_ptr logger; -static std::unique_ptr tracker; +#include "utility/io.h" +#include "utility/logger.h" +#include "tracking/change_tracker.h" + +static std::unique_ptr fd_guard; +static std::unique_ptr logger; +static std::unique_ptr tracker; void init() __attribute__ ((constructor)); void init() { if ( getenv("CHANGE_LOG_TARGET") != NULL ) { - fd_guard = std::make_unique( + fd_guard = std::make_unique( getenv("CHANGE_LOG_TARGET") ); logger = std::make_unique(*fd_guard); @@ -25,7 +26,7 @@ void init() { logger = std::make_unique(STDERR_FILENO); } - tracker = std::make_unique(logger.get()); + tracker = std::make_unique(logger.get()); } void exit(int status) { @@ -40,8 +41,8 @@ void exit(int status) { } ssize_t write(int fd, const void* buffer, size_t count) { - if ( io::is_regular_file(fd) ) { - const std::string file_name{ io::get_file_name(fd) }; + if ( utility::is_regular_file(fd) ) { + const std::string file_name{ utility::get_file_name(fd) }; if ( !tracker->is_tracked(file_name) ) { tracker->track(file_name); @@ -68,7 +69,7 @@ int rmdir(const char* path) { } int unlink(const char* path) { - if ( io::is_regular_file(path) ) { + if ( utility::is_regular_file(path) ) { logger->append("rm '" + std::string(path) + "'"); } @@ -79,15 +80,15 @@ int unlinkat(int dirfd, const char* path, int flags) { if ( dirfd == AT_FDCWD ) { logger->append("removed '" + std::string(path) + "'"); } else { - logger->append("removed '" + io::get_file_name(dirfd) + path + "'"); + logger->append("removed '" + utility::get_file_name(dirfd) + path + "'"); } return actual::unlinkat(dirfd, path, flags); } void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t offset) { - if ( ( prot & PROT_WRITE ) && io::is_regular_file(fd) ) { - const std::string file_name{ io::get_file_name(fd) }; + if ( ( prot & PROT_WRITE ) && utility::is_regular_file(fd) ) { + const std::string file_name{ utility::get_file_name(fd) }; if ( !tracker->is_tracked(file_name) ) { tracker->track(file_name); diff --git a/src/change_tracker.cc b/src/change_tracker.cc deleted file mode 100644 index 1373a8a..0000000 --- a/src/change_tracker.cc +++ /dev/null @@ -1,94 +0,0 @@ -#include "change_tracker.h" - -#include - -#include -#include - -namespace { - -// constants for increasing pair access readability -constexpr unsigned int EMPLACE_SUCCESS = 1; -constexpr unsigned int FILE_NAME = 0; -constexpr unsigned int DIFF_PROCESS = 1; - -boost::process::context createContext() { - boost::process::context context; - - context.environment = boost::process::self::get_environment(); - context.stdout_behavior = boost::process::capture_stream(); - context.stdin_behavior = boost::process::capture_stream(); - - return context; -} - -} - -namespace utility { - -ChangeTracker::ChangeTracker(utility::Logger* logger): - logger_(logger), - children_() { } - -ChangeTracker::~ChangeTracker() { - for ( auto&& tracked : this->children_ ) { - std::get(tracked)->get_stdin().close(); - - this->logger_->forward(std::get(tracked)->get_stdout()); - - tracked.second->wait(); - } -} - -bool ChangeTracker::is_tracked(const std::string& file_path) const { - return this->children_.find(file_path) != this->children_.end(); -} - -// Begins tracking changes to a file reachable by a given path -// -// The actual tracking is performed by a `diff` instance that is -// spawned by this method and managed by this class. -// As `diff` is called as a new subprocess and because there is no -// straight forward way for checking / enforcing if it has already -// completed reading the initial contents of the file the command -// is structured in the following sequence: -// -// diff -p - $file_path -// -// This means that reading the final file contents is delegated to -// `diff` while the initial file contents are read by this method -// and written to `diff`'s standard input. -// -// If the `-` and `$file_path` arguments were exchanged there would -// be no way to: -// - be sure the initial contents are read before the changing -// syscall that triggered this tracking in the first place is -// performed -// - be sure that the initial file contents are read completly -// as `diff` seemingly only reads the first block of the first -// file provided if the second file argument is standard input -// -bool ChangeTracker::track(const std::string& file_path) { - auto result = this->children_.emplace( - file_path, - std::make_unique( - boost::process::launch_shell("diff -p - " + file_name, createContext()) - ) - ); - - if ( std::get(result) ) { - boost::filesystem::ifstream file( - std::get(*result.first) - ); - - if ( file.is_open() ) { - std::get(*result.first)->get_stdin() << file.rdbuf(); - } - - return true; - } else { - return false; - } -} - -} diff --git a/src/change_tracker.h b/src/change_tracker.h deleted file mode 100644 index e8ffa32..0000000 --- a/src/change_tracker.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef CHANGE_SRC_CHANGE_TRACKER_H_ -#define CHANGE_SRC_CHANGE_TRACKER_H_ - -#include "utility.h" - -#include - -#include - -namespace utility { - -class ChangeTracker { - public: - ChangeTracker(utility::Logger*); - ~ChangeTracker(); - - bool is_tracked(const std::string&) const; - - bool track(const std::string&); - - private: - utility::Logger* const logger_; - - std::unordered_map< - std::string, std::unique_ptr - > children_; - -}; - -} - -#endif // CHANGE_SRC_CHANGE_TRACKER_H_ diff --git a/src/io.h b/src/io.h deleted file mode 100644 index 69caa5e..0000000 --- a/src/io.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef CHANGE_SRC_IO_H_ -#define CHANGE_SRC_IO_H_ - -#include -#include -#include -#include - -#include - -namespace io { - -class FileDescriptorGuard { - public: - FileDescriptorGuard(const std::string& path) { - this->fd = open(path.c_str(), O_CREAT | O_WRONLY | O_APPEND); - - if ( !this->fd ) { - this->fd = STDERR_FILENO; - } - } - - ~FileDescriptorGuard() { - close(this->fd); - } - - operator int() { - return this->fd; - } - - private: - int fd; - -}; - -std::string get_file_name(int fd) { - char proc_link[20]; - char file_name[256]; - - snprintf(proc_link, sizeof(proc_link), "/proc/self/fd/%d", fd); - const ssize_t name_size = readlink(proc_link, file_name, sizeof(file_name)); - - if ( name_size > 0 ) { - file_name[name_size] = '\0'; - - return std::string(file_name); - } else { - return std::string(); - } -} - -bool is_regular_file(int fd) { - struct stat fd_stat; - fstat(fd, &fd_stat); - - return S_ISREG(fd_stat.st_mode); -} - -bool is_regular_file(const char* path) { - struct stat fd_stat; - lstat(path, &fd_stat); - - return S_ISREG(fd_stat.st_mode); -} - -} - -#endif // CHANGE_SRC_IO_H_ diff --git a/src/tracking/change_tracker.cc b/src/tracking/change_tracker.cc new file mode 100644 index 0000000..913604e --- /dev/null +++ b/src/tracking/change_tracker.cc @@ -0,0 +1,92 @@ +#include "change_tracker.h" + +#include +#include + +namespace { + +// constants for increasing pair access readability +constexpr unsigned int EMPLACE_SUCCESS = 1; +constexpr unsigned int FILE_NAME = 0; +constexpr unsigned int DIFF_PROCESS = 1; + +boost::process::context getDefaultContext() { + boost::process::context context; + + context.environment = boost::process::self::get_environment(); + context.stdout_behavior = boost::process::capture_stream(); + context.stdin_behavior = boost::process::capture_stream(); + + return context; +} + +} + +namespace tracking { + +ChangeTracker::ChangeTracker(utility::Logger* logger): + logger_(logger), + children_() { } + +ChangeTracker::~ChangeTracker() { + for ( auto&& tracked : this->children_ ) { + std::get(tracked)->get_stdin().close(); + + this->logger_->forward(std::get(tracked)->get_stdout()); + + tracked.second->wait(); + } +} + +bool ChangeTracker::is_tracked(const std::string& file_path) const { + return this->children_.find(file_path) != this->children_.end(); +} + +// Begins tracking changes to a file reachable by a given path +// +// The actual tracking is performed by a `diff` instance that is +// spawned by this method and managed by this class. +// As `diff` is called as a new subprocess and because there is no +// straight forward way for checking / enforcing if it has already +// completed reading the initial contents of the file the command +// is structured in the following sequence: +// +// diff -p - $file_path +// +// This means that reading the final file contents is delegated to +// `diff` while the initial file contents are read by this method +// and written to `diff`'s standard input. +// +// If the `-` and `$file_path` arguments were exchanged there would +// be no way to: +// - be sure the initial contents are read before the changing +// syscall that triggered this tracking in the first place is +// performed +// - be sure that the initial file contents are read completly +// as `diff` seemingly only reads the first block of the first +// file provided if the second file argument is standard input +// +bool ChangeTracker::track(const std::string& file_path) { + auto result = this->children_.emplace( + file_path, + std::make_unique( + boost::process::launch_shell("diff -p - " + file_path, getDefaultContext()) + ) + ); + + if ( std::get(result) ) { + boost::filesystem::ifstream file( + std::get(*result.first) + ); + + if ( file.is_open() ) { + std::get(*result.first)->get_stdin() << file.rdbuf(); + } + + return true; + } else { + return false; + } +} + +} diff --git a/src/tracking/change_tracker.h b/src/tracking/change_tracker.h new file mode 100644 index 0000000..54af4f7 --- /dev/null +++ b/src/tracking/change_tracker.h @@ -0,0 +1,32 @@ +#ifndef CHANGE_SRC_TRACKING_CHANGE_TRACKER_H_ +#define CHANGE_SRC_TRACKING_CHANGE_TRACKER_H_ + +#include + +#include + +#include "utility/logger.h" + +namespace tracking { + +class ChangeTracker { + public: + ChangeTracker(utility::Logger*); + ~ChangeTracker(); + + bool is_tracked(const std::string&) const; + + bool track(const std::string&); + + private: + utility::Logger* const logger_; + + std::unordered_map< + std::string, std::unique_ptr + > children_; + +}; + +} + +#endif // CHANGE_SRC_TRACKING_CHANGE_TRACKER_H_ diff --git a/src/utility.h b/src/utility.h deleted file mode 100644 index 1dc44ed..0000000 --- a/src/utility.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef CHANGE_SRC_UTILITY_H_ -#define CHANGE_SRC_UTILITY_H_ - -#include - -#include - -#include - -namespace utility { - -class Logger { - public: - Logger(const int target_fd): - buffer_(target_fd, std::ios::out), - stream_(&this->buffer) { } - - void append(const std::string& msg) { - this->stream_ << msg << std::endl; - } - - // Forward the contents of a given standard output stream to the log target - // - // While `this->stream_ << stream.rdbuf()` would be more effective it sadly - // does not work with `boost::process::pistream` due to a broken pipe error - // in conjunction with the required `boost::process::capture_stream` context - // flag. - // - void forward(boost::process::pistream& stream) { - this->stream << std::string( - (std::istreambuf_iterator(stream)), - (std::istreambuf_iterator()) - ); - } - - private: - __gnu_cxx::stdio_filebuf buffer_; - std::ostream stream_; - -}; - -} - -#endif // CHANGE_SRC_UTILITY_H_ diff --git a/src/utility/io.h b/src/utility/io.h new file mode 100644 index 0000000..ed1f542 --- /dev/null +++ b/src/utility/io.h @@ -0,0 +1,68 @@ +#ifndef CHANGE_SRC_UTILITY_IO_H_ +#define CHANGE_SRC_UTILITY_IO_H_ + +#include +#include +#include +#include + +#include + +namespace utility { + +class FileDescriptorGuard { + public: + FileDescriptorGuard(const std::string& path) { + this->fd_ = open(path.c_str(), O_CREAT | O_WRONLY | O_APPEND); + + if ( !this->fd_ ) { + this->fd_ = STDERR_FILENO; + } + } + + ~FileDescriptorGuard() { + close(this->fd_); + } + + operator int() { + return this->fd_; + } + + private: + int fd_; + +}; + +std::string get_file_name(int fd) { + char proc_link[20]; + char file_name[256]; + + snprintf(proc_link, sizeof(proc_link), "/proc/self/fd/%d", fd); + const ssize_t name_size = readlink(proc_link, file_name, sizeof(file_name)); + + if ( name_size > 0 ) { + file_name[name_size] = '\0'; + + return std::string(file_name); + } else { + return std::string(); + } +} + +bool is_regular_file(int fd) { + struct stat fd_stat; + fstat(fd, &fd_stat); + + return S_ISREG(fd_stat.st_mode); +} + +bool is_regular_file(const char* path) { + struct stat fd_stat; + lstat(path, &fd_stat); + + return S_ISREG(fd_stat.st_mode); +} + +} + +#endif // CHANGE_SRC_UTILITY_IO_H_ diff --git a/src/utility/logger.h b/src/utility/logger.h new file mode 100644 index 0000000..475f33d --- /dev/null +++ b/src/utility/logger.h @@ -0,0 +1,44 @@ +#ifndef CHANGE_SRC_LOGGER_H_ +#define CHANGE_SRC_LOGGER_H_ + +#include + +#include + +#include + +namespace utility { + +class Logger { + public: + Logger(const int target_fd): + buffer_(target_fd, std::ios::out), + stream_(&this->buffer_) { } + + void append(const std::string& msg) { + this->stream_ << msg << std::endl; + } + + // Forward the contents of a given standard output stream to the log target + // + // While `this->stream_ << stream.rdbuf()` would be more effective it sadly + // does not work with `boost::process::pistream` due to a broken pipe error + // in conjunction with the required `boost::process::capture_stream` context + // flag. + // + void forward(boost::process::pistream& stream) { + this->stream_ << std::string( + (std::istreambuf_iterator(stream)), + (std::istreambuf_iterator()) + ); + } + + private: + __gnu_cxx::stdio_filebuf buffer_; + std::ostream stream_; + +}; + +} + +#endif // CHANGE_SRC_LOGGER_H_ -- cgit v1.2.3