diff --git a/src/utils/shared_files.cc b/src/utils/shared_files.cc index 73216bd0..df18022f 100644 --- a/src/utils/shared_files.cc +++ b/src/utils/shared_files.cc @@ -15,236 +15,103 @@ #include "src/utils/shared_files.h" -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#ifdef WIN32 +#include +#include +#endif -#include -#include -#include namespace modsecurity { namespace utils { -std::pair SharedFiles::find_handler( - const std::string &fileName) { - for (const auto &i : m_handlers) { - if (i.first == fileName) { - return i.second; - } - } - return std::pair(NULL, NULL); -} - - -std::pair SharedFiles::add_new_handler( +SharedFiles::handlers_map::iterator SharedFiles::add_new_handler( const std::string &fileName, std::string *error) { - int shm_id; - int ret; - key_t mem_key_structure; - msc_file_handler_t *new_debug_log = NULL; - struct shmid_ds shared_mem_info; - FILE *fp; - bool toBeCreated = true; - - fp = fopen(fileName.c_str(), "a"); + FILE *fp = fopen(fileName.c_str(), "a"); if (fp == 0) { error->assign("Failed to open file: " + fileName); - goto err_fh; + return m_handlers.end(); } - mem_key_structure = ftok(fileName.c_str(), 1); - if (mem_key_structure < 0) { - error->assign("Failed to select key for the shared memory (1): "); - error->append(strerror(errno)); - goto err_mem_key; - } - - shm_id = shmget(mem_key_structure, sizeof (msc_file_handler_t) \ - + fileName.size() + 1, IPC_CREAT | IPC_EXCL | 0666); - if (shm_id < 0) { - shm_id = shmget(mem_key_structure, sizeof (msc_file_handler_t) - + fileName.size() + 1, IPC_CREAT | 0666); - toBeCreated = false; - if (shm_id < 0) { - error->assign("Failed to allocate shared memory (1): "); - error->append(strerror(errno)); - goto err_shmget1; - } - } - - ret = shmctl(shm_id, IPC_STAT, &shared_mem_info); - if (ret < 0) { - error->assign("Failed to get information on shared memory (1): "); - error->append(strerror(errno)); - goto err_shmctl1; - } - - new_debug_log = reinterpret_cast( - shmat(shm_id, NULL, 0)); - if ((reinterpret_cast(new_debug_log)[0]) == -1) { - error->assign("Failed to attach shared memory (1): "); - error->append(strerror(errno)); - goto err_shmat1; - } - - if (toBeCreated == false && shared_mem_info.shm_nattch == 0) { - toBeCreated = true; - } - - if (toBeCreated) { - memset(new_debug_log, '\0', sizeof(msc_file_handler_t)); - new_debug_log->shm_id_structure = shm_id; - memcpy(new_debug_log->file_name, fileName.c_str(), fileName.size()); - new_debug_log->file_name[fileName.size()] = '\0'; - } - m_handlers.push_back(std::make_pair(fileName, - std::make_pair(new_debug_log, fp))); - - return std::make_pair(new_debug_log, fp); -err_shmat1: - shmdt(new_debug_log); -err_shmctl1: -err_shmget1: -err_mem_key: - fclose(fp); -err_fh: - return std::pair(NULL, NULL); + return m_handlers.insert({ fileName, {fp, 0} }).first; } bool SharedFiles::open(const std::string& fileName, std::string *error) { - std::pair a; - bool ret = true; - - #if MODSEC_USE_GENERAL_LOCK - pthread_mutex_lock(m_generalLock); -#endif - - a = find_handler(fileName); - if (a.first == NULL) { - a = add_new_handler(fileName, error); - if (error->size() > 0) { - ret = false; - goto out; - } + auto it = m_handlers.find(fileName); + if (it == m_handlers.end()) { + it = add_new_handler(fileName, error); + if (error->size() > 0) + return false; } - if (a.first == NULL) { + + if (it == m_handlers.end()) { error->assign("Not able to open: " + fileName); - ret = false; - goto out; + return false; } -out: -#if MODSEC_USE_GENERAL_LOCK - pthread_mutex_unlock(m_generalLock); -#endif + it->second.cnt++; - return ret; + return true; } void SharedFiles::close(const std::string& fileName) { - std::pair a; - /* int ret; */ - /* int shm_id; */ - /* struct shmid_ds shared_mem_info; */ - /* int j = 0; */ + if (fileName.empty()) + return; -#if MODSEC_USE_GENERAL_LOCK - pthread_mutex_lock(m_generalLock); -#endif + auto it = m_handlers.find(fileName); + if (it == m_handlers.end()) + return; - if (fileName.empty()) { - goto out; + it->second.cnt--; + if (it->second.cnt == 0) + { + fclose(it->second.fp); + + m_handlers.erase(it); } - - a = find_handler(fileName); - if (a.first == NULL || a.second == NULL) { - goto out; - } - - /* fclose(a.second); */ - a.second = 0; - - /* - * Delete the file structure will be welcomed, but we cannot delay - * while the process is being killed. - * - for (std::pair> i : m_handlers) { - if (i.first == fileName) { - j++; - } - } - - m_handlers.erase(m_handlers.begin()+j); - */ - - /* hmdt(a.second); */ - shmctl(a.first->shm_id_structure, IPC_RMID, NULL); - - /* - * - * We could check to see how many process attached to the shared memory - * we have, prior to the deletion of the shared memory. - * - ret = shmctl(a.first->shm_id_structure, IPC_STAT, &shared_mem_info); - if (ret < 0) { - goto out; - } - ret = shared_mem_info.shm_nattch; - shm_id = a.first->shm_id_structure; - */ - -out: -#if MODSEC_USE_GENERAL_LOCK - pthread_mutex_unlock(m_generalLock); -#endif - return; } bool SharedFiles::write(const std::string& fileName, const std::string &msg, std::string *error) { - std::pair a; - std::string lmsg = msg; - size_t wrote; - struct flock lock{}; bool ret = true; - a = find_handler(fileName); - if (a.first == NULL) { + auto it = m_handlers.find(fileName); + if (it == m_handlers.end()) { error->assign("file is not open: " + fileName); return false; } //Exclusively lock whole file +#ifndef WIN32 + struct flock lock {}; lock.l_start = lock.l_len = lock.l_whence = 0; lock.l_type = F_WRLCK; - fcntl(fileno(a.second), F_SETLKW, &lock); + fcntl(fileno(it->second.fp), F_SETLKW, &lock); +#else + auto handle = reinterpret_cast(_get_osfhandle(fileno(it->second.fp))); + OVERLAPPED overlapped = { 0 }; + ::LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped); +#endif - wrote = fwrite(lmsg.c_str(), 1, lmsg.size(), a.second); + auto wrote = fwrite(msg.c_str(), 1, msg.size(), it->second.fp); if (wrote < msg.size()) { error->assign("failed to write: " + fileName); ret = false; } - fflush(a.second); + fflush(it->second.fp); //Remove exclusive lock +#ifndef WIN32 lock.l_type = F_UNLCK; - fcntl(fileno(a.second), F_SETLKW, &lock); + fcntl(fileno(it->second.fp), F_SETLKW, &lock); +#else + overlapped = { 0 }; + ::UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped); +#endif return ret; } diff --git a/src/utils/shared_files.h b/src/utils/shared_files.h index d0d8ef99..4953eeff 100644 --- a/src/utils/shared_files.h +++ b/src/utils/shared_files.h @@ -17,45 +17,18 @@ #define SRC_UTILS_SHARED_FILES_H_ -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include "modsecurity/transaction.h" -#include "modsecurity/audit_log.h" - -/** - * Not using this critical section yet. - * - */ -/* #define MODSEC_USE_GENERAL_LOCK */ - namespace modsecurity { namespace utils { -typedef struct msc_file_handler { - int shm_id_structure; - char file_name[]; -} msc_file_handler_t; - - class SharedFiles { - public: +public: bool open(const std::string& fileName, std::string *error); void close(const std::string& fileName); bool write(const std::string& fileName, const std::string &msg, @@ -66,86 +39,28 @@ class SharedFiles { return instance; } - protected: - std::pair find_handler( - const std::string &fileName); - std::pair add_new_handler( - const std::string &fileName, std::string *error); - - private: - SharedFiles() -#ifdef MODSEC_USE_GENERAL_LOCK - : m_generalLock(NULL), - m_memKeyStructure(0) -#endif - { -#ifdef MODSEC_USE_GENERAL_LOCK - int shm_id; - bool toBeCreated(false); - bool err = false; - - m_memKeyStructure = ftok(".", 1); // cppcheck-suppress useInitializationList - if (m_memKeyStructure < 0) { - err = true; - goto err_mem_key; - } - - shm_id = shmget(m_memKeyStructure, sizeof(pthread_mutex_t), - IPC_CREAT | IPC_EXCL | 0666); - if (shm_id < 0) { - shm_id = shmget(m_memKeyStructure, sizeof(pthread_mutex_t), - IPC_CREAT | 0666); - toBeCreated = false; - if (shm_id < 0) { - err = true; - goto err_shmget1; - } - } - - m_generalLock = reinterpret_cast( - shmat(shm_id, NULL, 0)); - if ((reinterpret_cast(m_generalLock)[0]) == -1) { - err = true; - goto err_shmat1; - } - - if (toBeCreated) { - memset(m_generalLock, '\0', sizeof(pthread_mutex_t)); - pthread_mutex_init(m_generalLock, NULL); - pthread_mutex_unlock(m_generalLock); - } - - if (err) { -err_mem_key: - std::cerr << strerror(errno) << std::endl; -err_shmget1: - std::cerr << "err_shmget1" << std::endl; -err_shmat1: - std::cerr << "err_shmat1" << std::endl; - } -#endif - } - ~SharedFiles() { -#if MODSEC_USE_GENERAL_LOCK - shmdt(m_generalLock); - shmctl(m_memKeyStructure, IPC_RMID, NULL); -#endif - } +private: + SharedFiles() = default; + ~SharedFiles() = default; // C++ 03 // ======== // Dont forget to declare these two. You want to make sure they // are unacceptable otherwise you may accidentally get copies of // your singleton appearing. - SharedFiles(SharedFiles const&); - void operator=(SharedFiles const&); + SharedFiles(SharedFiles const&) = delete; + void operator=(SharedFiles const&) = delete; - std::vector>> m_handlers; -#if MODSEC_USE_GENERAL_LOCK - pthread_mutex_t *m_generalLock; - key_t m_memKeyStructure; -#endif + struct handler_info { + FILE* fp; + unsigned int cnt; + }; + + using handlers_map = std::unordered_map; + handlers_map m_handlers; + + handlers_map::iterator add_new_handler( + const std::string &fileName, std::string *error); };