xref: /openbmc/libcper/cli-app/cper-convert.c (revision 02c801a5)
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     {
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.
46 void 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.
96 void 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.
192 void 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");
205 }