23 #include "bblogfile.h"
25 #include <core/exceptions/system.h>
26 #include <utils/misc/strndup.h>
27 #include <blackboard/internal/instance_factory.h>
33 # include <sys/endian.h>
34 #elif defined(__MACH__) && defined(__APPLE__)
35 # include <sys/_endian.h>
39 #include <arpa/inet.h>
40 #include <sys/types.h>
45 using namespace fawkes;
68 ctor(filename, do_sanity_check);
71 __instance_factory = NULL;
72 __interface = interface;
73 if ((strcmp(__interface->type(), __interface_type) != 0) ||
74 (strcmp(__interface->id(), __interface_id) != 0)) {
78 free(__interface_type);
80 throw Exception(
"Interface UID %s does not match expected %s:%s",
81 __interface->uid(), __interface_type, __interface_id);
85 __interface = __instance_factory->new_interface_instance(__interface_type,
103 ctor(filename, do_sanity_check);
105 __instance_factory = NULL;
111 BBLogFile::ctor(
const char *filename,
bool do_sanity_check)
113 __f = fopen(filename,
"r");
118 __filename = strdup(filename);
123 if (do_sanity_check) sanity_check();
127 free(__interface_type);
128 free(__interface_id);
133 __ifdata = malloc(__header->data_size);
139 if (__instance_factory) {
140 __instance_factory->delete_interface_instance(__interface);
141 delete __instance_factory;
148 free(__interface_type);
149 free(__interface_id);
158 BBLogFile::read_file_header()
162 if ((fread(&magic,
sizeof(uint32_t), 1, __f) == 1) &&
163 (fread(&version,
sizeof(uint32_t), 1, __f) == 1) ) {
164 if ( (ntohl(magic) == BBLOGGER_FILE_MAGIC) &&
165 (ntohl(version) == BBLOGGER_FILE_VERSION) ) {
171 throw Exception(
"File magic/version %X/%u does not match (expected %X/%u)",
172 ntohl(magic), ntohl(version),
173 BBLOGGER_FILE_VERSION, BBLOGGER_FILE_MAGIC);
176 throw Exception(__filename, errno,
"Failed to read magic/version from file");
179 __scenario = strndup(__header->scenario, BBLOG_SCENARIO_SIZE);
180 __interface_type = strndup(__header->interface_type, BBLOG_INTERFACE_TYPE_SIZE);
181 __interface_id = strndup(__header->interface_id, BBLOG_INTERFACE_ID_SIZE);
183 __start_time.set_time(__header->start_time_sec, __header->start_time_usec);
195 BBLogFile::sanity_check()
197 if (__header->num_data_items == 0) {
198 Exception e(
"File %s does not specify number of data items", __filename);
199 e.set_type_id(
"bblogfile-num-items-zero");
204 if (fstat(fileno(__f), &fs) != 0) {
205 Exception e(errno,
"Failed to stat file %s", __filename);
206 e.set_type_id(
"bblogfile-stat-failed");
211 + __header->num_data_items * __header->data_size
213 if (expected_size != fs.st_size) {
214 Exception e(
"Size of file %s does not match expectation "
215 "(actual: %li, actual: %li)",
216 __filename, expected_size, (
long int)fs.st_size);
217 e.set_type_id(
"bblogfile-file-size-mismatch");
221 #if __BYTE_ORDER == __LITTLE_ENDIAN
222 if (__header->endianess == 1)
224 if (__header->endianess == 0)
227 Exception e(
"File %s has incompatible endianess", __filename);
228 e.set_type_id(
"bblogfile-endianess-mismatch");
242 if (fseek(__f, offset, SEEK_SET) != 0) {
243 throw Exception(errno,
"Cannot seek to index %u", index);
257 throw Exception(errno,
"Cannot reset file");
259 __entry_offset.set_time(0, 0);
271 if (getc(__f) == EOF) {
274 fseek(__f, -1, SEEK_CUR);
289 (fread(__ifdata, __header->data_size, 1, __f) == 1) ) {
291 __interface->set_from_chunk(__ifdata);
293 throw Exception(
"Cannot read interface data");
306 #if _POSIX_MAPPED_FILES
309 if (h == MAP_FAILED) {
310 throw Exception(errno,
"Failed to mmap log, not updating number of data items");
317 throw Exception(
"Cannot set number of entries, mmap not available.");
341 FILE *f = freopen(__filename,
"r+", __f);
343 throw Exception(
"Reopening file %s with new mode failed", __filename);
347 bool repair_done =
false;
349 Exception success(
"Successfully repaired file");
350 success.set_type_id(
"repair-success");
352 #if __BYTE_ORDER == __LITTLE_ENDIAN
353 if (__header->endianess == 1)
355 if (__header->endianess == 0)
358 throw Exception(
"File %s has incompatible endianess. Cannot repair.",
363 if (fstat(fileno(__f), &fs) != 0) {
364 throw Exception(errno,
"Failed to stat file %s", __filename);
369 size_t num_entries = all_entries_size / entry_size;
370 size_t extra_bytes = all_entries_size % entry_size;
372 if (extra_bytes != 0) {
373 success.append(
"FIXING: errorneous bytes at end of file, "
374 "truncating by %zu b", extra_bytes);
375 if (ftruncate(fileno(__f), fs.st_size - extra_bytes) == -1) {
376 throw Exception(errno,
"Failed to truncate file %s", __filename);
378 all_entries_size -= extra_bytes;
380 if (fstat(fileno(__f), &fs) != 0) {
381 throw Exception(errno,
"Failed to update information of file %s "
382 "after truncate", __filename);
386 if (__header->num_data_items == 0) {
387 success.append(
"FIXING: header of file %s has 0 data items, setting to %zu.",
388 __filename, num_entries);
389 set_num_entries(num_entries);
391 }
else if (__header->num_data_items != num_entries) {
392 success.append(
"FIXING: header has %u data items, but expecting %zu, setting",
393 __header->num_data_items, num_entries);
394 set_num_entries(num_entries);
398 f = freopen(__filename,
"r", __f);
400 throw Exception(
"Reopening file %s with read-only mode failed", __filename);
417 char interface_hash[BBLOG_INTERFACE_HASH_SIZE * 2 + 1];
419 for (
unsigned int i = 0; i < BBLOG_INTERFACE_HASH_SIZE; ++i) {
420 snprintf(&interface_hash[i*2], 3,
"%02X", __header->interface_hash[i]);
424 if (fstat(fileno(__f), &fs) != 0) {
425 throw Exception(errno,
"Failed to get stat file");
429 "%sFile version: %-10u Endianess: %s Endian\n"
430 "%s# data items: %-10u Data size: %u bytes\n"
431 "%sHeader size: %zu bytes File size: %li bytes\n"
434 "%sInterface: %s::%s (%s)\n"
435 "%sStart time: %s\n",
436 line_prefix, ntohl(__header->file_version),
437 (__header->endianess == 1) ?
"Big" :
"Little",
438 line_prefix, __header->num_data_items, __header->data_size,
441 line_prefix, __scenario,
442 line_prefix, __interface_type, __interface_id, interface_hash,
443 line_prefix, __start_time.str());
455 fprintf(outf,
"Time Offset: %f\n", __entry_offset.in_sec());
458 for (i = __interface->fields(); i != __interface->fields_end(); ++i) {
460 if (i.get_length() > 1) {
461 if (asprintf(&typesize,
"%s[%zu]", i.get_typename(), i.get_length()) == -1) {
465 if (asprintf(&typesize,
"%s", i.get_typename()) == -1) {
469 fprintf(outf,
"%-16s %-18s: %s\n",
470 i.get_name(), typesize, i.get_value_string());
493 if ( (strcmp(interface->
type(), __interface_type) == 0) &&
494 (strcmp(interface->
id(), __interface_id) == 0) &&
495 (memcmp(interface->
hash(), __header->interface_hash,
496 __INTERFACE_HASH_SIZE) == 0) ) {
497 if (__instance_factory) {
498 __instance_factory->delete_interface_instance(__interface);
499 delete __instance_factory;
500 __instance_factory = NULL;
502 __interface = interface;
516 return __entry_offset;
526 return ntohl(__header->file_version);
536 return (__header->endianess == 1);
545 return __header->num_data_items;
565 return __interface_type;
575 return __interface_id;
586 return __header->interface_hash;
596 return __header->data_size;
618 long curpos = ftell(__f);
619 size_t fsize = file_size();
620 size_t sizediff = fsize - curpos;
623 throw Exception(
"File %s shrank while reading it", __filename);
626 return sizediff / entry_size;
636 if (fstat(fileno(__f), &fs) != 0) {
637 Exception e(errno,
"Failed to stat file %s", __filename);