Re-format new C++ files
[babeltrace.git] / src / plugins / ctf / common / metadata / decoder-packetized-file-stream-to-buf.cpp
1 /*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright 2016-2017 Philippe Proulx <pproulx@efficios.com>
5 */
6
7 #define BT_COMP_LOG_SELF_COMP self_comp
8 #define BT_COMP_LOG_SELF_COMP_CLASS self_comp_class
9 #define BT_LOG_OUTPUT_LEVEL log_level
10 #define BT_LOG_TAG "PLUGIN/CTF/META/DECODER-DECODE-PACKET"
11 #include "logging/comp-logging.h"
12
13 #include "decoder-packetized-file-stream-to-buf.hpp"
14
15 #include <stdio.h>
16 #include <stdbool.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 #include <inttypes.h>
20 #include "common/assert.h"
21 #include "common/uuid.h"
22 #include "compat/memstream.h"
23 #include <babeltrace2/babeltrace.h>
24 #include <glib.h>
25 #include <string.h>
26
27 #include "ast.hpp"
28 #include "decoder.hpp"
29 #include "scanner.hpp"
30 #include "logging.hpp"
31
32 #define TSDL_MAGIC 0x75d11d57
33
34 struct ctf_metadata_decoder
35 {
36 struct ctf_visitor_generate_ir *visitor;
37 bt_uuid_t uuid;
38 bool is_uuid_set;
39 int bo;
40 struct ctf_metadata_decoder_config config;
41 };
42
43 struct packet_header
44 {
45 uint32_t magic;
46 bt_uuid_t uuid;
47 uint32_t checksum;
48 uint32_t content_size;
49 uint32_t packet_size;
50 uint8_t compression_scheme;
51 uint8_t encryption_scheme;
52 uint8_t checksum_scheme;
53 uint8_t major;
54 uint8_t minor;
55 } __attribute__((__packed__));
56
57 static int decode_packet(FILE *in_fp, FILE *out_fp, int byte_order, bool *is_uuid_set,
58 uint8_t *uuid, bt_logging_level log_level, bt_self_component *self_comp,
59 bt_self_component_class *self_comp_class)
60 {
61 struct packet_header header;
62 size_t readlen, writelen, toread;
63 uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */
64 int ret = 0;
65 const long offset = ftell(in_fp);
66
67 if (offset < 0) {
68 BT_COMP_LOGE_APPEND_CAUSE_ERRNO(BT_COMP_LOG_SELF_COMP,
69 "Failed to get current metadata file position", ".");
70 goto error;
71 }
72 BT_COMP_LOGD("Decoding metadata packet: offset=%ld", offset);
73 readlen = fread(&header, sizeof(header), 1, in_fp);
74 if (feof(in_fp) != 0) {
75 BT_COMP_LOGI("Reached end of file: offset=%ld", ftell(in_fp));
76 goto end;
77 }
78 if (readlen < 1) {
79 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot decode metadata packet: offset=%ld",
80 offset);
81 goto error;
82 }
83
84 if (byte_order != BYTE_ORDER) {
85 header.magic = GUINT32_SWAP_LE_BE(header.magic);
86 header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
87 header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
88 header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size);
89 }
90
91 if (header.compression_scheme) {
92 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
93 "Metadata packet compression is not supported as of this version: "
94 "compression-scheme=%u, offset=%ld",
95 (unsigned int) header.compression_scheme, offset);
96 goto error;
97 }
98
99 if (header.encryption_scheme) {
100 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
101 "Metadata packet encryption is not supported as of this version: "
102 "encryption-scheme=%u, offset=%ld",
103 (unsigned int) header.encryption_scheme, offset);
104 goto error;
105 }
106
107 if (header.checksum || header.checksum_scheme) {
108 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
109 "Metadata packet checksum verification is not supported as of this version: "
110 "checksum-scheme=%u, checksum=%x, offset=%ld",
111 (unsigned int) header.checksum_scheme, header.checksum, offset);
112 goto error;
113 }
114
115 if (!ctf_metadata_decoder_is_packet_version_valid(header.major, header.minor)) {
116 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Invalid metadata packet version: "
117 "version=%u.%u, offset=%ld",
118 header.major, header.minor, offset);
119 goto error;
120 }
121
122 /* Set expected trace UUID if not set; otherwise validate it */
123 if (is_uuid_set) {
124 if (!*is_uuid_set) {
125 bt_uuid_copy(uuid, header.uuid);
126 *is_uuid_set = true;
127 } else if (bt_uuid_compare(header.uuid, uuid)) {
128 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
129 "Metadata UUID mismatch between packets of the same stream: "
130 "packet-uuid=\"" BT_UUID_FMT "\", "
131 "expected-uuid=\"" BT_UUID_FMT "\", "
132 "offset=%ld",
133 BT_UUID_FMT_VALUES(header.uuid), BT_UUID_FMT_VALUES(uuid), offset);
134 goto error;
135 }
136 }
137
138 if ((header.content_size / CHAR_BIT) < sizeof(header)) {
139 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
140 "Bad metadata packet content size: content-size=%u, "
141 "offset=%ld",
142 header.content_size, offset);
143 goto error;
144 }
145
146 toread = header.content_size / CHAR_BIT - sizeof(header);
147
148 for (;;) {
149 size_t loop_read;
150
151 loop_read = MIN(sizeof(buf) - 1, toread);
152 readlen = fread(buf, sizeof(uint8_t), loop_read, in_fp);
153 if (ferror(in_fp)) {
154 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot read metadata packet buffer: "
155 "offset=%ld, read-size=%zu",
156 ftell(in_fp), loop_read);
157 goto error;
158 }
159 if (readlen > loop_read) {
160 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("fread returned more byte than expected: "
161 "read-size-asked=%zu, read-size-returned=%zu",
162 loop_read, readlen);
163 goto error;
164 }
165
166 writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp);
167 if (writelen < readlen || ferror(out_fp)) {
168 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
169 "Cannot write decoded metadata text to buffer: "
170 "read-offset=%ld, write-size=%zu",
171 ftell(in_fp), readlen);
172 goto error;
173 }
174
175 toread -= readlen;
176 if (toread == 0) {
177 int fseek_ret;
178
179 /* Read leftover padding */
180 toread = (header.packet_size - header.content_size) / CHAR_BIT;
181 fseek_ret = fseek(in_fp, toread, SEEK_CUR);
182 if (fseek_ret < 0) {
183 BT_COMP_LOGW_STR("Missing padding at the end of the metadata stream.");
184 }
185 break;
186 }
187 }
188
189 goto end;
190
191 error:
192 ret = -1;
193
194 end:
195 return ret;
196 }
197
198 BT_HIDDEN
199 int ctf_metadata_decoder_packetized_file_stream_to_buf(FILE *fp, char **buf, int byte_order,
200 bool *is_uuid_set, uint8_t *uuid,
201 bt_logging_level log_level,
202 bt_self_component *self_comp,
203 bt_self_component_class *self_comp_class)
204 {
205 FILE *out_fp;
206 size_t size;
207 int ret = 0;
208 int tret;
209 size_t packet_index = 0;
210
211 out_fp = bt_open_memstream(buf, &size);
212 if (!out_fp) {
213 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot open memory stream: %s.", strerror(errno));
214 goto error;
215 }
216
217 for (;;) {
218 if (feof(fp) != 0) {
219 break;
220 }
221
222 tret = decode_packet(fp, out_fp, byte_order, is_uuid_set, uuid, log_level, self_comp,
223 self_comp_class);
224 if (tret) {
225 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot decode packet: index=%zu",
226 packet_index);
227 goto error;
228 }
229
230 packet_index++;
231 }
232
233 /* Make sure the whole string ends with a null character */
234 tret = fputc('\0', out_fp);
235 if (tret == EOF) {
236 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
237 "Cannot append '\\0' to the decoded metadata buffer.");
238 goto error;
239 }
240
241 /* Close stream, which also flushes the buffer */
242 ret = bt_close_memstream(buf, &size, out_fp);
243 /*
244 * See fclose(3). Further access to out_fp after both success
245 * and error, even through another bt_close_memstream(), results
246 * in undefined behavior. Nullify out_fp to ensure we don't
247 * fclose it twice on error.
248 */
249 out_fp = NULL;
250 if (ret < 0) {
251 BT_COMP_LOGE_APPEND_CAUSE_ERRNO(BT_COMP_LOG_SELF_COMP, "Cannot close memory stream", ".");
252 goto error;
253 }
254
255 goto end;
256
257 error:
258 ret = -1;
259
260 if (out_fp) {
261 if (bt_close_memstream(buf, &size, out_fp)) {
262 BT_COMP_LOGE_ERRNO("Cannot close memory stream", ".");
263 }
264 }
265
266 if (*buf) {
267 free(*buf);
268 *buf = NULL;
269 }
270
271 end:
272 return ret;
273 }
This page took 0.0349 seconds and 4 git commands to generate.