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 <libcper/log.h> 14 #include <libcper/cper-parse.h> 15 #include <libcper/json-schema.h> 16 17 void cper_to_json(char *in_file, char *out_file, int is_single_section); 18 void json_to_cper(const char *in_file, const char *out_file); 19 void print_help(void); 20 21 int main(int argc, char *argv[]) 22 { 23 cper_set_log_stdio(); 24 //Print help if requested. 25 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 26 print_help(); 27 return 0; 28 } 29 30 //Ensure at least two arguments are present. 31 if (argc < 3) { 32 printf("Invalid number of arguments. See 'cper-convert --help' for command information.\n"); 33 return -1; 34 } 35 36 //Parse the command line arguments. 37 char *input_file = argv[2]; 38 char *output_file = NULL; 39 char *specification_file = NULL; 40 int no_validate = 0; 41 int debug = 0; 42 for (int i = 3; i < argc; i++) { 43 if (strcmp(argv[i], "--out") == 0 && i < argc - 1) { 44 //Output file. 45 output_file = argv[i + 1]; 46 i++; 47 } else if (strcmp(argv[i], "--specification") == 0 && 48 i < argc - 1) { 49 //Specification file. 50 specification_file = argv[i + 1]; 51 i++; 52 } else if (strcmp(argv[i], "--no-validate") == 0) { 53 //No validation to be used. 54 //Invalidates specification file. 55 specification_file = NULL; 56 no_validate = 1; 57 } else if (strcmp(argv[i], "--debug") == 0) { 58 //Debug output on. 59 debug = 1; 60 } else { 61 printf("Unrecognised argument '%s'. See 'cper-convert --help' for command information.\n", 62 argv[i]); 63 } 64 } 65 66 // Debug is not used at the moment. Leave for compatibility. 67 (void)debug; 68 (void)no_validate; 69 (void)specification_file; 70 //Run the requested command. 71 if (strcmp(argv[1], "to-json") == 0) { 72 cper_to_json(input_file, output_file, 0); 73 } else if (strcmp(argv[1], "to-json-section") == 0) { 74 cper_to_json(input_file, output_file, 1); 75 } else if (strcmp(argv[1], "to-cper") == 0) { 76 json_to_cper(input_file, output_file); 77 } else { 78 printf("Unrecognised argument '%s'. See 'cper-convert --help' for command information.\n", 79 argv[1]); 80 return -1; 81 } 82 83 return 0; 84 } 85 86 //Command for converting a provided CPER log file or CPER single section file into JSON. 87 void cper_to_json(char *in_file, char *out_file, int is_single_section) 88 { 89 //Get a handle for the log file. 90 FILE *cper_file = fopen(in_file, "r"); 91 if (cper_file == NULL) { 92 printf("Could not open provided CPER file '%s', file handle returned null.\n", 93 in_file); 94 return; 95 } 96 97 //Convert. 98 json_object *ir; 99 if (is_single_section) { 100 ir = cper_single_section_to_ir(cper_file); 101 } else { 102 ir = cper_to_ir(cper_file); 103 } 104 fclose(cper_file); 105 106 //Output to string. 107 const char *json_output = 108 json_object_to_json_string_ext(ir, JSON_C_TO_STRING_PRETTY); 109 110 //Check whether there is a "--out" argument, if there is, then output to file instead. 111 //Otherwise, just send to console. 112 if (out_file == NULL) { 113 printf("%s\n", json_output); 114 return; 115 } 116 117 //Try to open a file handle to the desired output file. 118 FILE *json_file = fopen(out_file, "w"); 119 if (json_file == NULL) { 120 printf("Could not get a handle for output file '%s', file handle returned null.\n", 121 out_file); 122 return; 123 } 124 125 //Write out to file. 126 fwrite(json_output, strlen(json_output), 1, json_file); 127 fclose(json_file); 128 } 129 130 //Command for converting a provided CPER-JSON JSON file to CPER binary. 131 void json_to_cper(const char *in_file, const char *out_file) 132 { 133 //Verify output file exists. 134 if (out_file == NULL) { 135 printf("No output file provided for 'to-cper'. See 'cper-convert --help' for command information.\n"); 136 return; 137 } 138 139 //Read JSON IR from file. 140 json_object *ir = json_object_from_file(in_file); 141 if (ir == NULL) { 142 printf("Could not read JSON from file '%s', import returned null.\n", 143 in_file); 144 return; 145 } 146 147 //Open a read for the output file. 148 FILE *cper_file = fopen(out_file, "w"); 149 if (cper_file == NULL) { 150 printf("Could not open output file '%s', file handle returned null.\n", 151 out_file); 152 json_object_put(ir); 153 return; 154 } 155 156 //Detect the type of CPER (full log, single section) from the IR given. 157 //Run the converter accordingly. 158 if (json_object_object_get(ir, "header") != NULL) { 159 ir_to_cper(ir, cper_file); 160 } else { 161 ir_single_section_to_cper(ir, cper_file); 162 } 163 fclose(cper_file); 164 json_object_put(ir); 165 } 166 167 //Command for printing help information. 168 void print_help(void) 169 { 170 printf(":: to-json cper.file [--out file.name]\n"); 171 printf("\tConverts the provided CPER log file into JSON, by default writing to stdout. If '--out' is specified,\n"); 172 printf("\tThe outputted JSON will be written to the provided file name instead.\n"); 173 printf("\n:: to-json-section cper.section.file [--out file.name]\n"); 174 printf("\tConverts the provided single CPER section descriptor & section file into JSON, by default writing to stdout.\n"); 175 printf("\tOtherwise behaves the same as 'to-json'.\n"); 176 printf("\n:: to-cper cper.json --out file.name [--no-validate] [--debug] [--specification some/spec/path.json]\n"); 177 printf("\tConverts the provided CPER-JSON JSON file into CPER binary. An output file must be specified with '--out'.\n"); 178 printf("\tWill automatically detect whether the JSON passed is a single section, or a whole file,\n"); 179 printf("\tand output binary accordingly.\n\n"); 180 printf("\tBy default, the provided JSON will try to be validated against a specification. If no specification file path\n"); 181 printf("\tis provided with '--specification', then it will default to 'argv[0] + /specification/cper-json.json'.\n"); 182 printf("\tIf the '--no-validate' argument is set, then the provided JSON will not be validated. Be warned, this may cause\n"); 183 printf("\tpremature exit/unexpected behaviour in CPER output.\n\n"); 184 printf("\tIf '--debug' is set, then debug output for JSON specification parsing will be printed to stdout.\n"); 185 printf("\n:: --help\n"); 186 printf("\tDisplays help information to the console.\n"); 187 } 188