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