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