blob: 488b6c9100bfe4dd0b001f13d2adceddfe7db9fd [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;
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100114 if (argc >= 6 && argc < 8)
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100115 {
116 if (strcmp(argv[5], "--no-validate") == 0)
117 {
118 do_validate = 0;
119 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100120 }
121
122 //Validate the JSON against specification, unless otherwise specified.
123 if (do_validate)
124 {
125 char* specification_path = NULL;
126
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100127 //Is there a specification file path?
128 if (argc >= 7 && strcmp(argv[argc - 2], "--specification") == 0)
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100129 {
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100130 specification_path = argv[argc - 1];
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100131 }
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100132 else
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100133 {
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 }
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100140
141 //Enable debug mode if indicated.
142 for (int i=5; i<argc; i++)
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100143 {
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100144 if (strcmp(argv[i], "--debug") == 0)
145 {
146 validate_schema_debug_enable();
147 printf("debug enabled.\n");
148 break;
149 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100150 }
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.
185void 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");
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100190 printf("\n:: to-cper cper.json --out file.name [--no-validate] [--debug] [--specification some/spec/path.json]\n");
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100191 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");
Lawrence Tang4ef0a0a2022-07-18 10:50:58 +0100198}