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