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