parameters: add simple BSON verification pass after export

This commit is contained in:
Daniel Agar
2021-12-23 17:20:28 -05:00
parent 72065c3d71
commit 20d3e6f4e1
5 changed files with 126 additions and 22 deletions
+116 -11
View File
@@ -1183,7 +1183,7 @@ static int param_save_file_internal(const char *filename)
while (res != OK && attempts > 0) {
// write parameters to file
int fd = ::open(filename, O_WRONLY | O_CREAT, PX4_O_MODE_666);
int fd = ::open(filename, O_RDWR | O_CREAT, PX4_O_MODE_666);
if (fd > -1) {
res = param_export(fd, nullptr);
@@ -1272,10 +1272,111 @@ param_load_default()
return res;
}
static int param_verify_callback(bson_decoder_t decoder, bson_node_t node)
{
if (node->type == BSON_EOO) {
return 0;
}
// find the parameter this node represents
param_t param = param_find_no_notification(node->name);
if (param == PARAM_INVALID) {
PX4_ERR("verify: invalid parameter '%s'", node->name);
return -1;
}
// handle verifying the parameter from the node
switch (node->type) {
case BSON_INT32: {
if (param_type(param) != PARAM_TYPE_INT32) {
PX4_ERR("verify: invalid param type %d for '%s' (BSON_INT32)", param_type(param), node->name);
return -1;
}
int32_t value;
if (param_get(param, &value) == 0) {
if (value == node->i32) {
return 1; // valid
} else {
PX4_ERR("verify: '%s' invalid BSON value %" PRIi32 "(expected %" PRIi32 ")", node->name, node->i32, value);
}
}
}
break;
case BSON_DOUBLE: {
if (param_type(param) != PARAM_TYPE_FLOAT) {
PX4_ERR("verify: invalid param type %d for '%s' (BSON_DOUBLE)", param_type(param), node->name);
return -1;
}
float value;
if (param_get(param, &value) == 0) {
if (fabsf(value - (float)node->d) <= FLT_EPSILON) {
return 1; // valid
} else {
PX4_ERR("verify: '%s' invalid BSON value %.3f (expected %.3f)", node->name, node->d, (double)value);
}
}
}
break;
default:
PX4_ERR("verify: '%s' invalid node type %d", node->name, node->type);
}
return -1;
}
static int param_verify(int fd)
{
if (fd < 0) {
return -1;
}
if (lseek(fd, 0, SEEK_SET) != 0) {
PX4_ERR("verify: seek failed");
return -1;
}
bson_decoder_s decoder{};
if (bson_decoder_init_file(&decoder, fd, param_verify_callback) == 0) {
int result = -1;
do {
result = bson_decoder_next(&decoder);
} while (result > 0);
if (result == 0) {
return 0;
} else if (result == -ENODATA) {
PX4_ERR("verify: no BSON data");
} else {
PX4_ERR("verify: failed (%d)", result);
}
}
return -1;
}
int
param_export(int fd, param_filter_func filter)
{
int result = -1;
/* no modified parameters -> we are done */
if (param_values == nullptr) {
return 0;
}
int result = -1;
perf_begin(param_export_perf);
if (fd < 0) {
@@ -1303,11 +1404,9 @@ param_export(int fd, param_filter_func filter)
param_lock_reader();
uint8_t bson_buffer[256];
bson_encoder_init_buf_file(&encoder, fd, &bson_buffer, sizeof(bson_buffer));
/* no modified parameters -> we are done */
if (param_values == nullptr) {
result = 0;
if (bson_encoder_init_buf_file(&encoder, fd, &bson_buffer, sizeof(bson_buffer)) != 0) {
result = -1;
goto out;
}
@@ -1323,7 +1422,7 @@ param_export(int fd, param_filter_func filter)
param_get_default_value_internal(s->param, &default_value);
if (s->val.i == default_value) {
PX4_DEBUG("skipping %s %d export", param_name(s->param), default_value);
PX4_DEBUG("skipping %s %" PRIi32 " export", param_name(s->param), default_value);
continue;
}
}
@@ -1348,7 +1447,7 @@ param_export(int fd, param_filter_func filter)
switch (param_type(s->param)) {
case PARAM_TYPE_INT32: {
const int32_t i = s->val.i;
PX4_DEBUG("exporting: %s (%d) size: %lu val: %d", name, s->param, (long unsigned int)size, i);
PX4_DEBUG("exporting: %s (%d) size: %lu val: %" PRIi32, name, s->param, (long unsigned int)size, i);
if (bson_encoder_append_int(&encoder, name, i) != 0) {
PX4_ERR("BSON append failed for '%s'", name);
@@ -1379,12 +1478,18 @@ out:
if (result == 0) {
if (bson_encoder_fini(&encoder) == PX4_OK) {
if (!filter) {
params_unsaved.reset();
// verify exported bson
if (param_verify(fd) == 0) {
if (!filter) {
params_unsaved.reset();
}
} else {
result = -1;
}
} else {
PX4_ERR("BSON encoder finialize failed");
PX4_ERR("BSON encoder finalize failed");
result = -1;
}
}