1*02c801a5SLawrence Tang /** 2*02c801a5SLawrence Tang * A user-space application linking to the CPER-JSON conversion library which allows for easy 3*02c801a5SLawrence Tang * conversion between CPER and CPER-JSON formats. 4*02c801a5SLawrence Tang * 5*02c801a5SLawrence Tang * Author: Lawrence.Tang@arm.com 6*02c801a5SLawrence Tang **/ 7*02c801a5SLawrence Tang 8*02c801a5SLawrence Tang #include <stdio.h> 9*02c801a5SLawrence Tang #include <string.h> 10*02c801a5SLawrence Tang #include <libgen.h> 11*02c801a5SLawrence Tang #include <limits.h> 12*02c801a5SLawrence Tang #include "json.h" 13*02c801a5SLawrence Tang #include "../cper-parse.h" 14*02c801a5SLawrence Tang #include "../json-schema.h" 15*02c801a5SLawrence Tang 16*02c801a5SLawrence Tang void cper_to_json(int argc, char* argv[]); 17*02c801a5SLawrence Tang void json_to_cper(int argc, char* argv[]); 18*02c801a5SLawrence Tang void print_help(void); 19*02c801a5SLawrence Tang 20*02c801a5SLawrence Tang int main(int argc, char* argv[]) 21*02c801a5SLawrence Tang { 22*02c801a5SLawrence Tang //Ensure at least one argument is present. 23*02c801a5SLawrence Tang if (argc < 2) 24*02c801a5SLawrence Tang { 25*02c801a5SLawrence Tang printf("Invalid number of arguments. See 'cper-convert --help' for command information.\n"); 26*02c801a5SLawrence Tang return -1; 27*02c801a5SLawrence Tang } 28*02c801a5SLawrence Tang 29*02c801a5SLawrence Tang //Run the requested command. 30*02c801a5SLawrence Tang if (strcmp(argv[1], "to-json") == 0) 31*02c801a5SLawrence Tang cper_to_json(argc, argv); 32*02c801a5SLawrence Tang else if (strcmp(argv[1], "to-cper") == 0) 33*02c801a5SLawrence Tang json_to_cper(argc, argv); 34*02c801a5SLawrence Tang else if (strcmp(argv[1], "--help") == 0) 35*02c801a5SLawrence Tang print_help(); 36*02c801a5SLawrence Tang else 37*02c801a5SLawrence Tang { 38*02c801a5SLawrence Tang printf("Unrecognised argument '%s'. See 'cper-convert --help' for command information.\n", argv[1]); 39*02c801a5SLawrence Tang return -1; 40*02c801a5SLawrence Tang } 41*02c801a5SLawrence Tang 42*02c801a5SLawrence Tang return 0; 43*02c801a5SLawrence Tang } 44*02c801a5SLawrence Tang 45*02c801a5SLawrence Tang //Command for converting a provided CPER log file into JSON. 46*02c801a5SLawrence Tang void cper_to_json(int argc, char* argv[]) 47*02c801a5SLawrence Tang { 48*02c801a5SLawrence Tang if (argc < 3) 49*02c801a5SLawrence Tang { 50*02c801a5SLawrence Tang printf("Insufficient number of arguments for 'to-json'. See 'cper-convert --help' for command information.\n"); 51*02c801a5SLawrence Tang return; 52*02c801a5SLawrence Tang } 53*02c801a5SLawrence Tang 54*02c801a5SLawrence Tang //Get a handle for the log file. 55*02c801a5SLawrence Tang FILE* cper_file = fopen(argv[2], "r"); 56*02c801a5SLawrence Tang if (cper_file == NULL) 57*02c801a5SLawrence Tang { 58*02c801a5SLawrence Tang printf("Could not open provided CPER file '%s', file handle returned null.\n", argv[2]); 59*02c801a5SLawrence Tang return; 60*02c801a5SLawrence Tang } 61*02c801a5SLawrence Tang 62*02c801a5SLawrence Tang //Convert. 63*02c801a5SLawrence Tang json_object* ir = cper_to_ir(cper_file); 64*02c801a5SLawrence Tang fclose(cper_file); 65*02c801a5SLawrence Tang const char* json_output = json_object_to_json_string_ext(ir, JSON_C_TO_STRING_PRETTY); 66*02c801a5SLawrence Tang 67*02c801a5SLawrence Tang //Check whether there is a "--out" argument, if there is, then output to file instead. 68*02c801a5SLawrence Tang //Otherwise, just send to console. 69*02c801a5SLawrence Tang if (argc != 5) 70*02c801a5SLawrence Tang { 71*02c801a5SLawrence Tang printf("%s\n", json_output); 72*02c801a5SLawrence Tang return; 73*02c801a5SLawrence Tang } 74*02c801a5SLawrence Tang 75*02c801a5SLawrence Tang //File out argument exists. Argument valid? 76*02c801a5SLawrence Tang if (strcmp(argv[3], "--out") != 0) 77*02c801a5SLawrence Tang { 78*02c801a5SLawrence Tang printf("Invalid argument '%s' for command 'to-json'. See 'cper-convert --help' for command information.\n", argv[3]); 79*02c801a5SLawrence Tang return; 80*02c801a5SLawrence Tang } 81*02c801a5SLawrence Tang 82*02c801a5SLawrence Tang //Try to open a file handle to the desired output file. 83*02c801a5SLawrence Tang FILE* json_file = fopen(argv[4], "w"); 84*02c801a5SLawrence Tang if (json_file == NULL) 85*02c801a5SLawrence Tang { 86*02c801a5SLawrence Tang printf("Could not get a handle for output file '%s', file handle returned null.\n", argv[4]); 87*02c801a5SLawrence Tang return; 88*02c801a5SLawrence Tang } 89*02c801a5SLawrence Tang 90*02c801a5SLawrence Tang //Write out to file. 91*02c801a5SLawrence Tang fwrite(json_output, strlen(json_output), 1, json_file); 92*02c801a5SLawrence Tang fclose(json_file); 93*02c801a5SLawrence Tang } 94*02c801a5SLawrence Tang 95*02c801a5SLawrence Tang //Command for converting a provided CPER-JSON JSON file to CPER binary. 96*02c801a5SLawrence Tang void json_to_cper(int argc, char* argv[]) 97*02c801a5SLawrence Tang { 98*02c801a5SLawrence Tang if (argc < 5) 99*02c801a5SLawrence Tang { 100*02c801a5SLawrence Tang printf("Insufficient number of arguments for 'to-cper'. See 'cper-convert --help' for command information.\n"); 101*02c801a5SLawrence Tang return; 102*02c801a5SLawrence Tang } 103*02c801a5SLawrence Tang 104*02c801a5SLawrence Tang //Read JSON IR from file. 105*02c801a5SLawrence Tang json_object* ir = json_object_from_file(argv[2]); 106*02c801a5SLawrence Tang if (ir == NULL) 107*02c801a5SLawrence Tang { 108*02c801a5SLawrence Tang printf("Could not read JSON from file '%s', import returned null.\n", argv[2]); 109*02c801a5SLawrence Tang return; 110*02c801a5SLawrence Tang } 111*02c801a5SLawrence Tang 112*02c801a5SLawrence Tang //Are we skipping validation? 113*02c801a5SLawrence Tang int do_validate = 1; 114*02c801a5SLawrence Tang if (argc == 6) 115*02c801a5SLawrence Tang { 116*02c801a5SLawrence Tang if (strcmp(argv[5], "--no-validate") == 0) 117*02c801a5SLawrence Tang { 118*02c801a5SLawrence Tang do_validate = 0; 119*02c801a5SLawrence Tang } 120*02c801a5SLawrence Tang else 121*02c801a5SLawrence Tang { 122*02c801a5SLawrence Tang printf("Invalid argument '%s' for command 'to-cper'. See 'cper-convert --help' for command information.\n", argv[5]); 123*02c801a5SLawrence Tang return; 124*02c801a5SLawrence Tang } 125*02c801a5SLawrence Tang } 126*02c801a5SLawrence Tang 127*02c801a5SLawrence Tang //Validate the JSON against specification, unless otherwise specified. 128*02c801a5SLawrence Tang if (do_validate) 129*02c801a5SLawrence Tang { 130*02c801a5SLawrence Tang char* specification_path = NULL; 131*02c801a5SLawrence Tang 132*02c801a5SLawrence Tang //If there is another argument pair, it must be a validation specification file path. 133*02c801a5SLawrence Tang if (argc == 7) 134*02c801a5SLawrence Tang { 135*02c801a5SLawrence Tang //Ensure valid argument naming. 136*02c801a5SLawrence Tang if (strcmp(argv[5], "--specification") != 0) 137*02c801a5SLawrence Tang { 138*02c801a5SLawrence Tang printf("Invalid argument '%s' for command 'to-cper'. See 'cper-convert --help' for command information.\n", argv[5]); 139*02c801a5SLawrence Tang return; 140*02c801a5SLawrence Tang } 141*02c801a5SLawrence Tang 142*02c801a5SLawrence Tang specification_path = argv[6]; 143*02c801a5SLawrence Tang } 144*02c801a5SLawrence Tang else if (argc == 5) 145*02c801a5SLawrence Tang { 146*02c801a5SLawrence Tang //Make the specification path the assumed default (application directory + specification/cper-json.json). 147*02c801a5SLawrence Tang specification_path = malloc(PATH_MAX); 148*02c801a5SLawrence Tang char* dir = dirname(argv[0]); 149*02c801a5SLawrence Tang strcpy(specification_path, dir); 150*02c801a5SLawrence Tang strcat(specification_path, "/specification/cper-json.json"); 151*02c801a5SLawrence Tang } 152*02c801a5SLawrence Tang else 153*02c801a5SLawrence Tang { 154*02c801a5SLawrence Tang //Invalid number of arguments. 155*02c801a5SLawrence Tang printf("Invalid number of arguments for command 'to-cper'. See 'cper-convert --help' for command information.\n"); 156*02c801a5SLawrence Tang return; 157*02c801a5SLawrence Tang } 158*02c801a5SLawrence Tang 159*02c801a5SLawrence Tang //Attempt to verify with the the specification. 160*02c801a5SLawrence Tang char* error_message = malloc(JSON_ERROR_MSG_MAX_LEN); 161*02c801a5SLawrence Tang int success = validate_schema_from_file(specification_path, ir, error_message); 162*02c801a5SLawrence Tang 163*02c801a5SLawrence Tang //Free specification path (if necessary). 164*02c801a5SLawrence Tang if (argc == 5) 165*02c801a5SLawrence Tang free(specification_path); 166*02c801a5SLawrence Tang 167*02c801a5SLawrence Tang //If failed, early exit before conversion. 168*02c801a5SLawrence Tang if (!success) 169*02c801a5SLawrence Tang { 170*02c801a5SLawrence Tang printf("JSON format validation failed: %s\n", error_message); 171*02c801a5SLawrence Tang free(error_message); 172*02c801a5SLawrence Tang return; 173*02c801a5SLawrence Tang } 174*02c801a5SLawrence Tang free(error_message); 175*02c801a5SLawrence Tang } 176*02c801a5SLawrence Tang 177*02c801a5SLawrence Tang //Attempt a conversion. 178*02c801a5SLawrence Tang //Open a read for the output file. 179*02c801a5SLawrence Tang FILE* cper_file = fopen(argv[4], "w"); 180*02c801a5SLawrence Tang if (cper_file == NULL) 181*02c801a5SLawrence Tang { 182*02c801a5SLawrence Tang printf("Could not open output file '%s', file handle returned null.\n", argv[4]); 183*02c801a5SLawrence Tang return; 184*02c801a5SLawrence Tang } 185*02c801a5SLawrence Tang 186*02c801a5SLawrence Tang //Run the converter. 187*02c801a5SLawrence Tang ir_to_cper(ir, cper_file); 188*02c801a5SLawrence Tang fclose(cper_file); 189*02c801a5SLawrence Tang } 190*02c801a5SLawrence Tang 191*02c801a5SLawrence Tang //Command for printing help information. 192*02c801a5SLawrence Tang void print_help(void) 193*02c801a5SLawrence Tang { 194*02c801a5SLawrence Tang printf(":: to-json cper.file [--out file.name]\n"); 195*02c801a5SLawrence Tang printf("\tConverts the provided CPER log file into JSON, by default outputting to console. If '--out' is specified,\n"); 196*02c801a5SLawrence Tang printf("\tThe outputted JSON will be written to the provided file name instead.\n"); 197*02c801a5SLawrence Tang printf("\n:: to-cper cper.json --out file.name [--no-validate] [--specification some/spec/path.json]\n"); 198*02c801a5SLawrence Tang printf("\tConverts the provided CPER-JSON JSON file into CPER binary. An output file must be specified with '--out'.\n"); 199*02c801a5SLawrence Tang printf("\tBy default, the provided JSON will try to be validated against a specification. If no specification file path\n"); 200*02c801a5SLawrence Tang printf("\tis provided with '--specification', then it will default to 'argv[0] + /specification/cper-json.json'.\n"); 201*02c801a5SLawrence Tang printf("\tIf the '--no-validate' argument is set, then the provided JSON will not be validated. Be warned, this may cause\n"); 202*02c801a5SLawrence Tang printf("\tpremature exit/unexpected behaviour in CPER output.\n"); 203*02c801a5SLawrence Tang printf("\n:: --help\n"); 204*02c801a5SLawrence Tang printf("\tDisplays help information to the console.\n"); 205*02c801a5SLawrence Tang }