// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "iosyscalls-internal.hpp" #include #include #include #include #include #include #include #include #include #include namespace { constexpr auto ENV_NAME = "IOSYSCALLS_REDIRECT_TO_IMAGE"; constexpr auto FIRST_FILEDESC = 64'566'756; constexpr auto SYSROOT = "sysroot"; constexpr auto SYSTEM_PARTITION = "system_a"; constexpr auto SYSTEM_DATA_DIR = "data"; bool g_evaluated = false; bool g_redirect = false; constexpr auto LINUX_PATHS = { "/dev/", "/etc/", "/lib", "/usr/share", "/run/user", "/home", "/proc", "/tmp", "MuditaOS.log"}; constexpr auto IMAGE_PATHS = {"/system", "/mfgconf", "/user"}; pthread_mutex_t g_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; phmap::flat_hash_set g_fdlist; phmap::flat_hash_set g_dirlist; std::string imageFileName; std::string sysroot = SYSROOT; } // namespace namespace vfsn::linux::internal { void set_sysroot(const char *newSysroot) { sysroot = newSysroot; } void set_image_path(const char *newImageName) { imageFileName = std::string(newImageName); } bool redirect_to_image() { if (!g_evaluated) { const auto env = std::getenv(ENV_NAME); g_redirect = env && !std::strcmp(env, "1"); g_evaluated = true; } return g_redirect; } bool redirect_to_image(const char *inpath) { if (!redirect_to_image()) { return false; } if (std::strstr(inpath, imageFileName.c_str()) == inpath) { return false; } for (const auto &path : LINUX_PATHS) { if (std::strstr(inpath, path) == inpath) { return false; } } return true; } const char *npath_translate(const char *inpath, char *buffer) { const auto inputPath = std::string(inpath); for (const auto &path : IMAGE_PATHS) { if (std::strstr(inpath, path) == inpath) { std::string outpath = sysroot; const auto pathLength = std::strlen(path); if (std::strcmp(path, "/mfgconf") == 0) { outpath += "/"; outpath += SYSTEM_PARTITION; outpath += "/"; outpath += SYSTEM_DATA_DIR; outpath += inputPath.substr(pathLength); } else if (std::strcmp(path, "/system") == 0) { outpath += "/"; outpath += SYSTEM_PARTITION; outpath += inputPath.substr(pathLength); } else if (*inpath == '/') { outpath += inputPath; } assert(outpath.size() < PATH_MAX); std::copy_n(std::begin(outpath), outpath.size(), buffer); buffer[outpath.size()] = '\0'; return buffer; } } return inpath; } bool is_image_handle(const FILE *fil) { return false; } int to_native_fd(int fd) { return FIRST_FILEDESC + fd; } int to_image_fd(int fd) { return fd - FIRST_FILEDESC; } bool is_image_fd(int fd) { return fd >= FIRST_FILEDESC; } FILEX *allocate_filex(int fd) { auto ret = new FILEX; ret->fd = fd; pthread_mutex_lock(&g_lock); g_fdlist.emplace(ret); pthread_mutex_unlock(&g_lock); return ret; } void add_DIR_to_image_list(DIR *indir) { pthread_mutex_lock(&g_lock); g_dirlist.emplace(indir); pthread_mutex_unlock(&g_lock); } void remove_DIR_from_image_list(DIR *indir) { pthread_mutex_lock(&g_lock); auto fres = g_dirlist.find(indir); if (fres != g_dirlist.end()) { g_dirlist.erase(fres); } pthread_mutex_unlock(&g_lock); } bool is_image_DIR(DIR *indir) { if (indir == nullptr) { return false; } pthread_mutex_lock(&g_lock); auto fres = g_dirlist.find(indir); auto isntdir = (fres != g_dirlist.end()); pthread_mutex_unlock(&g_lock); return isntdir; } bool is_filex(const void *fd) { if (fd == nullptr) { return false; } pthread_mutex_lock(&g_lock); auto fres = g_fdlist.find(reinterpret_cast(fd)); auto isfilex = (fres != g_fdlist.end()); pthread_mutex_unlock(&g_lock); return isfilex; } void remove_filex(FILEX *fil) { pthread_mutex_lock(&g_lock); auto fres = g_fdlist.find(fil); if (fres != g_fdlist.end()) { g_fdlist.erase(fres); delete fil; } pthread_mutex_unlock(&g_lock); } void debug_trace_syscall(const char *fn, const char *format, ...) { auto rvprint = reinterpret_cast(dlsym(RTLD_NEXT, "vfprintf")); auto rprint = reinterpret_cast(dlsym(RTLD_NEXT, "fprintf")); rprint(stderr, ">>>>>>> IOFUNC: [%s] ", fn); va_list args; va_start(args, format); rvprint(stderr, format, args); va_end(args); rprint(stderr, " >>>>>>>>>>>\n"); } } // namespace vfsn::linux::internal