#include #include #include #include #include #include #include #include #include #include #include "message.hpp" #include #include #include #include const uint32_t g_eyecatcher = 0x4F424D43; // OBMC const uint16_t g_version = 1; struct logheader_t { uint32_t eyecatcher; uint16_t version; uint16_t logid; time_t timestamp; uint16_t detailsoffset; uint16_t messagelen; uint16_t severitylen; uint16_t associationlen; uint16_t reportedbylen; uint16_t debugdatalen; }; size_t get_file_size(string fn); event_manager::event_manager(string path, size_t reqmaxsize, uint16_t reqmaxlogs) { uint16_t x; eventpath = path; latestid = 0; dirp = NULL; logcount = 0; maxsize = -1; maxlogs = -1; currentsize = get_managed_size(); if (reqmaxsize) maxsize = reqmaxsize; if (reqmaxlogs) maxlogs = reqmaxlogs; // examine the files being managed and advance latestid to that value while ( (x = next_log()) ) { logcount++; if ( x > latestid ) latestid = x; } return; } event_manager::~event_manager() { if (dirp) closedir(dirp); return; } bool event_manager::is_logid_a_log(uint16_t logid) { std::ostringstream buffer; buffer << int(logid); return is_file_a_log(buffer.str()); } bool event_manager::is_file_a_log(string str) { std::ostringstream buffer; ifstream f; logheader_t hdr; if (!str.compare(".")) return 0; if (!str.compare("..")) return 0; buffer << eventpath << "/" << str; f.open( buffer.str(), ios::binary); if (!f.good()) { f.close(); return 0; } f.read((char*)&hdr, sizeof(hdr)); f.close(); if (hdr.eyecatcher != g_eyecatcher) return 0; return 1; } uint16_t event_manager::log_count(void) { return logcount; } uint16_t event_manager::latest_log_id(void) { return latestid; } uint16_t event_manager::new_log_id(void) { return ++latestid; } void event_manager::next_log_refresh(void) { if (dirp) { closedir(dirp); dirp = NULL; } return; } uint16_t event_manager::next_log(void) { std::ostringstream buffer; struct dirent *ent; uint16_t id; if (dirp == NULL) dirp = opendir(eventpath.c_str()); if (dirp) { do { ent = readdir(dirp); if (ent == NULL) break; string str(ent->d_name); if (is_file_a_log(str)) { id = (uint16_t) atoi(str.c_str()); break; } } while( 1 ); } else { cerr << "Error opening directory " << eventpath << endl; ent = NULL; id = 0; } if (ent == NULL) { closedir(dirp); dirp = NULL; } return ((ent == NULL) ? 0 : id); } uint16_t event_manager::create(event_record_t *rec) { rec->logid = new_log_id(); rec->timestamp = time(NULL); return create_log_event(rec); } inline uint16_t getlen(const char *s) { return (uint16_t) (1 + strlen(s)); } /* If everything is working correctly, return file size, */ /* Otherwise return 0 */ size_t get_file_size(string fn) { struct stat f_stat; int r = -1; r = stat(fn.c_str(), &f_stat); if (r < 0) { fprintf(stderr, "Error get_file_size() for %s, %s\n", fn.c_str(), strerror(errno)); return 0; } return (f_stat.st_size); } size_t event_manager::get_managed_size(void) { DIR *dirp; std::ostringstream buffer; struct dirent *ent; ifstream f; size_t db_size = 0; dirp = opendir(eventpath.c_str()); if (dirp) { while ( (ent = readdir(dirp)) != NULL ) { string str(ent->d_name); if (is_file_a_log(str)) { buffer.str(""); buffer << eventpath << "/" << str.c_str(); db_size += get_file_size(buffer.str()); } } } closedir(dirp); return (db_size); } uint16_t event_manager::create_log_event(event_record_t *rec) { std::ostringstream buffer; ofstream myfile; logheader_t hdr = {0}; size_t event_size=0; buffer << eventpath << "/" << int(rec->logid) ; hdr.eyecatcher = g_eyecatcher; hdr.version = g_version; hdr.logid = rec->logid; hdr.timestamp = rec->timestamp; hdr.detailsoffset = offsetof(logheader_t, messagelen); hdr.messagelen = getlen(rec->message); hdr.severitylen = getlen(rec->severity); hdr.associationlen = getlen(rec->association); hdr.reportedbylen = getlen(rec->reportedby); hdr.debugdatalen = rec->n; event_size = sizeof(logheader_t) + \ hdr.messagelen + \ hdr.severitylen + \ hdr.associationlen + \ hdr.reportedbylen + \ hdr.debugdatalen; if((event_size + currentsize) >= maxsize) { syslog(LOG_ERR, "event logger reached maximum capacity, event not logged"); rec->logid = 0; } else if (logcount >= maxlogs) { syslog(LOG_ERR, "event logger reached maximum log events, event not logged"); rec->logid = 0; } else { currentsize += event_size; myfile.open(buffer.str() , ios::out|ios::binary); myfile.write((char*) &hdr, sizeof(hdr)); myfile.write((char*) rec->message, hdr.messagelen); myfile.write((char*) rec->severity, hdr.severitylen); myfile.write((char*) rec->association, hdr.associationlen); myfile.write((char*) rec->reportedby, hdr.reportedbylen); myfile.write((char*) rec->p, hdr.debugdatalen); myfile.close(); if (is_logid_a_log(rec->logid)) { logcount++; } else { cout << "Warning: Event not logged, failed to store data" << endl; rec->logid = 0; } } return rec->logid; } int event_manager::open(uint16_t logid, event_record_t **rec) { std::ostringstream buffer; ifstream f; logheader_t hdr; buffer << eventpath << "/" << int(logid); f.open( buffer.str(), ios::binary ); if (!f.good()) { return 0; } *rec = new event_record_t; f.read((char*)&hdr, sizeof(hdr)); (*rec)->logid = hdr.logid; (*rec)->timestamp = hdr.timestamp; (*rec)->message = new char[hdr.messagelen]; f.read((*rec)->message, hdr.messagelen); (*rec)->severity = new char[hdr.severitylen]; f.read((*rec)->severity, hdr.severitylen); (*rec)->association = new char[hdr.associationlen]; f.read((*rec)->association, hdr.associationlen); (*rec)->reportedby = new char[hdr.reportedbylen]; f.read((*rec)->reportedby, hdr.reportedbylen); (*rec)->p = new uint8_t[hdr.debugdatalen]; f.read((char*)(*rec)->p, hdr.debugdatalen); (*rec)->n = hdr.debugdatalen; f.close(); return logid; } void event_manager::close(event_record_t *rec) { delete[] rec->message; delete[] rec->severity; delete[] rec->association; delete[] rec->reportedby; delete[] rec->p; delete rec; return ; } int event_manager::remove(uint16_t logid) { std::stringstream buffer; string s; size_t event_size; buffer << eventpath << "/" << int(logid); s = buffer.str(); event_size = get_file_size(s); std::remove(s.c_str()); /* If everything is working correctly deleting all the logs would */ /* result in currentsize being zero. But since size_t is unsigned */ /* it's kind of dangerous to assume life happens perfectly */ if (currentsize < event_size) currentsize = 0; else currentsize -= event_size; if (logcount > 0) logcount--; return 0; }