#include "develhook.h" #include "util/logging.h" #include "util/detour.h" #include "avs/core.h" #include #include #include namespace hooks::devel::avs_fs { static constexpr char needle_[] = ""; // set to "" to print all static avs::core::AVS_FS_LSTAT_T avs_fs_lstat_; static avs::core::AVS_FS_MOUNT_T avs_fs_mount_; static avs::core::AVS_FS_OPEN_T avs_fs_open_; int on_avs_fs_lstat(const char *path, struct avs::core::avs_stat *stat) { if (strstr(path, needle_)) { log_info("hooks::devel", "{}({})", __FUNCTION__, path); } return avs_fs_lstat_(path, stat); } avs::core::avs_file_t on_avs_fs_mount(const char *mountpoint, const char *fsroot, const char *fstype, void *data) { if (strstr(fsroot, needle_)) { log_info("hooks::devel", "{}({}=>{}) @{} :nullptr data?{} ", __FUNCTION__, fsroot, mountpoint, fstype, data == nullptr); } return avs_fs_mount_(mountpoint, fsroot, fstype, data); } avs::core::avs_file_t on_avs_fs_open(const char *name, uint16_t mode, int flags) { if (strstr(name, needle_)) { log_info("hooks::devel", "{}({}::{}) @{}", __FUNCTION__, name, mode, flags); } return avs_fs_open_(name, mode, flags); } void run() { detour::trampoline(reinterpret_cast(avs::core::avs_fs_lstat), reinterpret_cast(on_avs_fs_lstat), reinterpret_cast(&avs_fs_lstat_)); detour::trampoline(reinterpret_cast(avs::core::avs_fs_mount), reinterpret_cast(on_avs_fs_mount), reinterpret_cast(&avs_fs_mount_)); detour::trampoline(reinterpret_cast(avs::core::avs_fs_open), reinterpret_cast(on_avs_fs_open), reinterpret_cast(&avs_fs_open_)); } } namespace hooks::devel { void (*routine_cb_[devel_routine_last])() ={ [avs_fs_detour] = avs_fs::run }; static constexpr unsigned int by_str(const char *str, int h = 0) { return !str[h] ? 5381 : (by_str(str, h + 1) * 33) ^ str[h]; } std::vector from_env(const char *str) { std::vector r; std::stringstream ss(getenv(str) ? getenv(str) : ""); std::string flag; while (std::getline(ss, flag, ';')) { r.push_back(flag); } return r; } static devel_routine_t routines() { static devel_routine_t routines_ = -1; if (routines_ == static_cast(-1)) { routines_ = 0; for (const auto &routine: from_env("SPICE_DEVEL")) { switch (by_str(routine.c_str())) { case by_str("avs_fs_detour"): routines_ |= 1 << avs_fs_detour; break; case by_str("sndb_test"): routines_ |= 1 << sndb_test; break; default: break; } } } return routines_; } bool active_routine(hooks::devel::devel_routine_t val) { return routines() & (1 << val); } void bind_routine(devel_routine_t val, void (*cb)()) { routine_cb_[val] = cb; } void entry_main() { if (routines()) log_info("hooks::devel", "Processing subroutines.."); for (devel_routine_t i = 0; i < devel_routine_last; i++) { if (active_routine(i) && routine_cb_[i]) routine_cb_[i](); } } }