|
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