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