Sort includes in C++ files
[babeltrace.git] / src / plugins / ctf / common / metadata / decoder-packetized-file-stream-to-buf.cpp
CommitLineData
3c8252a5 1/*
0235b0db 2 * SPDX-License-Identifier: MIT
3c8252a5 3 *
0235b0db 4 * Copyright 2016-2017 Philippe Proulx <pproulx@efficios.com>
3c8252a5
PP
5 */
6
c802cacb
SM
7#include <glib.h>
8#include <inttypes.h>
9#include <stdbool.h>
10#include <stdint.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14
15#include <babeltrace2/babeltrace.h>
16
4164020e 17#define BT_COMP_LOG_SELF_COMP self_comp
50f6fce8 18#define BT_COMP_LOG_SELF_COMP_CLASS self_comp_class
4164020e
SM
19#define BT_LOG_OUTPUT_LEVEL log_level
20#define BT_LOG_TAG "PLUGIN/CTF/META/DECODER-DECODE-PACKET"
c802cacb 21#include "logging.hpp"
d9c39b0a 22#include "logging/comp-logging.h"
3c8252a5 23
3c8252a5 24#include "common/assert.h"
6162e6b7 25#include "common/uuid.h"
3c8252a5 26#include "compat/memstream.h"
3c8252a5 27
087cd0f5 28#include "ast.hpp"
c802cacb 29#include "decoder-packetized-file-stream-to-buf.hpp"
087cd0f5
SM
30#include "decoder.hpp"
31#include "scanner.hpp"
3c8252a5 32
4164020e 33#define TSDL_MAGIC 0x75d11d57
3c8252a5 34
4164020e
SM
35struct ctf_metadata_decoder
36{
37 struct ctf_visitor_generate_ir *visitor;
38 bt_uuid_t uuid;
39 bool is_uuid_set;
40 int bo;
41 struct ctf_metadata_decoder_config config;
3c8252a5
PP
42};
43
4164020e
SM
44struct packet_header
45{
46 uint32_t magic;
47 bt_uuid_t uuid;
48 uint32_t checksum;
49 uint32_t content_size;
50 uint32_t packet_size;
51 uint8_t compression_scheme;
52 uint8_t encryption_scheme;
53 uint8_t checksum_scheme;
54 uint8_t major;
55 uint8_t minor;
3c8252a5
PP
56} __attribute__((__packed__));
57
4164020e
SM
58static int decode_packet(FILE *in_fp, FILE *out_fp, int byte_order, bool *is_uuid_set,
59 uint8_t *uuid, bt_logging_level log_level, bt_self_component *self_comp,
60 bt_self_component_class *self_comp_class)
3c8252a5 61{
4164020e
SM
62 struct packet_header header;
63 size_t readlen, writelen, toread;
64 uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */
65 int ret = 0;
66 const long offset = ftell(in_fp);
67
68 if (offset < 0) {
69 BT_COMP_LOGE_APPEND_CAUSE_ERRNO(BT_COMP_LOG_SELF_COMP,
70 "Failed to get current metadata file position", ".");
71 goto error;
72 }
73 BT_COMP_LOGD("Decoding metadata packet: offset=%ld", offset);
74 readlen = fread(&header, sizeof(header), 1, in_fp);
75 if (feof(in_fp) != 0) {
76 BT_COMP_LOGI("Reached end of file: offset=%ld", ftell(in_fp));
77 goto end;
78 }
79 if (readlen < 1) {
80 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot decode metadata packet: offset=%ld",
81 offset);
82 goto error;
83 }
84
85 if (byte_order != BYTE_ORDER) {
86 header.magic = GUINT32_SWAP_LE_BE(header.magic);
87 header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
88 header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
89 header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size);
90 }
91
92 if (header.compression_scheme) {
93 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
94 "Metadata packet compression is not supported as of this version: "
95 "compression-scheme=%u, offset=%ld",
96 (unsigned int) header.compression_scheme, offset);
97 goto error;
98 }
99
100 if (header.encryption_scheme) {
101 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
102 "Metadata packet encryption is not supported as of this version: "
103 "encryption-scheme=%u, offset=%ld",
104 (unsigned int) header.encryption_scheme, offset);
105 goto error;
106 }
107
108 if (header.checksum || header.checksum_scheme) {
109 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
110 "Metadata packet checksum verification is not supported as of this version: "
111 "checksum-scheme=%u, checksum=%x, offset=%ld",
112 (unsigned int) header.checksum_scheme, header.checksum, offset);
113 goto error;
114 }
115
116 if (!ctf_metadata_decoder_is_packet_version_valid(header.major, header.minor)) {
117 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Invalid metadata packet version: "
118 "version=%u.%u, offset=%ld",
119 header.major, header.minor, offset);
120 goto error;
121 }
122
123 /* Set expected trace UUID if not set; otherwise validate it */
124 if (is_uuid_set) {
125 if (!*is_uuid_set) {
126 bt_uuid_copy(uuid, header.uuid);
127 *is_uuid_set = true;
128 } else if (bt_uuid_compare(header.uuid, uuid)) {
129 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
130 "Metadata UUID mismatch between packets of the same stream: "
131 "packet-uuid=\"" BT_UUID_FMT "\", "
132 "expected-uuid=\"" BT_UUID_FMT "\", "
133 "offset=%ld",
134 BT_UUID_FMT_VALUES(header.uuid), BT_UUID_FMT_VALUES(uuid), offset);
135 goto error;
136 }
137 }
138
139 if ((header.content_size / CHAR_BIT) < sizeof(header)) {
140 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
141 "Bad metadata packet content size: content-size=%u, "
142 "offset=%ld",
143 header.content_size, offset);
144 goto error;
145 }
146
147 toread = header.content_size / CHAR_BIT - sizeof(header);
148
149 for (;;) {
150 size_t loop_read;
151
152 loop_read = MIN(sizeof(buf) - 1, toread);
153 readlen = fread(buf, sizeof(uint8_t), loop_read, in_fp);
154 if (ferror(in_fp)) {
155 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("Cannot read metadata packet buffer: "
156 "offset=%ld, read-size=%zu",
157 ftell(in_fp), loop_read);
158 goto error;
159 }
160 if (readlen > loop_read) {
161 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE("fread returned more byte than expected: "
162 "read-size-asked=%zu, read-size-returned=%zu",
163 loop_read, readlen);
164 goto error;
165 }
166
167 writelen = fwrite(buf, sizeof(uint8_t), readlen, out_fp);
168 if (writelen < readlen || ferror(out_fp)) {
169 _BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
170 "Cannot write decoded metadata text to buffer: "
171 "read-offset=%ld, write-size=%zu",
172 ftell(in_fp), readlen);
173 goto error;
174 }
175
176 toread -= readlen;
177 if (toread == 0) {
178 int fseek_ret;
179
180 /* Read leftover padding */
181 toread = (header.packet_size - header.content_size) / CHAR_BIT;
182 fseek_ret = fseek(in_fp, toread, SEEK_CUR);
183 if (fseek_ret < 0) {
184 BT_COMP_LOGW_STR("Missing padding at the end of the metadata stream.");
185 }
186 break;
187 }
188 }
189
190 goto end;
3c8252a5
PP
191
192error:
4164020e 193 ret = -1;
3c8252a5
PP
194
195end:
4164020e 196 return ret;
3c8252a5
PP
197}
198
4164020e
SM
199int 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)
3c8252a5 204{
4164020e
SM
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;
3c8252a5
PP
256
257error:
4164020e 258 ret = -1;
3c8252a5 259
4164020e
SM
260 if (out_fp) {
261 if (bt_close_memstream(buf, &size, out_fp)) {
262 BT_COMP_LOGE_ERRNO("Cannot close memory stream", ".");
263 }
264 }
3c8252a5 265
4164020e
SM
266 if (*buf) {
267 free(*buf);
268 *buf = NULL;
269 }
3c8252a5
PP
270
271end:
4164020e 272 return ret;
3c8252a5 273}
This page took 0.077417 seconds and 4 git commands to generate.