Fix: define macros for logging levels
[babeltrace.git] / src / plugins / ctf / common / metadata / decoder-packetized-file-stream-to-buf.c
CommitLineData
3c8252a5
PP
1/*
2 * Copyright 2016-2017 - Philippe Proulx <pproulx@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 */
14
15#define BT_COMP_LOG_SELF_COMP self_comp
16#define BT_LOG_OUTPUT_LEVEL log_level
17#define BT_LOG_TAG "PLUGIN/CTF/META/DECODER-DECODE-PACKET"
d9c39b0a 18#include "logging/comp-logging.h"
3c8252a5
PP
19
20#include <stdio.h>
21#include <stdbool.h>
22#include <stdint.h>
23#include <stdlib.h>
24#include <inttypes.h>
25#include "common/assert.h"
6162e6b7 26#include "common/uuid.h"
3c8252a5
PP
27#include "compat/memstream.h"
28#include <babeltrace2/babeltrace.h>
29#include <glib.h>
30#include <string.h>
31
32#include "ast.h"
33#include "decoder.h"
34#include "scanner.h"
35#include "logging.h"
36
37#define TSDL_MAGIC 0x75d11d57
38
3c8252a5
PP
39struct ctf_metadata_decoder {
40 struct ctf_visitor_generate_ir *visitor;
6162e6b7 41 bt_uuid_t uuid;
3c8252a5
PP
42 bool is_uuid_set;
43 int bo;
44 struct ctf_metadata_decoder_config config;
45};
46
47struct packet_header {
48 uint32_t magic;
6162e6b7 49 bt_uuid_t uuid;
3c8252a5
PP
50 uint32_t checksum;
51 uint32_t content_size;
52 uint32_t packet_size;
53 uint8_t compression_scheme;
54 uint8_t encryption_scheme;
55 uint8_t checksum_scheme;
56 uint8_t major;
57 uint8_t minor;
58} __attribute__((__packed__));
59
60static
61int decode_packet(FILE *in_fp, FILE *out_fp,
62 int byte_order, bool *is_uuid_set, uint8_t *uuid,
63 bt_logging_level log_level, bt_self_component *self_comp)
64{
65 struct packet_header header;
66 size_t readlen, writelen, toread;
67 uint8_t buf[512 + 1]; /* + 1 for debug-mode \0 */
68 int ret = 0;
69 const long offset = ftell(in_fp);
70
71 if (offset < 0) {
72 BT_COMP_LOGE_ERRNO("Failed to get current metadata file position",
73 ".");
74 goto error;
75 }
76 BT_COMP_LOGD("Decoding metadata packet: offset=%ld", offset);
77 readlen = fread(&header, sizeof(header), 1, in_fp);
78 if (feof(in_fp) != 0) {
79 BT_COMP_LOGI("Reached end of file: offset=%ld", ftell(in_fp));
80 goto end;
81 }
82 if (readlen < 1) {
83 BT_COMP_LOGE("Cannot decode metadata packet: offset=%ld", offset);
84 goto error;
85 }
86
87 if (byte_order != BYTE_ORDER) {
88 header.magic = GUINT32_SWAP_LE_BE(header.magic);
89 header.checksum = GUINT32_SWAP_LE_BE(header.checksum);
90 header.content_size = GUINT32_SWAP_LE_BE(header.content_size);
91 header.packet_size = GUINT32_SWAP_LE_BE(header.packet_size);
92 }
93
94 if (header.compression_scheme) {
95 BT_COMP_LOGE("Metadata packet compression is not supported as of this version: "
96 "compression-scheme=%u, offset=%ld",
97 (unsigned int) header.compression_scheme, offset);
98 goto error;
99 }
100
101 if (header.encryption_scheme) {
102 BT_COMP_LOGE("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_LOGE("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,
112 offset);
113 goto error;
114 }
115
116 if (!ctf_metadata_decoder_is_packet_version_valid(header.major,
117 header.minor)) {
118 BT_COMP_LOGE("Invalid metadata packet version: "
119 "version=%u.%u, offset=%ld",
120 header.major, header.minor, offset);
121 goto error;
122 }
123
124 /* Set expected trace UUID if not set; otherwise validate it */
125 if (is_uuid_set) {
126 if (!*is_uuid_set) {
6162e6b7 127 bt_uuid_copy(uuid, header.uuid);
3c8252a5
PP
128 *is_uuid_set = true;
129 } else if (bt_uuid_compare(header.uuid, uuid)) {
130 BT_COMP_LOGE("Metadata UUID mismatch between packets of the same stream: "
6162e6b7
MJ
131 "packet-uuid=\"" BT_UUID_FMT "\", "
132 "expected-uuid=\"" BT_UUID_FMT "\", "
3c8252a5 133 "offset=%ld",
6162e6b7
MJ
134 BT_UUID_FMT_VALUES(header.uuid),
135 BT_UUID_FMT_VALUES(uuid),
3c8252a5
PP
136 offset);
137 goto error;
138 }
139 }
140
141 if ((header.content_size / CHAR_BIT) < sizeof(header)) {
142 BT_COMP_LOGE("Bad metadata packet content size: content-size=%u, "
143 "offset=%ld", 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_LOGE("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_LOGE("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_LOGE("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) /
181 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;
191
192error:
193 ret = -1;
194
195end:
196 return ret;
197}
198
199BT_HIDDEN
200int ctf_metadata_decoder_packetized_file_stream_to_buf(FILE *fp,
201 char **buf, int byte_order, bool *is_uuid_set,
202 uint8_t *uuid, bt_logging_level log_level,
203 bt_self_component *self_comp)
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);
5084732e 212 if (!out_fp) {
3c8252a5
PP
213 BT_COMP_LOGE("Cannot open memory stream: %s.",
214 strerror(errno));
215 goto error;
216 }
217
218 for (;;) {
219 if (feof(fp) != 0) {
220 break;
221 }
222
223 tret = decode_packet(fp, out_fp, byte_order, is_uuid_set,
224 uuid, log_level, self_comp);
225 if (tret) {
226 BT_COMP_LOGE("Cannot decode packet: index=%zu",
227 packet_index);
228 goto error;
229 }
230
231 packet_index++;
232 }
233
234 /* Make sure the whole string ends with a null character */
235 tret = fputc('\0', out_fp);
236 if (tret == EOF) {
237 BT_COMP_LOGE_STR(
238 "Cannot append '\\0' to the decoded metadata buffer.");
239 goto error;
240 }
241
242 /* Close stream, which also flushes the buffer */
243 ret = bt_close_memstream(buf, &size, out_fp);
244 /*
245 * See fclose(3). Further access to out_fp after both success
246 * and error, even through another bt_close_memstream(), results
247 * in undefined behavior. Nullify out_fp to ensure we don't
248 * fclose it twice on error.
249 */
250 out_fp = NULL;
251 if (ret < 0) {
252 BT_COMP_LOGE_ERRNO("Cannot close memory stream", ".");
253 goto error;
254 }
255
256 goto end;
257
258error:
259 ret = -1;
260
261 if (out_fp) {
262 if (bt_close_memstream(buf, &size, out_fp)) {
263 BT_COMP_LOGE_ERRNO("Cannot close memory stream", ".");
264 }
265 }
266
267 if (*buf) {
268 free(*buf);
269 *buf = NULL;
270 }
271
272end:
273 return ret;
274}
This page took 0.042729 seconds and 4 git commands to generate.