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