1591 lines
32 KiB
C
1591 lines
32 KiB
C
/*
|
|
* Copyright (C) 2012 Texas Instruments Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2 as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <regex.h>
|
|
#include <sys/stat.h>
|
|
#include <getopt.h>
|
|
|
|
#include "crc32.h"
|
|
#include "wlconf.h"
|
|
|
|
#ifdef ANDROID
|
|
ssize_t getline(char **lineptr, size_t *n, FILE *stream)
|
|
{
|
|
char *lptr;
|
|
ssize_t len;
|
|
|
|
lptr = fgetln(stream, (size_t*) &len);
|
|
if (lptr == NULL) {
|
|
len = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (*lineptr == NULL || (ssize_t) *n < (len + 1)) {
|
|
/* needs reallocation */
|
|
char *newptr = realloc(*lineptr, len + 1);
|
|
if (newptr == NULL) {
|
|
/* realloc failed, we still have old lineptr and n */
|
|
len = -1;
|
|
goto out;
|
|
}
|
|
|
|
*lineptr = newptr;
|
|
*n = len + 1;
|
|
}
|
|
|
|
memcpy(*lineptr, lptr, len);
|
|
(*lineptr)[len] = '\0';
|
|
|
|
out:
|
|
return len;
|
|
}
|
|
#endif
|
|
|
|
static struct dict_entry *dict = NULL;
|
|
static int n_dict_entries = 0;
|
|
|
|
static struct structure *structures = NULL;
|
|
static int n_structs = 0;
|
|
|
|
static int magic = 0;
|
|
static int version = 0;
|
|
static int checksum = 0;
|
|
static int struct_chksum = 0;
|
|
static int ignore_checksum = 0;
|
|
|
|
static int get_type(char *type_str)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < (sizeof(types) / sizeof(types[0])); i++)
|
|
if (!strcmp(type_str, types[i].name))
|
|
return i;
|
|
|
|
for (i = 0; i < n_structs; i++) {
|
|
struct structure *curr_struct;
|
|
curr_struct = &structures[i];
|
|
|
|
if (!strcmp(type_str, curr_struct->name)) {
|
|
return STRUCT_BASE + i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static char *remove_comments(const char *orig_str)
|
|
{
|
|
regex_t r;
|
|
char *new_str = NULL;
|
|
regmatch_t m[6];
|
|
|
|
if (regcomp(&r, CC_COMMENT_PATTERN, REG_EXTENDED) < 0)
|
|
goto out;
|
|
|
|
new_str = strdup(orig_str);
|
|
|
|
while (!regexec(&r, new_str, 4, m, 0)) {
|
|
char *part1, *part2;
|
|
|
|
part1 = strndup(new_str + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
part2 = strndup(new_str + m[3].rm_so, m[3].rm_eo - m[3].rm_so);
|
|
|
|
snprintf(new_str, strlen(orig_str), "%s%s", part1, part2);
|
|
|
|
free(part1);
|
|
free(part2);
|
|
}
|
|
|
|
regfree(&r);
|
|
|
|
if (regcomp(&r, C_COMMENT_PATTERN, REG_EXTENDED) < 0)
|
|
goto out;
|
|
|
|
while (!regexec(&r, new_str, 6, m, 0)) {
|
|
char *part1, *part2;
|
|
|
|
part1 = strndup(new_str + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
part2 = strndup(new_str + m[5].rm_so, m[5].rm_eo - m[5].rm_so);
|
|
|
|
snprintf(new_str, strlen(orig_str), "%s%s", part1, part2);
|
|
|
|
free(part1);
|
|
free(part2);
|
|
}
|
|
|
|
regfree(&r);
|
|
out:
|
|
return new_str;
|
|
}
|
|
|
|
static struct structure *get_struct(const char *structure)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < n_structs; j++)
|
|
if (!strcmp(structure, structures[j].name))
|
|
return &structures[j];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int parse_define(const char *buffer, char *symbol, int *value)
|
|
{
|
|
regex_t r;
|
|
int ret;
|
|
const char *str;
|
|
|
|
ret = regcomp(&r, DEFINE_PATTERN, REG_EXTENDED);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
str = buffer;
|
|
|
|
while (strlen(str)) {
|
|
regmatch_t m[3];
|
|
char *symbol_str, *value_str = NULL;
|
|
|
|
if (regexec(&r, str, 3, m, 0))
|
|
break;
|
|
|
|
symbol_str =
|
|
strndup(str + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
|
|
value_str = strndup(str + m[2].rm_so, m[2].rm_eo - m[2].rm_so);
|
|
|
|
if (!strcmp(symbol, symbol_str)) {
|
|
if (*value == 0) {
|
|
*value = strtol(value_str, NULL, 0);
|
|
printf("symbol %s found %s (%08x)\n",
|
|
symbol, value_str, *value);
|
|
} else {
|
|
fprintf(stderr, "symbol %s redefined\n",
|
|
symbol_str);
|
|
ret = -1;
|
|
}
|
|
}
|
|
|
|
free(symbol_str);
|
|
symbol_str = NULL;
|
|
free(value_str);
|
|
value_str = NULL;
|
|
|
|
str += m[2].rm_eo;
|
|
};
|
|
|
|
out:
|
|
regfree(&r);
|
|
return ret;
|
|
}
|
|
|
|
static int parse_elements(char *orig_str, struct element **elements,
|
|
size_t *size)
|
|
{
|
|
regex_t r;
|
|
int ret, n_elements = 0;
|
|
char *str, *clean_str;
|
|
|
|
*size = 0;
|
|
|
|
ret = regcomp(&r, ELEMENT_PATTERN, REG_EXTENDED);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
clean_str = remove_comments(orig_str);
|
|
if (!clean_str)
|
|
goto out;
|
|
|
|
*elements = NULL;
|
|
|
|
str = clean_str;
|
|
|
|
while (strlen(str)) {
|
|
regmatch_t m[6];
|
|
char *type_str, *array_size_str = NULL;
|
|
struct element *curr_element;
|
|
|
|
if (regexec(&r, str, 6, m, 0))
|
|
break;
|
|
|
|
*elements = realloc(*elements,
|
|
++n_elements * sizeof(**elements));
|
|
if (!elements) {
|
|
ret = -1;
|
|
goto out_free;
|
|
}
|
|
|
|
curr_element = &(*elements)[n_elements - 1];
|
|
|
|
curr_element->name =
|
|
strndup(str + m[2].rm_so, m[2].rm_eo - m[2].rm_so);
|
|
|
|
curr_element->position = *size;
|
|
|
|
if (m[4].rm_so == m[4].rm_eo) {
|
|
curr_element->array_size = 1;
|
|
} else {
|
|
array_size_str =
|
|
strndup(str + m[4].rm_so, m[4].rm_eo - m[4].rm_so);
|
|
curr_element->array_size = strtol(array_size_str, NULL, 0);
|
|
}
|
|
|
|
type_str = strndup(str + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
curr_element->type = get_type(type_str);
|
|
if (curr_element->type == -1)
|
|
fprintf(stderr, "Error! Unknown type '%s'\n", type_str);
|
|
|
|
if (curr_element->type < STRUCT_BASE)
|
|
*size += curr_element->array_size *
|
|
types[curr_element->type].size;
|
|
else {
|
|
struct structure *structure =
|
|
get_struct(type_str);
|
|
|
|
*size += curr_element->array_size *
|
|
structure->size;
|
|
}
|
|
|
|
free(type_str);
|
|
free(array_size_str);
|
|
|
|
str += m[2].rm_eo;
|
|
}
|
|
|
|
ret = n_elements;
|
|
|
|
out_free:
|
|
free(clean_str);
|
|
regfree(&r);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void print_usage(char *executable)
|
|
{
|
|
printf("Usage:\n\t%s [OPTIONS] [COMMANDS]\n"
|
|
"\n\tOPTIONS\n"
|
|
"\t-S, --source-struct\tuse the structure specified in a C header file\n"
|
|
"\t-b, --binary-struct\tspecify the binary file where the structure is defined\n"
|
|
"\t-i, --input-config\tlocation of the input binary configuration file\n"
|
|
"\t-o, --output-config\tlocation of the input binary configuration file\n"
|
|
"\t-X, --ignore-checksum\tignore file checksum error detection\n"
|
|
"\n\tCOMMANDS\n"
|
|
"\t-D, --create-default\tcreate default configuration bin file (%s)\n"
|
|
"\t-g, --get\t\tget the value of the specified element (element[.element...]) or\n"
|
|
"\t\t\t\tprint the entire tree if no element is specified\n"
|
|
"\t-s, --set\t\tset the value of the specified element (element[.element...])\n"
|
|
"\t-G, --generate-struct\tgenerate the binary structure file from\n"
|
|
"\t\t\t\tthe specified source file\n"
|
|
"\t-C, --parse-text-conf\tparse the specified text config and set the values accordingly\n"
|
|
"\t-I, --parse-ini\t\tparse the specified INI file and set the values accordingly\n"
|
|
"\t\t\t\tin the output binary configuration file\n"
|
|
"\t-p, --print-struct\tprint out the structure\n"
|
|
"\t-h, --help\t\tprint this help\n"
|
|
"\n",
|
|
executable,
|
|
DEFAULT_INPUT_FILENAME);
|
|
}
|
|
|
|
static void free_structs(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_structs; i++)
|
|
free(structures[i].elements);
|
|
|
|
free(structures);
|
|
}
|
|
|
|
static void free_dict(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n_dict_entries; i++) {
|
|
free(dict[i].ini_str);
|
|
free(dict[i].element_str);
|
|
}
|
|
|
|
free(dict);
|
|
}
|
|
|
|
static int parse_header(const char *buffer)
|
|
{
|
|
regex_t r;
|
|
const char *str;
|
|
int ret;
|
|
|
|
ret = parse_define(buffer, DEFAULT_MAGIC_SYMBOL, &magic);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = parse_define(buffer, DEFAULT_VERSION_SYMBOL, &version);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = regcomp(&r, STRUCT_PATTERN, REG_EXTENDED);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
str = buffer;
|
|
|
|
while (strlen(str)) {
|
|
char *elements_str;
|
|
struct structure *curr_struct;
|
|
regmatch_t m[4];
|
|
|
|
if (regexec(&r, str, 4, m, 0))
|
|
break;
|
|
|
|
structures = realloc(structures, ++n_structs *
|
|
sizeof(struct structure));
|
|
if (!structures) {
|
|
ret = -1;
|
|
goto out_free;
|
|
}
|
|
|
|
curr_struct = &structures[n_structs - 1];
|
|
|
|
curr_struct->name =
|
|
strndup(str + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
|
|
elements_str = strndup(str + m[2].rm_so, m[2].rm_eo - m[2].rm_so);
|
|
|
|
ret = parse_elements(elements_str, &curr_struct->elements,
|
|
&curr_struct->size);
|
|
if (ret < 0)
|
|
break;
|
|
|
|
curr_struct->n_elements = ret;
|
|
|
|
str += m[2].rm_eo;
|
|
}
|
|
|
|
out_free:
|
|
regfree(&r);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void print_data(struct element *elem, void *data)
|
|
{
|
|
uint8_t *u8;
|
|
uint16_t *u16;
|
|
uint32_t *u32;
|
|
int i;
|
|
char *pos = data;
|
|
|
|
for (i = 0; i < elem->array_size; i++) {
|
|
switch (types[elem->type].size) {
|
|
case 1:
|
|
u8 = (uint8_t *) pos;
|
|
printf("0x%02x", *u8);
|
|
break;
|
|
case 2:
|
|
u16 = (uint16_t *) pos;
|
|
printf("0x%04x", *u16);
|
|
break;
|
|
case 4:
|
|
u32 = (uint32_t *) pos;
|
|
printf("0x%08x", *u32);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Error! Unsupported data size\n");
|
|
break;
|
|
}
|
|
|
|
if (i < elem->array_size - 1)
|
|
printf(", ");
|
|
|
|
pos += types[elem->type].size;
|
|
}
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
static int set_data(struct element *elem, void *buffer, void *data)
|
|
{
|
|
switch (types[elem->type].size) {
|
|
case 1:
|
|
*((uint8_t *)buffer) = *((uint8_t *)data);
|
|
break;
|
|
case 2:
|
|
*((uint16_t *)buffer) = *((uint16_t *)data);
|
|
break;
|
|
case 4:
|
|
*((uint32_t *)buffer) = *((uint32_t *)data);
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Error! Unsupported data size\n");
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int print_element(struct element *elem, char *parent, void *data)
|
|
{
|
|
char *pos = data, *curr_name = NULL;
|
|
size_t len;
|
|
int ret = 0;
|
|
|
|
if (parent) {
|
|
len = parent ? strlen(parent) : 0;
|
|
len += strlen(elem->name) + 2;
|
|
curr_name = malloc(len);
|
|
if (!curr_name) {
|
|
fprintf(stderr, "couldn't allocate memory\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
sprintf(curr_name, "%s.%s", parent, elem->name);
|
|
} else if (elem->type != get_type(DEFAULT_ROOT_STRUCT)) {
|
|
curr_name = strdup(elem->name);
|
|
}
|
|
|
|
if (elem->type < STRUCT_BASE) {
|
|
if (data) {
|
|
printf("%s = ", curr_name);
|
|
print_data(elem, pos);
|
|
pos += elem->array_size *
|
|
types[elem->type].size;
|
|
} else {
|
|
printf("\t%s %s[%d]\n",
|
|
types[elem->type].name, elem->name,
|
|
elem->array_size);
|
|
}
|
|
} else {
|
|
struct structure *sub;
|
|
int j;
|
|
|
|
sub = &structures[elem->type - STRUCT_BASE];
|
|
|
|
if (!data)
|
|
printf("struct %s {\n", sub->name);
|
|
|
|
for (j = 0; j < sub->n_elements; j++) {
|
|
print_element(&sub->elements[j], curr_name, pos);
|
|
|
|
if (!data)
|
|
continue;
|
|
|
|
if (sub->elements[j].type < STRUCT_BASE)
|
|
pos += sub->elements[j].array_size *
|
|
types[sub->elements[j].type].size;
|
|
else
|
|
pos += sub->elements[j].array_size *
|
|
structures[sub->elements[j].type - STRUCT_BASE].size;
|
|
}
|
|
|
|
if (!data)
|
|
printf("} /* %s */\n", sub->name);
|
|
}
|
|
|
|
free(curr_name);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int read_file(const char *filename, void **buffer, size_t size)
|
|
{
|
|
FILE *file;
|
|
struct stat st;
|
|
int ret;
|
|
size_t buf_size;
|
|
|
|
ret = stat(filename, &st);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Couldn't get file size '%s'\n", filename);
|
|
goto out;
|
|
}
|
|
|
|
file = fopen(filename, "r");
|
|
if (!file) {
|
|
fprintf(stderr, "Couldn't open file '%s'\n", filename);
|
|
return -1;
|
|
}
|
|
|
|
if (size)
|
|
buf_size = size;
|
|
else
|
|
buf_size = st.st_size;
|
|
|
|
*buffer = malloc(buf_size);
|
|
if (!*buffer) {
|
|
fprintf(stderr, "Couldn't allocate enough memory (%d)\n", buf_size);
|
|
fclose(file);
|
|
return -1;
|
|
}
|
|
|
|
if (fread(*buffer, 1, buf_size, file) != buf_size) {
|
|
fprintf(stderr, "Failed to read file '%s'\n", filename);
|
|
fclose(file);
|
|
return -1;
|
|
}
|
|
|
|
fclose(file);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void free_file(void *buffer)
|
|
{
|
|
free(buffer);
|
|
}
|
|
|
|
static int write_file(const char *filename, const void *buffer, size_t size)
|
|
{
|
|
FILE *file;
|
|
int ret;
|
|
|
|
file = fopen(filename, "w");
|
|
if (!file) {
|
|
fprintf(stderr, "Couldn't open file '%s' for writing\n",
|
|
filename);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (fwrite(buffer, 1, size, file) != size) {
|
|
fprintf(stderr, "Failed to write file '%s'\n", filename);
|
|
fclose(file);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
fclose(file);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int get_element_pos(struct structure *structure, const char *argument,
|
|
struct element **element)
|
|
{
|
|
int i, pos = 0;
|
|
struct structure *curr_struct = structure;
|
|
struct element *curr_element = NULL;
|
|
char *str, *arg = strdup(argument);
|
|
|
|
str = strtok(arg, ".");
|
|
|
|
while(str) {
|
|
|
|
for (i = 0; i < curr_struct->n_elements; i++)
|
|
if (!strcmp(str, curr_struct->elements[i].name)) {
|
|
curr_element = &curr_struct->elements[i];
|
|
pos += curr_element->position;
|
|
break;
|
|
}
|
|
|
|
if (i == curr_struct->n_elements) {
|
|
pos = -1;
|
|
goto out;
|
|
}
|
|
|
|
str = strtok(NULL, ".");
|
|
if (str && curr_element->type < STRUCT_BASE) {
|
|
fprintf(stderr, "element %s is not a struct\n",
|
|
curr_element->name);
|
|
pos = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (str)
|
|
curr_struct =
|
|
&structures[curr_element->type - STRUCT_BASE];
|
|
}
|
|
|
|
out:
|
|
*element = curr_element;
|
|
free(arg);
|
|
return pos;
|
|
}
|
|
|
|
static void get_value(void *buffer, struct structure *structure,
|
|
char *argument)
|
|
{
|
|
int pos;
|
|
struct element *element, *root_element = NULL;
|
|
char *elim;
|
|
|
|
if (argument) {
|
|
pos = get_element_pos(structure, argument, &element);
|
|
if (pos < 0) {
|
|
fprintf(stderr, "couldn't find %s\n", argument);
|
|
return;
|
|
}
|
|
/* change argument into parent by removing the last
|
|
* element name */
|
|
elim = strrchr(argument, '.');
|
|
if (elim)
|
|
*elim = '\0';
|
|
else
|
|
argument = NULL;
|
|
} else {
|
|
root_element = malloc(sizeof(*element));
|
|
root_element->name = NULL;
|
|
root_element->type = get_type(DEFAULT_ROOT_STRUCT);
|
|
root_element->array_size = 1;
|
|
root_element->value = NULL;
|
|
root_element->position = 0;
|
|
element = root_element;
|
|
pos = 0;
|
|
}
|
|
|
|
if (buffer)
|
|
buffer = ((char *)buffer) + pos;
|
|
|
|
print_element(element, argument, buffer);
|
|
|
|
free(root_element);
|
|
}
|
|
|
|
static int set_value(void *buffer, struct structure *structure,
|
|
char *argument)
|
|
{
|
|
int pos, ret = 0;
|
|
char *split_point, *element_str, *value_str;
|
|
struct element *element;
|
|
uint32_t value;
|
|
|
|
split_point = strchr(argument, '=');
|
|
if (!split_point) {
|
|
fprintf(stderr,
|
|
"--set requires the format <element>[.<element>...]=<value>\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
*split_point = '\0';
|
|
element_str = argument;
|
|
value_str = split_point + 1;
|
|
|
|
pos = get_element_pos(structure, element_str, &element);
|
|
if (pos < 0) {
|
|
fprintf(stderr, "couldn't find %s\n", element_str);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (element->array_size > 1) {
|
|
fprintf(stderr, "setting arrays not supported yet\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (element->type >= STRUCT_BASE) {
|
|
fprintf(stderr,
|
|
"setting entire structures is not supported.\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
value = strtoul(value_str, NULL, 0);
|
|
ret = set_data(element, ((char *)buffer) + pos, &value);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int write_element(FILE *file, struct element *element)
|
|
{
|
|
size_t name_len = strlen(element->name);
|
|
|
|
WRITE_INT32(name_len, file);
|
|
fwrite(element->name, 1, name_len, file);
|
|
WRITE_INT32(element->type, file);
|
|
WRITE_INT32(element->array_size, file);
|
|
WRITE_INT32(element->position, file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int write_struct(FILE *file, struct structure *structure)
|
|
{
|
|
size_t name_len = strlen(structure->name);
|
|
int i, ret = 0;
|
|
|
|
WRITE_INT32(name_len, file);
|
|
fwrite(structure->name, 1, name_len, file);
|
|
WRITE_INT32(structure->n_elements, file);
|
|
WRITE_INT32(structure->size, file);
|
|
|
|
for (i = 0; i < structure->n_elements; i++) {
|
|
ret = write_element(file, &structure->elements[i]);
|
|
if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int generate_struct(const char *filename)
|
|
{
|
|
FILE *file;
|
|
int i, ret = 0;
|
|
|
|
file = fopen(filename, "w");
|
|
if (!file) {
|
|
fprintf(stderr, "Couldn't open file '%s' for writing\n",
|
|
filename);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
WRITE_INT32(magic, file);
|
|
WRITE_INT32(version, file);
|
|
WRITE_INT32(struct_chksum, file);
|
|
WRITE_INT32(n_structs, file);
|
|
|
|
for (i = 0; i < n_structs; i++) {
|
|
ret = write_struct(file, &structures[i]);
|
|
if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
fclose(file);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int read_element(FILE *file, struct element *element)
|
|
{
|
|
size_t name_len;
|
|
int ret = 0;
|
|
|
|
READ_INT32(name_len, (size_t), file);
|
|
|
|
element->name = malloc(name_len + 1);
|
|
if (!element->name) {
|
|
fprintf(stderr, "Couldn't allocate enough memory (%d)\n",
|
|
name_len);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
fread(element->name, 1, name_len, file);
|
|
element->name[name_len] = '\0';
|
|
|
|
READ_INT32(element->type, (int), file);
|
|
READ_INT32(element->array_size, (int), file);
|
|
READ_INT32(element->position, (size_t), file);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int read_struct(FILE *file, struct structure *structure)
|
|
{
|
|
size_t name_len;
|
|
int i, ret = 0;
|
|
|
|
READ_INT32(name_len, (size_t), file);
|
|
|
|
structure->name = malloc(name_len + 1);
|
|
if (!structure->name) {
|
|
fprintf(stderr, "Couldn't allocate enough memory (%d)\n",
|
|
name_len);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
fread(structure->name, 1, name_len, file);
|
|
structure->name[name_len] = '\0';
|
|
|
|
READ_INT32(structure->n_elements, (int), file);
|
|
READ_INT32(structure->size, (size_t), file);
|
|
|
|
structure->elements = malloc(structure->n_elements *
|
|
sizeof(struct element));
|
|
if (!structure->elements) {
|
|
fprintf(stderr, "Couldn't allocate enough memory (%d)\n",
|
|
structure->n_elements * sizeof(struct element));
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
for (i = 0; i < structure->n_elements; i++) {
|
|
ret = read_element(file, &structure->elements[i]);
|
|
if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int read_binary_struct(const char *filename)
|
|
{
|
|
FILE *file;
|
|
int i, ret = 0;
|
|
|
|
file = fopen(filename, "r");
|
|
if (!file) {
|
|
fprintf(stderr, "Couldn't open file '%s' for reading\n",
|
|
filename);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
READ_INT32(magic, (int), file);
|
|
READ_INT32(version, (int), file);
|
|
READ_INT32(struct_chksum, (int), file);
|
|
READ_INT32(n_structs, (int), file);
|
|
|
|
structures = malloc(n_structs * sizeof(struct structure));
|
|
if (!structures) {
|
|
fprintf(stderr, "Couldn't allocate enough memory (%d)\n",
|
|
n_structs * sizeof(struct structure));
|
|
ret = -1;
|
|
goto out_close;
|
|
}
|
|
|
|
for (i = 0; i < n_structs; i++) {
|
|
ret = read_struct(file, &structures[i]);
|
|
if (ret < 0)
|
|
break;
|
|
}
|
|
|
|
out_close:
|
|
fclose(file);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int get_value_int(void *buffer, struct structure *structure,
|
|
int *value, char *element_str)
|
|
{
|
|
int pos, ret = 0;
|
|
struct element *element;
|
|
|
|
pos = get_element_pos(structure, element_str, &element);
|
|
if (pos < 0) {
|
|
fprintf(stderr, "couldn't find %s\n", element_str);
|
|
ret = pos;
|
|
goto out;
|
|
}
|
|
|
|
if ((element->type != get_type("u32")) &&
|
|
(element->type != get_type("__le32"))) {
|
|
fprintf(stderr,
|
|
"element %s has invalid type (expected u32 or le32)\n",
|
|
element_str);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
*value = *(int *) (((char *)buffer) + pos);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int set_value_int(void *buffer, struct structure *structure,
|
|
int value, char *element_str)
|
|
{
|
|
int pos, ret = 0;
|
|
struct element *element;
|
|
|
|
pos = get_element_pos(structure, element_str, &element);
|
|
if (pos < 0) {
|
|
fprintf(stderr, "couldn't find %s\n", element_str);
|
|
ret = pos;
|
|
goto out;
|
|
}
|
|
|
|
if ((element->type != get_type("u32")) &&
|
|
(element->type != get_type("__le32"))) {
|
|
fprintf(stderr,
|
|
"element %s has invalid type (expected u32 or le32)\n",
|
|
element_str);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
*(int *) (((char *)buffer) + pos) = value;
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int read_input(const char *filename, void **buffer,
|
|
struct structure *structure)
|
|
{
|
|
int ret;
|
|
int input_magic, input_version, input_checksum;
|
|
|
|
ret = read_file(filename, buffer, structure->size);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = get_value_int(*buffer, structure, &input_magic,
|
|
DEFAULT_MAGIC_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = get_value_int(*buffer, structure, &input_version,
|
|
DEFAULT_VERSION_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = get_value_int(*buffer, structure, &input_checksum,
|
|
DEFAULT_CHKSUM_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* after reading the checksum, set it to 0 for checksum calculation */
|
|
ret = set_value_int(*buffer, structure, 0, DEFAULT_CHKSUM_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
checksum = calc_crc32(*buffer, structure->size);
|
|
|
|
if ((magic != input_magic) ||
|
|
(version != input_version)) {
|
|
fprintf(stderr, "incompatible binary file\n"
|
|
"expected 0x%08x 0x%08x\n"
|
|
"got 0x%08x 0x%08x\n",
|
|
magic, version, input_magic, input_version);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (!ignore_checksum && (checksum != input_checksum)) {
|
|
fprintf(stderr, "corrupted binary file\n"
|
|
"expected checksum 0x%08x got 0x%08x\n",
|
|
checksum, input_checksum);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int translate_ini(char **element_str, char **value_array)
|
|
{
|
|
int i, ret = 0;
|
|
char *translated_array, *translated_value, *value_str;
|
|
size_t len;
|
|
|
|
for (i = 0; i < n_dict_entries; i++)
|
|
if (!strcmp(dict[i].ini_str, *element_str)) {
|
|
free(*element_str);
|
|
*element_str = strdup(dict[i].element_str);
|
|
if (!element_str) {
|
|
fprintf(stderr, "couldn't allocate memory\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
translated_array = malloc(MAX_ARRAY_STR_LEN);
|
|
translated_value = malloc(MAX_VALUE_STR_LEN);
|
|
if(!translated_array || !translated_value) {
|
|
fprintf(stderr, "couldn't allocate memory\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
translated_array[0] = '\0';
|
|
|
|
value_str = strtok(*value_array, " \t");
|
|
while (value_str) {
|
|
len = snprintf(translated_value, MAX_VALUE_STR_LEN, "0x%s,",
|
|
value_str);
|
|
if (len >= MAX_VALUE_STR_LEN) {
|
|
fprintf(stderr, "value string is too long!\n");
|
|
ret = -1;
|
|
goto out_free;
|
|
}
|
|
|
|
len = strlen(translated_value) + strlen(translated_array);
|
|
if (len >= MAX_ARRAY_STR_LEN) {
|
|
fprintf(stderr, "value array is too long!\n");
|
|
ret = -1;
|
|
goto out_free;
|
|
}
|
|
|
|
strncat(translated_array, translated_value, MAX_ARRAY_STR_LEN);
|
|
|
|
value_str = strtok(NULL, " \t");
|
|
}
|
|
|
|
/* remove last comma */
|
|
translated_array[strlen(translated_array) - 1] = '\0';
|
|
|
|
free(*value_array);
|
|
*value_array = strdup(translated_array);
|
|
if (!*value_array) {
|
|
fprintf(stderr, "couldn't allocate memory\n");
|
|
ret = -1;
|
|
goto out_free;
|
|
}
|
|
|
|
out_free:
|
|
free(translated_array);
|
|
free(translated_value);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int parse_dict(const char *filename)
|
|
{
|
|
regex_t r;
|
|
FILE *file;
|
|
unsigned int parse_errors = 0, line_number = 0;
|
|
int ret;
|
|
|
|
file = fopen(filename, "r");
|
|
if (!file) {
|
|
fprintf(stderr, "Couldn't open file '%s'\n", filename);
|
|
return -1;
|
|
}
|
|
|
|
ret = regcomp(&r, DICT_PATTERN, REG_EXTENDED);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
while (!feof(file)) {
|
|
char *ini_str = NULL, *element_str = NULL, *line = NULL;
|
|
char *elim;
|
|
regmatch_t m[3];
|
|
size_t len;
|
|
|
|
ret = getline(&line, &len, file);
|
|
if (ret < 0) {
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
line_number++;
|
|
|
|
/* eliminate comments */
|
|
elim = strchr(line, '#');
|
|
if (elim)
|
|
*elim = '\0';
|
|
|
|
/* eliminate newline */
|
|
elim = strchr(line, '\n');
|
|
if (elim)
|
|
*elim = '\0';
|
|
|
|
if (!strlen(line))
|
|
goto cont;
|
|
|
|
if (regexec(&r, line, 3, m, 0)) {
|
|
fprintf(stderr, "line %d: invalid syntax: '%s'\n",
|
|
line_number, line);
|
|
|
|
parse_errors++;
|
|
goto cont;
|
|
}
|
|
|
|
ini_str =
|
|
strndup(line + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
|
|
element_str = strndup(line + m[2].rm_so,
|
|
m[2].rm_eo - m[2].rm_so);
|
|
|
|
dict = realloc(dict, ++n_dict_entries *
|
|
sizeof(struct dict_entry));
|
|
if (!dict) {
|
|
free(line);
|
|
ret = -1;
|
|
goto out_free;
|
|
}
|
|
|
|
dict[n_dict_entries - 1].ini_str = ini_str;
|
|
dict[n_dict_entries - 1].element_str = element_str;
|
|
|
|
cont:
|
|
free(line);
|
|
};
|
|
|
|
out_free:
|
|
regfree(&r);
|
|
out:
|
|
if (parse_errors) {
|
|
fprintf(stderr,
|
|
"%d errors found, output file was not generated.\n",
|
|
parse_errors);
|
|
ret = -1;
|
|
}
|
|
|
|
fclose(file);
|
|
return ret;
|
|
}
|
|
|
|
static int parse_text_file(char *conf_buffer, struct structure *structure,
|
|
const char *filename, enum text_file_type type)
|
|
{
|
|
regex_t r;
|
|
FILE *file;
|
|
unsigned int parse_errors = 0, line_number = 0;
|
|
int ret = -1;
|
|
|
|
file = fopen(filename, "r");
|
|
if (!file) {
|
|
fprintf(stderr, "Couldn't open file '%s'\n", filename);
|
|
return -1;
|
|
}
|
|
|
|
if (type == TEXT_FILE_CONF)
|
|
ret = regcomp(&r, TEXT_CONF_PATTERN, REG_EXTENDED);
|
|
else if (type == TEXT_FILE_INI)
|
|
ret = regcomp(&r, TEXT_INI_PATTERN, REG_EXTENDED);
|
|
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
while (!feof(file)) {
|
|
char *element_str = NULL, *line = NULL, *elim;
|
|
char *value_str = NULL, *value_array = NULL;
|
|
regmatch_t m[3];
|
|
struct element *element;
|
|
long int value;
|
|
int pos, i;
|
|
size_t len;
|
|
|
|
ret = getline(&line, &len, file);
|
|
if (ret < 0) {
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
line_number++;
|
|
|
|
/* eliminate comments */
|
|
elim = strchr(line, '#');
|
|
if (elim)
|
|
*elim = '\0';
|
|
|
|
/* eliminate newline */
|
|
elim = strchr(line, '\n');
|
|
if (elim)
|
|
*elim = '\0';
|
|
|
|
if (!strlen(line))
|
|
goto cont;
|
|
|
|
if (regexec(&r, line, 3, m, 0)) {
|
|
fprintf(stderr, "line %d: invalid syntax: '%s'\n",
|
|
line_number, line);
|
|
|
|
parse_errors++;
|
|
goto cont;
|
|
}
|
|
|
|
element_str =
|
|
strndup(line + m[1].rm_so, m[1].rm_eo - m[1].rm_so);
|
|
|
|
value_array = strndup(line + m[2].rm_so, m[2].rm_eo - m[2].rm_so);
|
|
|
|
if (type == TEXT_FILE_INI) {
|
|
ret = translate_ini(&element_str, &value_array);
|
|
if (ret < 0) {
|
|
fprintf(stderr,
|
|
"line %d: couldn't translate INI file: '%s'\n",
|
|
line_number, line);
|
|
parse_errors++;
|
|
goto cont_free;
|
|
}
|
|
}
|
|
|
|
pos = get_element_pos(structure, element_str, &element);
|
|
if (pos < 0) {
|
|
fprintf(stderr, "line %d: couldn't find element %s\n",
|
|
line_number, element_str);
|
|
parse_errors++;
|
|
goto cont_free;
|
|
} else if (element->type >= STRUCT_BASE) {
|
|
fprintf(stderr,
|
|
"line %d: setting entire structures is not supported.\n",
|
|
line_number);
|
|
parse_errors++;
|
|
goto cont_free;
|
|
}
|
|
|
|
i = 0;
|
|
|
|
value_str = strtok(value_array, ",");
|
|
while (value_str) {
|
|
if (++i > element->array_size)
|
|
break;
|
|
value = strtoul(value_str, NULL, 0);
|
|
ret = set_data(element, conf_buffer + pos, &value);
|
|
|
|
pos += types[element->type].size;
|
|
|
|
value_str = strtok(NULL, ",");
|
|
}
|
|
|
|
if (i != element->array_size) {
|
|
fprintf(stderr,
|
|
"line %d: invalid array size, expected %d got %d\n",
|
|
line_number, element->array_size, i);
|
|
parse_errors++;
|
|
goto cont_free;
|
|
}
|
|
|
|
cont_free:
|
|
free(element_str);
|
|
free(value_array);
|
|
|
|
cont:
|
|
free(line);
|
|
};
|
|
|
|
regfree(&r);
|
|
out:
|
|
if (parse_errors) {
|
|
fprintf(stderr,
|
|
"%d errors found, output file was not generated.\n",
|
|
parse_errors);
|
|
ret = -1;
|
|
}
|
|
|
|
fclose(file);
|
|
return ret;
|
|
}
|
|
|
|
static int create_default(const char *conf_filename,
|
|
const char *output_filename,
|
|
void **conf_buf, struct structure *structure)
|
|
{
|
|
int ret;
|
|
|
|
*conf_buf = malloc(structure->size);
|
|
if (!*conf_buf) {
|
|
fprintf(stderr, "Couldn't allocate enough memory (%d)\n",
|
|
structure->size);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
/* set the magic for writing */
|
|
ret = set_value_int(*conf_buf, structure,
|
|
magic,
|
|
DEFAULT_MAGIC_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* set the version for writing */
|
|
ret = set_value_int(*conf_buf, structure,
|
|
version,
|
|
DEFAULT_VERSION_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = parse_text_file(*conf_buf, structure,
|
|
conf_filename, TEXT_FILE_CONF);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* set the checksum for writing */
|
|
ret = set_value_int(*conf_buf, structure,
|
|
calc_crc32(*conf_buf, structure->size),
|
|
DEFAULT_CHKSUM_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = write_file(output_filename, *conf_buf, structure->size);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
out:
|
|
if (ret < 0 && *conf_buf) free(*conf_buf);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#define SHORT_OPTIONS "S:s:b:i:o:g::G:C:I:phXD"
|
|
|
|
struct option long_options[] = {
|
|
{ "binary-struct", required_argument, NULL, 'b' },
|
|
{ "source-struct", required_argument, NULL, 'S' },
|
|
{ "input-config", required_argument, NULL, 'i' },
|
|
{ "output-config", required_argument, NULL, 'o' },
|
|
{ "ignore-checksum", no_argument, NULL, 'X' },
|
|
{ "create-default", no_argument, NULL, 'D' },
|
|
{ "get", optional_argument, NULL, 'g' },
|
|
{ "set", required_argument, NULL, 's' },
|
|
{ "generate-struct", required_argument, NULL, 'G' },
|
|
{ "parse-text-conf", required_argument, NULL, 'C' },
|
|
{ "parse-ini", required_argument, NULL, 'I' },
|
|
{ "print-struct", no_argument, NULL, 'p' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
{ 0, 0, 0, 0 },
|
|
};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
void *header_buf = NULL;
|
|
void *conf_buf = NULL;
|
|
char *header_filename = NULL;
|
|
char *binary_struct_filename = NULL;
|
|
char *input_filename = NULL;
|
|
char *output_filename = NULL;
|
|
char *dict_filename = NULL;
|
|
char *command_arg = NULL;
|
|
struct structure *root_struct;
|
|
int c, ret = 0;
|
|
char command = 0;
|
|
|
|
while (1) {
|
|
c = getopt_long(argc, argv, SHORT_OPTIONS, long_options, NULL);
|
|
|
|
if (c < 0)
|
|
break;
|
|
|
|
switch(c) {
|
|
case 'S':
|
|
header_filename = optarg;
|
|
break;
|
|
|
|
case 'b':
|
|
binary_struct_filename = strdup(optarg);
|
|
break;
|
|
|
|
case 'i':
|
|
input_filename = strdup(optarg);
|
|
break;
|
|
|
|
case 'o':
|
|
output_filename = strdup(optarg);
|
|
break;
|
|
|
|
case 'X':
|
|
ignore_checksum = 1;
|
|
break;
|
|
|
|
case 'D':
|
|
/* Build default configuration bin file (default input) */
|
|
if (output_filename) {
|
|
fprintf(stderr, "Cannot specify output file name with -D\n");
|
|
print_usage(argv[0]);
|
|
exit(-1);
|
|
}
|
|
else
|
|
output_filename = strdup(DEFAULT_INPUT_FILENAME);
|
|
/* Fall through */
|
|
case 'G':
|
|
case 'g':
|
|
case 's':
|
|
case 'C':
|
|
case 'I':
|
|
command_arg = optarg;
|
|
/* Fall through */
|
|
case 'p':
|
|
if (command) {
|
|
fprintf(stderr,
|
|
"Only one command option is allowed, can't use -%c with -%c.\n",
|
|
command, c);
|
|
print_usage(argv[0]);
|
|
exit(-1);
|
|
}
|
|
command = c;
|
|
break;
|
|
|
|
case 'h':
|
|
print_usage(argv[0]);
|
|
exit(0);
|
|
|
|
default:
|
|
print_usage(argv[0]);
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
if (!input_filename)
|
|
input_filename = strdup(DEFAULT_INPUT_FILENAME);
|
|
|
|
if (!dict_filename)
|
|
dict_filename = strdup(DEFAULT_DICT_FILENAME);
|
|
|
|
if (!output_filename)
|
|
output_filename = strdup(DEFAULT_OUTPUT_FILENAME);
|
|
|
|
if (header_filename && binary_struct_filename) {
|
|
fprintf(stderr,
|
|
"Can't specify both source struct and binary struct\n");
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
if (!header_filename && !binary_struct_filename) {
|
|
binary_struct_filename = strdup(DEFAULT_BIN_FILENAME);
|
|
ret = read_binary_struct(binary_struct_filename);
|
|
if (ret < 0)
|
|
goto out;
|
|
}
|
|
|
|
if (binary_struct_filename) {
|
|
ret = read_binary_struct(binary_struct_filename);
|
|
if (ret < 0)
|
|
goto out;
|
|
}
|
|
|
|
if (header_filename) {
|
|
ret = read_file(header_filename, &header_buf, 0);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = parse_header(header_buf);
|
|
if (ret < 0)
|
|
goto out;
|
|
}
|
|
|
|
root_struct = get_struct(DEFAULT_ROOT_STRUCT);
|
|
if (!root_struct) {
|
|
fprintf(stderr,
|
|
"error: root struct (%s) is not defined\n",
|
|
DEFAULT_ROOT_STRUCT);
|
|
ret = -1;
|
|
goto out;
|
|
}
|
|
|
|
switch (command) {
|
|
case 'D':
|
|
/* Generate default configuration bin file */
|
|
ret = create_default(DEFAULT_CONF_FILENAME, output_filename,
|
|
&conf_buf, root_struct);
|
|
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
break;
|
|
case 'G':
|
|
if (!header_buf) {
|
|
fprintf(stderr, "Source struct file must be specified.\n");
|
|
ret = -1;
|
|
break;
|
|
}
|
|
|
|
ret = generate_struct(command_arg);
|
|
break;
|
|
|
|
case 'g':
|
|
ret = read_input(input_filename, &conf_buf, root_struct);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
get_value(conf_buf, root_struct, command_arg);
|
|
break;
|
|
|
|
case 's':
|
|
ret = read_input(input_filename, &conf_buf, root_struct);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = set_value(conf_buf, root_struct, command_arg);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* update the checksum for writing */
|
|
ret = set_value_int(conf_buf, root_struct,
|
|
calc_crc32(conf_buf, root_struct->size),
|
|
DEFAULT_CHKSUM_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = write_file(output_filename, conf_buf, root_struct->size);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
ret = read_input(input_filename, &conf_buf, root_struct);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = parse_text_file(conf_buf, root_struct,
|
|
command_arg, TEXT_FILE_CONF);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* update the checksum for writing */
|
|
ret = set_value_int(conf_buf, root_struct,
|
|
calc_crc32(conf_buf, root_struct->size),
|
|
DEFAULT_CHKSUM_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = write_file(output_filename, conf_buf, root_struct->size);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
ret = read_input(input_filename, &conf_buf, root_struct);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = parse_dict(dict_filename);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = parse_text_file(conf_buf, root_struct,
|
|
command_arg, TEXT_FILE_INI);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/* update the checksum for writing */
|
|
ret = set_value_int(conf_buf, root_struct,
|
|
calc_crc32(conf_buf, root_struct->size),
|
|
DEFAULT_CHKSUM_ELEMENT);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
ret = write_file(output_filename, conf_buf, root_struct->size);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
get_value(NULL, root_struct, NULL);
|
|
break;
|
|
|
|
default:
|
|
print_usage(argv[0]);
|
|
break;
|
|
}
|
|
|
|
free_file(header_buf);
|
|
free_file(conf_buf);
|
|
|
|
free_structs();
|
|
free_dict();
|
|
out:
|
|
free(input_filename);
|
|
free(output_filename);
|
|
free(dict_filename);
|
|
free(binary_struct_filename);
|
|
|
|
exit(ret);
|
|
}
|