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