102c801a5SLawrence Tang /** 202c801a5SLawrence Tang * A user-space application linking to the CPER-JSON conversion library which allows for easy 302c801a5SLawrence Tang * conversion between CPER and CPER-JSON formats. 402c801a5SLawrence Tang * 502c801a5SLawrence Tang * Author: Lawrence.Tang@arm.com 602c801a5SLawrence Tang **/ 702c801a5SLawrence Tang 802c801a5SLawrence Tang #include <stdio.h> 902c801a5SLawrence Tang #include <string.h> 1002c801a5SLawrence Tang #include <libgen.h> 1102c801a5SLawrence Tang #include <limits.h> 1202c801a5SLawrence Tang #include "json.h" 1302c801a5SLawrence Tang #include "../cper-parse.h" 1402c801a5SLawrence Tang #include "../json-schema.h" 1502c801a5SLawrence Tang 1602c801a5SLawrence Tang void cper_to_json(int argc, char *argv[]); 1702c801a5SLawrence Tang void json_to_cper(int argc, char *argv[]); 1802c801a5SLawrence Tang void print_help(void); 1902c801a5SLawrence Tang 2002c801a5SLawrence Tang int main(int argc, char *argv[]) 2102c801a5SLawrence Tang { 2202c801a5SLawrence Tang //Ensure at least one argument is present. 23e407b4c8SLawrence Tang if (argc < 2) { 2402c801a5SLawrence Tang printf("Invalid number of arguments. See 'cper-convert --help' for command information.\n"); 2502c801a5SLawrence Tang return -1; 2602c801a5SLawrence Tang } 2702c801a5SLawrence Tang 28*71c70a3dSLawrence Tang //Parse the command line arguments. 29*71c70a3dSLawrence Tang char* input_file = NULL; 30*71c70a3dSLawrence Tang char* output_file = NULL; 31*71c70a3dSLawrence Tang 3202c801a5SLawrence Tang //Run the requested command. 3302c801a5SLawrence Tang if (strcmp(argv[1], "to-json") == 0) 3402c801a5SLawrence Tang cper_to_json(argc, argv); 3502c801a5SLawrence Tang else if (strcmp(argv[1], "to-cper") == 0) 3602c801a5SLawrence Tang json_to_cper(argc, argv); 3702c801a5SLawrence Tang else if (strcmp(argv[1], "--help") == 0) 3802c801a5SLawrence Tang print_help(); 39e407b4c8SLawrence Tang else { 40e407b4c8SLawrence Tang printf("Unrecognised argument '%s'. See 'cper-convert --help' for command information.\n", 41e407b4c8SLawrence Tang argv[1]); 4202c801a5SLawrence Tang return -1; 4302c801a5SLawrence Tang } 4402c801a5SLawrence Tang 4502c801a5SLawrence Tang return 0; 4602c801a5SLawrence Tang } 4702c801a5SLawrence Tang 4802c801a5SLawrence Tang //Command for converting a provided CPER log file into JSON. 4902c801a5SLawrence Tang void cper_to_json(int argc, char *argv[]) 5002c801a5SLawrence Tang { 51e407b4c8SLawrence Tang if (argc < 3) { 5202c801a5SLawrence Tang printf("Insufficient number of arguments for 'to-json'. See 'cper-convert --help' for command information.\n"); 5302c801a5SLawrence Tang return; 5402c801a5SLawrence Tang } 5502c801a5SLawrence Tang 5602c801a5SLawrence Tang //Get a handle for the log file. 5702c801a5SLawrence Tang FILE *cper_file = fopen(argv[2], "r"); 58e407b4c8SLawrence Tang if (cper_file == NULL) { 59e407b4c8SLawrence Tang printf("Could not open provided CPER file '%s', file handle returned null.\n", 60e407b4c8SLawrence Tang argv[2]); 6102c801a5SLawrence Tang return; 6202c801a5SLawrence Tang } 6302c801a5SLawrence Tang 6402c801a5SLawrence Tang //Convert. 6502c801a5SLawrence Tang json_object *ir = cper_to_ir(cper_file); 6602c801a5SLawrence Tang fclose(cper_file); 67e407b4c8SLawrence Tang const char *json_output = 68e407b4c8SLawrence Tang json_object_to_json_string_ext(ir, JSON_C_TO_STRING_PRETTY); 6902c801a5SLawrence Tang 7002c801a5SLawrence Tang //Check whether there is a "--out" argument, if there is, then output to file instead. 7102c801a5SLawrence Tang //Otherwise, just send to console. 72e407b4c8SLawrence Tang if (argc != 5) { 7302c801a5SLawrence Tang printf("%s\n", json_output); 7402c801a5SLawrence Tang return; 7502c801a5SLawrence Tang } 7602c801a5SLawrence Tang 7702c801a5SLawrence Tang //File out argument exists. Argument valid? 78e407b4c8SLawrence Tang if (strcmp(argv[3], "--out") != 0) { 79e407b4c8SLawrence Tang printf("Invalid argument '%s' for command 'to-json'. See 'cper-convert --help' for command information.\n", 80e407b4c8SLawrence Tang argv[3]); 8102c801a5SLawrence Tang return; 8202c801a5SLawrence Tang } 8302c801a5SLawrence Tang 8402c801a5SLawrence Tang //Try to open a file handle to the desired output file. 8502c801a5SLawrence Tang FILE *json_file = fopen(argv[4], "w"); 86e407b4c8SLawrence Tang if (json_file == NULL) { 87e407b4c8SLawrence Tang printf("Could not get a handle for output file '%s', file handle returned null.\n", 88e407b4c8SLawrence Tang argv[4]); 8902c801a5SLawrence Tang return; 9002c801a5SLawrence Tang } 9102c801a5SLawrence Tang 9202c801a5SLawrence Tang //Write out to file. 9302c801a5SLawrence Tang fwrite(json_output, strlen(json_output), 1, json_file); 9402c801a5SLawrence Tang fclose(json_file); 9502c801a5SLawrence Tang } 9602c801a5SLawrence Tang 9702c801a5SLawrence Tang //Command for converting a provided CPER-JSON JSON file to CPER binary. 9802c801a5SLawrence Tang void json_to_cper(int argc, char *argv[]) 9902c801a5SLawrence Tang { 100e407b4c8SLawrence Tang if (argc < 5) { 10102c801a5SLawrence Tang printf("Insufficient number of arguments for 'to-cper'. See 'cper-convert --help' for command information.\n"); 10202c801a5SLawrence Tang return; 10302c801a5SLawrence Tang } 10402c801a5SLawrence Tang 10502c801a5SLawrence Tang //Read JSON IR from file. 10602c801a5SLawrence Tang json_object *ir = json_object_from_file(argv[2]); 107e407b4c8SLawrence Tang if (ir == NULL) { 108e407b4c8SLawrence Tang printf("Could not read JSON from file '%s', import returned null.\n", 109e407b4c8SLawrence Tang argv[2]); 11002c801a5SLawrence Tang return; 11102c801a5SLawrence Tang } 11202c801a5SLawrence Tang 11302c801a5SLawrence Tang //Are we skipping validation? 11402c801a5SLawrence Tang int do_validate = 1; 115e407b4c8SLawrence Tang if (argc >= 6 && argc < 8) { 116e407b4c8SLawrence Tang if (strcmp(argv[5], "--no-validate") == 0) { 11702c801a5SLawrence Tang do_validate = 0; 11802c801a5SLawrence Tang } 11902c801a5SLawrence Tang } 12002c801a5SLawrence Tang 12102c801a5SLawrence Tang //Validate the JSON against specification, unless otherwise specified. 122e407b4c8SLawrence Tang if (do_validate) { 12302c801a5SLawrence Tang char *specification_path = NULL; 12402c801a5SLawrence Tang 125d34f2b11SLawrence Tang //Is there a specification file path? 126e407b4c8SLawrence Tang if (argc >= 7 && 127e407b4c8SLawrence Tang strcmp(argv[argc - 2], "--specification") == 0) { 128d34f2b11SLawrence Tang specification_path = argv[argc - 1]; 129e407b4c8SLawrence Tang } else { 13002c801a5SLawrence Tang //Make the specification path the assumed default (application directory + specification/cper-json.json). 13102c801a5SLawrence Tang specification_path = malloc(PATH_MAX); 13202c801a5SLawrence Tang char *dir = dirname(argv[0]); 13302c801a5SLawrence Tang strcpy(specification_path, dir); 134e407b4c8SLawrence Tang strcat(specification_path, 135e407b4c8SLawrence Tang "/specification/cper-json.json"); 13602c801a5SLawrence Tang } 137d34f2b11SLawrence Tang 138d34f2b11SLawrence Tang //Enable debug mode if indicated. 139e407b4c8SLawrence Tang for (int i = 5; i < argc; i++) { 140e407b4c8SLawrence Tang if (strcmp(argv[i], "--debug") == 0) { 141d34f2b11SLawrence Tang validate_schema_debug_enable(); 142d34f2b11SLawrence Tang printf("debug enabled.\n"); 143d34f2b11SLawrence Tang break; 144d34f2b11SLawrence Tang } 14502c801a5SLawrence Tang } 14602c801a5SLawrence Tang 14702c801a5SLawrence Tang //Attempt to verify with the the specification. 14802c801a5SLawrence Tang char *error_message = malloc(JSON_ERROR_MSG_MAX_LEN); 149e407b4c8SLawrence Tang int success = validate_schema_from_file(specification_path, ir, 150e407b4c8SLawrence Tang error_message); 15102c801a5SLawrence Tang 15202c801a5SLawrence Tang //Free specification path (if necessary). 15302c801a5SLawrence Tang if (argc == 5) 15402c801a5SLawrence Tang free(specification_path); 15502c801a5SLawrence Tang 15602c801a5SLawrence Tang //If failed, early exit before conversion. 157e407b4c8SLawrence Tang if (!success) { 158e407b4c8SLawrence Tang printf("JSON format validation failed: %s\n", 159e407b4c8SLawrence Tang error_message); 16002c801a5SLawrence Tang free(error_message); 16102c801a5SLawrence Tang return; 16202c801a5SLawrence Tang } 16302c801a5SLawrence Tang free(error_message); 16402c801a5SLawrence Tang } 16502c801a5SLawrence Tang 16602c801a5SLawrence Tang //Attempt a conversion. 16702c801a5SLawrence Tang //Open a read for the output file. 16802c801a5SLawrence Tang FILE *cper_file = fopen(argv[4], "w"); 169e407b4c8SLawrence Tang if (cper_file == NULL) { 170e407b4c8SLawrence Tang printf("Could not open output file '%s', file handle returned null.\n", 171e407b4c8SLawrence Tang argv[4]); 17202c801a5SLawrence Tang return; 17302c801a5SLawrence Tang } 17402c801a5SLawrence Tang 17502c801a5SLawrence Tang //Run the converter. 17602c801a5SLawrence Tang ir_to_cper(ir, cper_file); 17702c801a5SLawrence Tang fclose(cper_file); 17802c801a5SLawrence Tang } 17902c801a5SLawrence Tang 18002c801a5SLawrence Tang //Command for printing help information. 18102c801a5SLawrence Tang void print_help(void) 18202c801a5SLawrence Tang { 18302c801a5SLawrence Tang printf(":: to-json cper.file [--out file.name]\n"); 18402c801a5SLawrence Tang printf("\tConverts the provided CPER log file into JSON, by default outputting to console. If '--out' is specified,\n"); 18502c801a5SLawrence Tang printf("\tThe outputted JSON will be written to the provided file name instead.\n"); 186d34f2b11SLawrence Tang printf("\n:: to-cper cper.json --out file.name [--no-validate] [--debug] [--specification some/spec/path.json]\n"); 18702c801a5SLawrence Tang printf("\tConverts the provided CPER-JSON JSON file into CPER binary. An output file must be specified with '--out'.\n"); 18802c801a5SLawrence Tang printf("\tBy default, the provided JSON will try to be validated against a specification. If no specification file path\n"); 18902c801a5SLawrence Tang printf("\tis provided with '--specification', then it will default to 'argv[0] + /specification/cper-json.json'.\n"); 19002c801a5SLawrence Tang printf("\tIf the '--no-validate' argument is set, then the provided JSON will not be validated. Be warned, this may cause\n"); 19102c801a5SLawrence Tang printf("\tpremature exit/unexpected behaviour in CPER output.\n"); 19202c801a5SLawrence Tang printf("\n:: --help\n"); 19302c801a5SLawrence Tang printf("\tDisplays help information to the console.\n"); 19402c801a5SLawrence Tang }