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