blob: d1db4d2acdc9b281f8b5c8fbe6bbeb303ab2039b [file] [log] [blame]
Lawrence Tangb8fa2f72022-07-18 10:50:19 +01001/**
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
Lawrence Tange407b4c2022-07-21 13:54:01 +010016void cper_to_json(int argc, char *argv[]);
17void json_to_cper(int argc, char *argv[]);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010018void print_help(void);
19
Lawrence Tange407b4c2022-07-21 13:54:01 +010020int main(int argc, char *argv[])
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010021{
Lawrence Tange407b4c2022-07-21 13:54:01 +010022 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010027
Lawrence Tang71c70a32022-08-08 09:16:06 +010028 //Parse the command line arguments.
29 char* input_file = NULL;
30 char* output_file = NULL;
31
Lawrence Tange407b4c2022-07-21 13:54:01 +010032 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010044
Lawrence Tange407b4c2022-07-21 13:54:01 +010045 return 0;
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010046}
47
48//Command for converting a provided CPER log file into JSON.
Lawrence Tange407b4c2022-07-21 13:54:01 +010049void cper_to_json(int argc, char *argv[])
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010050{
Lawrence Tange407b4c2022-07-21 13:54:01 +010051 if (argc < 3) {
52 printf("Insufficient number of arguments for 'to-json'. See 'cper-convert --help' for command information.\n");
53 return;
54 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010055
Lawrence Tange407b4c2022-07-21 13:54:01 +010056 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010063
Lawrence Tange407b4c2022-07-21 13:54:01 +010064 //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);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010069
Lawrence Tange407b4c2022-07-21 13:54:01 +010070 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010076
Lawrence Tange407b4c2022-07-21 13:54:01 +010077 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010083
Lawrence Tange407b4c2022-07-21 13:54:01 +010084 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010091
Lawrence Tange407b4c2022-07-21 13:54:01 +010092 //Write out to file.
93 fwrite(json_output, strlen(json_output), 1, json_file);
94 fclose(json_file);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010095}
96
97//Command for converting a provided CPER-JSON JSON file to CPER binary.
Lawrence Tange407b4c2022-07-21 13:54:01 +010098void json_to_cper(int argc, char *argv[])
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010099{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100100 if (argc < 5) {
101 printf("Insufficient number of arguments for 'to-cper'. See 'cper-convert --help' for command information.\n");
102 return;
103 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100104
Lawrence Tange407b4c2022-07-21 13:54:01 +0100105 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100112
Lawrence Tange407b4c2022-07-21 13:54:01 +0100113 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100120
Lawrence Tange407b4c2022-07-21 13:54:01 +0100121 //Validate the JSON against specification, unless otherwise specified.
122 if (do_validate) {
123 char *specification_path = NULL;
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100124
Lawrence Tange407b4c2022-07-21 13:54:01 +0100125 //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 }
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100137
Lawrence Tange407b4c2022-07-21 13:54:01 +0100138 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100146
Lawrence Tange407b4c2022-07-21 13:54:01 +0100147 //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);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100151
Lawrence Tange407b4c2022-07-21 13:54:01 +0100152 //Free specification path (if necessary).
153 if (argc == 5)
154 free(specification_path);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100155
Lawrence Tange407b4c2022-07-21 13:54:01 +0100156 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100165
Lawrence Tange407b4c2022-07-21 13:54:01 +0100166 //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 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100174
Lawrence Tange407b4c2022-07-21 13:54:01 +0100175 //Run the converter.
176 ir_to_cper(ir, cper_file);
177 fclose(cper_file);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100178}
179
180//Command for printing help information.
181void print_help(void)
182{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100183 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");
Lawrence Tang4ef0a0a2022-07-18 10:50:58 +0100194}