blob: ba1908d4bbe3ce3ddc65466a4e0d41e2dfaba22c [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
16void cper_to_json(int argc, char* argv[]);
17void json_to_cper(int argc, char* argv[]);
18void print_help(void);
19
20int 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.
46void 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.
96void 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)
115 {
116 if (strcmp(argv[5], "--no-validate") == 0)
117 {
118 do_validate = 0;
119 }
120 else
121 {
122 printf("Invalid argument '%s' for command 'to-cper'. See 'cper-convert --help' for command information.\n", argv[5]);
123 return;
124 }
125 }
126
127 //Validate the JSON against specification, unless otherwise specified.
128 if (do_validate)
129 {
130 char* specification_path = NULL;
131
132 //If there is another argument pair, it must be a validation specification file path.
133 if (argc == 7)
134 {
135 //Ensure valid argument naming.
136 if (strcmp(argv[5], "--specification") != 0)
137 {
138 printf("Invalid argument '%s' for command 'to-cper'. See 'cper-convert --help' for command information.\n", argv[5]);
139 return;
140 }
141
142 specification_path = argv[6];
143 }
144 else if (argc == 5)
145 {
146 //Make the specification path the assumed default (application directory + specification/cper-json.json).
147 specification_path = malloc(PATH_MAX);
148 char* dir = dirname(argv[0]);
149 strcpy(specification_path, dir);
150 strcat(specification_path, "/specification/cper-json.json");
151 }
152 else
153 {
154 //Invalid number of arguments.
155 printf("Invalid number of arguments for command 'to-cper'. See 'cper-convert --help' for command information.\n");
156 return;
157 }
158
159 //Attempt to verify with the the specification.
160 char* error_message = malloc(JSON_ERROR_MSG_MAX_LEN);
161 int success = validate_schema_from_file(specification_path, ir, error_message);
162
163 //Free specification path (if necessary).
164 if (argc == 5)
165 free(specification_path);
166
167 //If failed, early exit before conversion.
168 if (!success)
169 {
170 printf("JSON format validation failed: %s\n", error_message);
171 free(error_message);
172 return;
173 }
174 free(error_message);
175 }
176
177 //Attempt a conversion.
178 //Open a read for the output file.
179 FILE* cper_file = fopen(argv[4], "w");
180 if (cper_file == NULL)
181 {
182 printf("Could not open output file '%s', file handle returned null.\n", argv[4]);
183 return;
184 }
185
186 //Run the converter.
187 ir_to_cper(ir, cper_file);
188 fclose(cper_file);
189}
190
191//Command for printing help information.
192void print_help(void)
193{
194 printf(":: to-json cper.file [--out file.name]\n");
195 printf("\tConverts the provided CPER log file into JSON, by default outputting to console. If '--out' is specified,\n");
196 printf("\tThe outputted JSON will be written to the provided file name instead.\n");
197 printf("\n:: to-cper cper.json --out file.name [--no-validate] [--specification some/spec/path.json]\n");
198 printf("\tConverts the provided CPER-JSON JSON file into CPER binary. An output file must be specified with '--out'.\n");
199 printf("\tBy default, the provided JSON will try to be validated against a specification. If no specification file path\n");
200 printf("\tis provided with '--specification', then it will default to 'argv[0] + /specification/cper-json.json'.\n");
201 printf("\tIf the '--no-validate' argument is set, then the provided JSON will not be validated. Be warned, this may cause\n");
202 printf("\tpremature exit/unexpected behaviour in CPER output.\n");
203 printf("\n:: --help\n");
204 printf("\tDisplays help information to the console.\n");
Lawrence Tang4ef0a0a2022-07-18 10:50:58 +0100205}