|
15 | 15 |
|
16 | 16 | #include "src/utils/shared_files.h"
|
17 | 17 |
|
18 |
| -#include <errno.h> |
19 | 18 | #include <fcntl.h>
|
20 |
| -#include <pthread.h> |
21 |
| -#include <stdio.h> |
22 |
| -#include <sys/ipc.h> |
23 |
| -#include <sys/shm.h> |
24 |
| -#include <sys/stat.h> |
25 |
| -#include <sys/types.h> |
26 |
| -#include <unistd.h> |
27 |
| -#include <stdlib.h> |
28 |
| -#include <string.h> |
29 |
| - |
30 |
| -#include <utility> |
31 |
| -#include <fstream> |
32 |
| -#include <string> |
| 19 | +#ifdef WIN32 |
| 20 | +#include <windows.h> |
| 21 | +#include <io.h> |
| 22 | +#endif |
| 23 | + |
33 | 24 |
|
34 | 25 | namespace modsecurity {
|
35 | 26 | namespace utils {
|
36 | 27 |
|
37 | 28 |
|
38 |
| -std::pair<msc_file_handler *, FILE *> SharedFiles::find_handler( |
39 |
| - const std::string &fileName) { |
40 |
| - for (const auto &i : m_handlers) { |
41 |
| - if (i.first == fileName) { |
42 |
| - return i.second; |
43 |
| - } |
44 |
| - } |
45 |
| - return std::pair<modsecurity::utils::msc_file_handler *, |
46 |
| - FILE *>(NULL, NULL); |
47 |
| -} |
48 |
| - |
49 |
| - |
50 |
| -std::pair<msc_file_handler *, FILE *> SharedFiles::add_new_handler( |
| 29 | +SharedFiles::handlers_map::iterator SharedFiles::add_new_handler( |
51 | 30 | const std::string &fileName, std::string *error) {
|
52 |
| - int shm_id; |
53 |
| - int ret; |
54 |
| - key_t mem_key_structure; |
55 |
| - msc_file_handler_t *new_debug_log = NULL; |
56 |
| - struct shmid_ds shared_mem_info; |
57 |
| - FILE *fp; |
58 |
| - bool toBeCreated = true; |
59 |
| - |
60 |
| - fp = fopen(fileName.c_str(), "a"); |
| 31 | + FILE *fp = fopen(fileName.c_str(), "a"); |
61 | 32 | if (fp == 0) {
|
62 | 33 | error->assign("Failed to open file: " + fileName);
|
63 |
| - goto err_fh; |
64 |
| - } |
65 |
| - |
66 |
| - mem_key_structure = ftok(fileName.c_str(), 1); |
67 |
| - if (mem_key_structure < 0) { |
68 |
| - error->assign("Failed to select key for the shared memory (1): "); |
69 |
| - error->append(strerror(errno)); |
70 |
| - goto err_mem_key; |
71 |
| - } |
72 |
| - |
73 |
| - shm_id = shmget(mem_key_structure, sizeof (msc_file_handler_t) \ |
74 |
| - + fileName.size() + 1, IPC_CREAT | IPC_EXCL | 0666); |
75 |
| - if (shm_id < 0) { |
76 |
| - shm_id = shmget(mem_key_structure, sizeof (msc_file_handler_t) |
77 |
| - + fileName.size() + 1, IPC_CREAT | 0666); |
78 |
| - toBeCreated = false; |
79 |
| - if (shm_id < 0) { |
80 |
| - error->assign("Failed to allocate shared memory (1): "); |
81 |
| - error->append(strerror(errno)); |
82 |
| - goto err_shmget1; |
83 |
| - } |
| 34 | + return m_handlers.end(); |
84 | 35 | }
|
85 | 36 |
|
86 |
| - ret = shmctl(shm_id, IPC_STAT, &shared_mem_info); |
87 |
| - if (ret < 0) { |
88 |
| - error->assign("Failed to get information on shared memory (1): "); |
89 |
| - error->append(strerror(errno)); |
90 |
| - goto err_shmctl1; |
91 |
| - } |
92 |
| - |
93 |
| - new_debug_log = reinterpret_cast<msc_file_handler_t *>( |
94 |
| - shmat(shm_id, NULL, 0)); |
95 |
| - if ((reinterpret_cast<char *>(new_debug_log)[0]) == -1) { |
96 |
| - error->assign("Failed to attach shared memory (1): "); |
97 |
| - error->append(strerror(errno)); |
98 |
| - goto err_shmat1; |
99 |
| - } |
100 |
| - |
101 |
| - if (toBeCreated == false && shared_mem_info.shm_nattch == 0) { |
102 |
| - toBeCreated = true; |
103 |
| - } |
104 |
| - |
105 |
| - if (toBeCreated) { |
106 |
| - memset(new_debug_log, '\0', sizeof(msc_file_handler_t)); |
107 |
| - new_debug_log->shm_id_structure = shm_id; |
108 |
| - memcpy(new_debug_log->file_name, fileName.c_str(), fileName.size()); |
109 |
| - new_debug_log->file_name[fileName.size()] = '\0'; |
110 |
| - } |
111 |
| - m_handlers.push_back(std::make_pair(fileName, |
112 |
| - std::make_pair(new_debug_log, fp))); |
113 |
| - |
114 |
| - return std::make_pair(new_debug_log, fp); |
115 |
| -err_shmat1: |
116 |
| - shmdt(new_debug_log); |
117 |
| -err_shmctl1: |
118 |
| -err_shmget1: |
119 |
| -err_mem_key: |
120 |
| - fclose(fp); |
121 |
| -err_fh: |
122 |
| - return std::pair<modsecurity::utils::msc_file_handler *, |
123 |
| - FILE *>(NULL, NULL); |
| 37 | + return m_handlers.insert({ fileName, {fp, 0} }).first; |
124 | 38 | }
|
125 | 39 |
|
126 | 40 |
|
127 | 41 | bool SharedFiles::open(const std::string& fileName, std::string *error) {
|
128 |
| - std::pair<msc_file_handler *, FILE *> a; |
129 |
| - bool ret = true; |
130 |
| - |
131 |
| - #if MODSEC_USE_GENERAL_LOCK |
132 |
| - pthread_mutex_lock(m_generalLock); |
133 |
| -#endif |
134 |
| - |
135 |
| - a = find_handler(fileName); |
136 |
| - if (a.first == NULL) { |
137 |
| - a = add_new_handler(fileName, error); |
138 |
| - if (error->size() > 0) { |
139 |
| - ret = false; |
140 |
| - goto out; |
141 |
| - } |
| 42 | + auto it = m_handlers.find(fileName); |
| 43 | + if (it == m_handlers.end()) { |
| 44 | + it = add_new_handler(fileName, error); |
| 45 | + if (error->size() > 0) |
| 46 | + return false; |
142 | 47 | }
|
143 |
| - if (a.first == NULL) { |
| 48 | + |
| 49 | + if (it == m_handlers.end()) { |
144 | 50 | error->assign("Not able to open: " + fileName);
|
145 |
| - ret = false; |
146 |
| - goto out; |
| 51 | + return false; |
147 | 52 | }
|
148 | 53 |
|
149 |
| -out: |
150 |
| -#if MODSEC_USE_GENERAL_LOCK |
151 |
| - pthread_mutex_unlock(m_generalLock); |
152 |
| -#endif |
| 54 | + it->second.cnt++; |
153 | 55 |
|
154 |
| - return ret; |
| 56 | + return true; |
155 | 57 | }
|
156 | 58 |
|
157 | 59 |
|
158 | 60 | void SharedFiles::close(const std::string& fileName) {
|
159 |
| - std::pair<msc_file_handler *, FILE *> a; |
160 |
| - /* int ret; */ |
161 |
| - /* int shm_id; */ |
162 |
| - /* struct shmid_ds shared_mem_info; */ |
163 |
| - /* int j = 0; */ |
164 |
| - |
165 |
| -#if MODSEC_USE_GENERAL_LOCK |
166 |
| - pthread_mutex_lock(m_generalLock); |
167 |
| -#endif |
168 |
| - |
169 |
| - if (fileName.empty()) { |
170 |
| - goto out; |
171 |
| - } |
172 |
| - |
173 |
| - a = find_handler(fileName); |
174 |
| - if (a.first == NULL || a.second == NULL) { |
175 |
| - goto out; |
176 |
| - } |
177 |
| - |
178 |
| - /* fclose(a.second); */ |
179 |
| - a.second = 0; |
180 |
| - |
181 |
| - /* |
182 |
| - * Delete the file structure will be welcomed, but we cannot delay |
183 |
| - * while the process is being killed. |
184 |
| - * |
185 |
| - for (std::pair<std::string, |
186 |
| - std::pair<msc_file_handler *, FILE *>> i : m_handlers) { |
187 |
| - if (i.first == fileName) { |
188 |
| - j++; |
189 |
| - } |
190 |
| - } |
| 61 | + if (fileName.empty()) |
| 62 | + return; |
191 | 63 |
|
192 |
| - m_handlers.erase(m_handlers.begin()+j); |
193 |
| - */ |
| 64 | + auto it = m_handlers.find(fileName); |
| 65 | + if (it == m_handlers.end()) |
| 66 | + return; |
194 | 67 |
|
195 |
| - /* hmdt(a.second); */ |
196 |
| - shmctl(a.first->shm_id_structure, IPC_RMID, NULL); |
| 68 | + it->second.cnt--; |
| 69 | + if (it->second.cnt == 0) |
| 70 | + { |
| 71 | + fclose(it->second.fp); |
197 | 72 |
|
198 |
| - /* |
199 |
| - * |
200 |
| - * We could check to see how many process attached to the shared memory |
201 |
| - * we have, prior to the deletion of the shared memory. |
202 |
| - * |
203 |
| - ret = shmctl(a.first->shm_id_structure, IPC_STAT, &shared_mem_info); |
204 |
| - if (ret < 0) { |
205 |
| - goto out; |
| 73 | + m_handlers.erase(it); |
206 | 74 | }
|
207 |
| - ret = shared_mem_info.shm_nattch; |
208 |
| - shm_id = a.first->shm_id_structure; |
209 |
| - */ |
210 |
| - |
211 |
| -out: |
212 |
| -#if MODSEC_USE_GENERAL_LOCK |
213 |
| - pthread_mutex_unlock(m_generalLock); |
214 |
| -#endif |
215 |
| - return; |
216 | 75 | }
|
217 | 76 |
|
218 | 77 |
|
219 | 78 | bool SharedFiles::write(const std::string& fileName,
|
220 | 79 | const std::string &msg, std::string *error) {
|
221 |
| - std::pair<msc_file_handler *, FILE *> a; |
222 |
| - std::string lmsg = msg; |
223 |
| - size_t wrote; |
224 |
| - struct flock lock{}; |
225 | 80 | bool ret = true;
|
226 | 81 |
|
227 |
| - a = find_handler(fileName); |
228 |
| - if (a.first == NULL) { |
| 82 | + auto it = m_handlers.find(fileName); |
| 83 | + if (it == m_handlers.end()) { |
229 | 84 | error->assign("file is not open: " + fileName);
|
230 | 85 | return false;
|
231 | 86 | }
|
232 | 87 |
|
233 | 88 | //Exclusively lock whole file
|
| 89 | +#ifndef WIN32 |
| 90 | + struct flock lock {}; |
234 | 91 | lock.l_start = lock.l_len = lock.l_whence = 0;
|
235 | 92 | lock.l_type = F_WRLCK;
|
236 |
| - fcntl(fileno(a.second), F_SETLKW, &lock); |
| 93 | + fcntl(fileno(it->second.fp), F_SETLKW, &lock); |
| 94 | +#else |
| 95 | + auto handle = reinterpret_cast<HANDLE>(_get_osfhandle(fileno(it->second.fp))); |
| 96 | + OVERLAPPED overlapped = { 0 }; |
| 97 | + ::LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped); |
| 98 | +#endif |
237 | 99 |
|
238 |
| - wrote = fwrite(lmsg.c_str(), 1, lmsg.size(), a.second); |
| 100 | + auto wrote = fwrite(msg.c_str(), 1, msg.size(), it->second.fp); |
239 | 101 | if (wrote < msg.size()) {
|
240 | 102 | error->assign("failed to write: " + fileName);
|
241 | 103 | ret = false;
|
242 | 104 | }
|
243 |
| - fflush(a.second); |
| 105 | + fflush(it->second.fp); |
244 | 106 |
|
245 | 107 | //Remove exclusive lock
|
| 108 | +#ifndef WIN32 |
246 | 109 | lock.l_type = F_UNLCK;
|
247 |
| - fcntl(fileno(a.second), F_SETLKW, &lock); |
| 110 | + fcntl(fileno(it->second.fp), F_SETLKW, &lock); |
| 111 | +#else |
| 112 | + overlapped = { 0 }; |
| 113 | + ::UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped); |
| 114 | +#endif |
248 | 115 |
|
249 | 116 | return ret;
|
250 | 117 | }
|
|
0 commit comments