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 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 63 event_manager::~event_manager() 64 { 65 if (dirp) 66 closedir(dirp); 67 68 return; 69 } 70 71 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 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 110 uint16_t event_manager::log_count(void) 111 { 112 return logcount; 113 } 114 uint16_t event_manager::latest_log_id(void) 115 { 116 return latestid; 117 } 118 uint16_t event_manager::new_log_id(void) 119 { 120 return ++latestid; 121 } 122 void event_manager::next_log_refresh(void) 123 { 124 if (dirp) { 125 closedir(dirp); 126 dirp = NULL; 127 } 128 129 return; 130 } 131 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 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 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 */ 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 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 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 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 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 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