1 #include <iostream>
2 #include <fstream>
3 #include <iomanip>
4 #include <cstdint>
5 #include <string>
6 #include <sys/types.h>
7 #include <dirent.h>
8 #include <sstream>
9 #include <sys/stat.h>
10 #include <cstring>
11 #include "message.hpp"
12 #include <time.h>
13 #include <stddef.h>
14 #include <cstdio>
15 #include <syslog.h>
16
17 const uint32_t g_eyecatcher = 0x4F424D43; // OBMC
18 const uint16_t g_version = 1;
19
20 struct logheader_t {
21 uint32_t eyecatcher;
22 uint16_t version;
23 uint16_t logid;
24 time_t timestamp;
25 uint16_t detailsoffset;
26 uint16_t messagelen;
27 uint16_t severitylen;
28 uint16_t associationlen;
29 uint16_t reportedbylen;
30 uint16_t debugdatalen;
31 };
32
33 size_t get_file_size(string fn);
34
35
event_manager(string path,size_t reqmaxsize,uint16_t reqmaxlogs)36 event_manager::event_manager(string path, size_t reqmaxsize, uint16_t reqmaxlogs)
37 {
38 uint16_t x;
39 eventpath = path;
40 latestid = 0;
41 dirp = NULL;
42 logcount = 0;
43 maxsize = -1;
44 maxlogs = -1;
45 currentsize = get_managed_size();
46
47 if (reqmaxsize)
48 maxsize = reqmaxsize;
49
50 if (reqmaxlogs)
51 maxlogs = reqmaxlogs;
52
53 // examine the files being managed and advance latestid to that value
54 while ( (x = next_log()) ) {
55 logcount++;
56 if ( x > latestid )
57 latestid = x;
58 }
59
60 return;
61 }
62
~event_manager()63 event_manager::~event_manager()
64 {
65 if (dirp)
66 closedir(dirp);
67
68 return;
69 }
70
71
is_logid_a_log(uint16_t logid)72 bool event_manager::is_logid_a_log(uint16_t logid)
73 {
74 std::ostringstream buffer;
75 buffer << int(logid);
76 return is_file_a_log(buffer.str());
77 }
78
79
is_file_a_log(string str)80 bool event_manager::is_file_a_log(string str)
81 {
82 std::ostringstream buffer;
83 ifstream f;
84 logheader_t hdr;
85
86 if (!str.compare("."))
87 return 0;
88
89 if (!str.compare(".."))
90 return 0;
91
92 buffer << eventpath << "/" << str;
93
94 f.open( buffer.str(), ios::binary);
95
96 if (!f.good()) {
97 f.close();
98 return 0;
99 }
100
101 f.read((char*)&hdr, sizeof(hdr));
102 f.close();
103
104 if (hdr.eyecatcher != g_eyecatcher)
105 return 0;
106
107 return 1;
108 }
109
log_count(void)110 uint16_t event_manager::log_count(void)
111 {
112 return logcount;
113 }
latest_log_id(void)114 uint16_t event_manager::latest_log_id(void)
115 {
116 return latestid;
117 }
new_log_id(void)118 uint16_t event_manager::new_log_id(void)
119 {
120 return ++latestid;
121 }
next_log_refresh(void)122 void event_manager::next_log_refresh(void)
123 {
124 if (dirp) {
125 closedir(dirp);
126 dirp = NULL;
127 }
128
129 return;
130 }
131
next_log(void)132 uint16_t event_manager::next_log(void)
133 {
134 std::ostringstream buffer;
135 struct dirent *ent;
136 uint16_t id;
137
138 if (dirp == NULL)
139 dirp = opendir(eventpath.c_str());
140
141 if (dirp) {
142 do {
143 ent = readdir(dirp);
144
145 if (ent == NULL)
146 break;
147
148 string str(ent->d_name);
149
150 if (is_file_a_log(str)) {
151 id = (uint16_t) atoi(str.c_str());
152 break;
153 }
154
155 } while( 1 );
156 } else {
157 cerr << "Error opening directory " << eventpath << endl;
158 ent = NULL;
159 id = 0;
160 }
161
162 if (ent == NULL) {
163 closedir(dirp);
164 dirp = NULL;
165 }
166
167 return ((ent == NULL) ? 0 : id);
168 }
169
170
create(event_record_t * rec)171 uint16_t event_manager::create(event_record_t *rec)
172 {
173 rec->logid = new_log_id();
174 rec->timestamp = time(NULL);
175
176 return create_log_event(rec);
177 }
178
getlen(const char * s)179 inline uint16_t getlen(const char *s)
180 {
181 return (uint16_t) (1 + strlen(s));
182 }
183
184
185 /* If everything is working correctly, return file size, */
186 /* Otherwise return 0 */
get_file_size(string fn)187 size_t get_file_size(string fn)
188 {
189 struct stat f_stat;
190 int r = -1;
191
192 r = stat(fn.c_str(), &f_stat);
193
194 if (r < 0) {
195 fprintf(stderr, "Error get_file_size() for %s, %s\n",
196 fn.c_str(),
197 strerror(errno));
198 return 0;
199 }
200
201 return (f_stat.st_size);
202 }
203
204
get_managed_size(void)205 size_t event_manager::get_managed_size(void)
206 {
207 DIR *dirp;
208 std::ostringstream buffer;
209 struct dirent *ent;
210 ifstream f;
211
212 size_t db_size = 0;
213
214 dirp = opendir(eventpath.c_str());
215
216 if (dirp) {
217 while ( (ent = readdir(dirp)) != NULL ) {
218
219 string str(ent->d_name);
220
221 if (is_file_a_log(str)) {
222 buffer.str("");
223 buffer << eventpath << "/" << str.c_str();
224 db_size += get_file_size(buffer.str());
225 }
226 }
227 }
228
229 closedir(dirp);
230
231 return (db_size);
232 }
233
create_log_event(event_record_t * rec)234 uint16_t event_manager::create_log_event(event_record_t *rec)
235 {
236 std::ostringstream buffer;
237 ofstream myfile;
238 logheader_t hdr = {0};
239 size_t event_size=0;
240
241 buffer << eventpath << "/" << int(rec->logid) ;
242
243 hdr.eyecatcher = g_eyecatcher;
244 hdr.version = g_version;
245 hdr.logid = rec->logid;
246 hdr.timestamp = rec->timestamp;
247 hdr.detailsoffset = offsetof(logheader_t, messagelen);
248 hdr.messagelen = getlen(rec->message);
249 hdr.severitylen = getlen(rec->severity);
250 hdr.associationlen = getlen(rec->association);
251 hdr.reportedbylen = getlen(rec->reportedby);
252 hdr.debugdatalen = rec->n;
253
254 event_size = sizeof(logheader_t) + \
255 hdr.messagelen + \
256 hdr.severitylen + \
257 hdr.associationlen + \
258 hdr.reportedbylen + \
259 hdr.debugdatalen;
260
261 if((event_size + currentsize) >= maxsize) {
262 syslog(LOG_ERR, "event logger reached maximum capacity, event not logged");
263 rec->logid = 0;
264
265 } else if (logcount >= maxlogs) {
266 syslog(LOG_ERR, "event logger reached maximum log events, event not logged");
267 rec->logid = 0;
268
269 } else {
270 currentsize += event_size;
271 myfile.open(buffer.str() , ios::out|ios::binary);
272 myfile.write((char*) &hdr, sizeof(hdr));
273 myfile.write((char*) rec->message, hdr.messagelen);
274 myfile.write((char*) rec->severity, hdr.severitylen);
275 myfile.write((char*) rec->association, hdr.associationlen);
276 myfile.write((char*) rec->reportedby, hdr.reportedbylen);
277 myfile.write((char*) rec->p, hdr.debugdatalen);
278 myfile.close();
279
280 if (is_logid_a_log(rec->logid)) {
281 logcount++;
282 } else {
283 cout << "Warning: Event not logged, failed to store data" << endl;
284 rec->logid = 0;
285 }
286 }
287
288 return rec->logid;
289 }
290
open(uint16_t logid,event_record_t ** rec)291 int event_manager::open(uint16_t logid, event_record_t **rec)
292 {
293 std::ostringstream buffer;
294 ifstream f;
295 logheader_t hdr;
296
297 buffer << eventpath << "/" << int(logid);
298
299 f.open( buffer.str(), ios::binary );
300
301 if (!f.good()) {
302 return 0;
303 }
304
305 *rec = new event_record_t;
306
307 f.read((char*)&hdr, sizeof(hdr));
308
309 (*rec)->logid = hdr.logid;
310 (*rec)->timestamp = hdr.timestamp;
311
312
313 (*rec)->message = new char[hdr.messagelen];
314 f.read((*rec)->message, hdr.messagelen);
315
316 (*rec)->severity = new char[hdr.severitylen];
317 f.read((*rec)->severity, hdr.severitylen);
318
319 (*rec)->association = new char[hdr.associationlen];
320 f.read((*rec)->association, hdr.associationlen);
321
322 (*rec)->reportedby = new char[hdr.reportedbylen];
323 f.read((*rec)->reportedby, hdr.reportedbylen);
324
325 (*rec)->p = new uint8_t[hdr.debugdatalen];
326 f.read((char*)(*rec)->p, hdr.debugdatalen);
327 (*rec)->n = hdr.debugdatalen;
328
329
330 f.close();
331 return logid;
332 }
333
close(event_record_t * rec)334 void event_manager::close(event_record_t *rec)
335 {
336 delete[] rec->message;
337 delete[] rec->severity;
338 delete[] rec->association;
339 delete[] rec->reportedby;
340 delete[] rec->p;
341 delete rec;
342
343 return ;
344 }
345
remove(uint16_t logid)346 int event_manager::remove(uint16_t logid)
347 {
348 std::stringstream buffer;
349 string s;
350 size_t event_size;
351
352 buffer << eventpath << "/" << int(logid);
353
354 s = buffer.str();
355
356 event_size = get_file_size(s);
357 std::remove(s.c_str());
358
359 /* If everything is working correctly deleting all the logs would */
360 /* result in currentsize being zero. But since size_t is unsigned */
361 /* it's kind of dangerous to assume life happens perfectly */
362 if (currentsize < event_size)
363 currentsize = 0;
364 else
365 currentsize -= event_size;
366
367 if (logcount > 0)
368 logcount--;
369
370 return 0;
371 }
372