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