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