From a0fe7d97d4a551665af7bd91f7571dc785a75951 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 17 May 2011 08:55:49 -0400 Subject: [PATCH] Test and fix packet-based metadata parsing Signed-off-by: Mathieu Desnoyers --- formats/ctf/ctf.c | 28 ++++++++++--- .../metadata/ctf-visitor-generate-io-struct.c | 39 +++++++++++------- include/babeltrace/ctf/metadata.h | 2 +- .../succeed/packet-based-metadata/datastream | Bin 0 -> 131072 bytes .../succeed/packet-based-metadata/metadata | Bin 0 -> 636 bytes 5 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 tests/ctf-traces/succeed/packet-based-metadata/datastream create mode 100644 tests/ctf-traces/succeed/packet-based-metadata/metadata diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index b0d3ebcf..7c354bf0 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -46,6 +46,10 @@ #define WRITE_PACKET_LEN (getpagesize() * 8 * CHAR_BIT) #define UUID_LEN 16 /* uuid by value len */ +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + extern int yydebug; struct trace_descriptor *ctf_open_trace(const char *path, int flags); @@ -380,7 +384,7 @@ int packet_metadata(struct ctf_trace *td, FILE *fp) int ret = 0; len = fread(&magic, sizeof(magic), 1, fp); - if (len != sizeof(magic)) { + if (len != 1) { goto end; } if (magic == TSDL_MAGIC) { @@ -391,6 +395,7 @@ int packet_metadata(struct ctf_trace *td, FILE *fp) td->byte_order = (BYTE_ORDER == BIG_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; } + CTF_TRACE_SET_FIELD(td, byte_order); end: rewind(fp); return ret; @@ -401,12 +406,12 @@ int ctf_open_trace_metadata_packet_read(struct ctf_trace *td, FILE *in, FILE *out) { struct metadata_packet_header header; - size_t readlen, writelen; + size_t readlen, writelen, toread; char buf[4096]; int ret = 0; readlen = fread(&header, sizeof(header), 1, in); - if (readlen < sizeof(header)) + if (readlen < 1) return -EINVAL; if (td->byte_order != BYTE_ORDER) { @@ -440,12 +445,15 @@ int ctf_open_trace_metadata_packet_read(struct ctf_trace *td, FILE *in, return -EINVAL; } - while (!feof(in)) { - readlen = fread(buf, sizeof(char), sizeof(buf), in); + toread = header.content_size / CHAR_BIT; + + for (;;) { + readlen = fread(buf, sizeof(char), min(sizeof(buf), toread), in); if (ferror(in)) { ret = -EINVAL; break; } + printf("read %s\n", buf); writelen = fwrite(buf, sizeof(char), readlen, out); if (writelen < readlen) { ret = -EIO; @@ -455,6 +463,15 @@ int ctf_open_trace_metadata_packet_read(struct ctf_trace *td, FILE *in, ret = -EINVAL; break; } + toread -= readlen; + if (!toread) { + ret = -EOF; + break; + } + if (feof(in)) { + ret = -EINVAL; + break; + } } return ret; } @@ -862,7 +879,6 @@ int ctf_open_trace_read(struct ctf_trace *td, const char *path, int flags) readdir_error: free(dirent); error_metadata: - g_ptr_array_free(td->streams, TRUE); close(td->dirfd); error_dirfd: closedir(td->dir); diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 9a5cda09..9dffdcbf 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -1888,7 +1888,8 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru CTF_TRACE_SET_FIELD(trace, minor); } else if (!strcmp(left, "uuid")) { uuid_t uuid; - ret = get_unary_uuid(&node->u.ctf_expression.right, &trace->uuid); + + ret = get_unary_uuid(&node->u.ctf_expression.right, &uuid); if (ret) { fprintf(fd, "[error] %s: unexpected unary expression for trace uuid\n", __func__); ret = -EINVAL; @@ -1899,22 +1900,27 @@ int ctf_trace_declaration_visit(FILE *fd, int depth, struct ctf_node *node, stru fprintf(fd, "[error] %s: uuid mismatch\n", __func__); ret = -EPERM; goto error; + } else { + memcpy(trace->uuid, uuid, sizeof(uuid)); } CTF_TRACE_SET_FIELD(trace, uuid); } else if (!strcmp(left, "byte_order")) { struct ctf_node *right; int byte_order; - if (CTF_TRACE_FIELD_IS_SET(trace, byte_order)) { - fprintf(fd, "[error] %s: endianness already declared in trace declaration\n", __func__); - ret = -EPERM; - goto error; - } right = _cds_list_first_entry(&node->u.ctf_expression.right, struct ctf_node, siblings); byte_order = get_trace_byte_order(fd, depth, right); if (byte_order < 0) return -EINVAL; - trace->byte_order = byte_order; + + if (CTF_TRACE_FIELD_IS_SET(trace, byte_order) + && byte_order != trace->byte_order) { + fprintf(fd, "[error] %s: endianness mismatch\n", __func__); + ret = -EPERM; + goto error; + } else { + trace->byte_order = byte_order; + } CTF_TRACE_SET_FIELD(trace, byte_order); } else if (!strcmp(left, "packet.header")) { struct declaration *declaration; @@ -2081,7 +2087,6 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, printf_verbose("CTF visitor: metadata construction... "); trace->root_declaration_scope = new_declaration_scope(NULL); - trace->streams = g_ptr_array_new(); trace->byte_order = byte_order; switch (node->type) { @@ -2091,26 +2096,27 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, ret = ctf_root_declaration_visit(fd, depth + 1, iter, trace); if (ret) { fprintf(fd, "[error] %s: root declaration error\n", __func__); - return ret; + goto error; } } cds_list_for_each_entry(iter, &node->u.root.trace, siblings) { ret = ctf_trace_visit(fd, depth + 1, iter, trace); if (ret) { fprintf(fd, "[error] %s: trace declaration error\n", __func__); - return ret; + goto error; } } if (!trace->streams) { fprintf(fd, "[error] %s: missing trace declaration\n", __func__); - return -EINVAL; + ret = -EINVAL; + goto error; } cds_list_for_each_entry(iter, &node->u.root.stream, siblings) { ret = ctf_stream_visit(fd, depth + 1, iter, trace->root_declaration_scope, trace); if (ret) { fprintf(fd, "[error] %s: stream declaration error\n", __func__); - return ret; + goto error; } } cds_list_for_each_entry(iter, &node->u.root.event, siblings) { @@ -2118,7 +2124,7 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, trace->root_declaration_scope, trace); if (ret) { fprintf(fd, "[error] %s: event declaration error\n", __func__); - return ret; + goto error; } } break; @@ -2126,8 +2132,13 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, default: fprintf(fd, "[error] %s: unknown node type %d\n", __func__, (int) node->type); - return -EINVAL; + ret = -EINVAL; + goto error; } printf_verbose("done.\n"); return ret; + +error: + free_declaration_scope(trace->root_declaration_scope); + return ret; } diff --git a/include/babeltrace/ctf/metadata.h b/include/babeltrace/ctf/metadata.h index 6ebd0c7c..c1976247 100644 --- a/include/babeltrace/ctf/metadata.h +++ b/include/babeltrace/ctf/metadata.h @@ -188,6 +188,6 @@ struct metadata_packet_header { uint8_t compression_scheme; /* 0 if unused */ uint8_t encryption_scheme; /* 0 if unused */ uint8_t checksum_scheme; /* 0 if unused */ -}; +} __attribute__((packed)); #endif /* _BABELTRACE_CTF_METADATA_H */ diff --git a/tests/ctf-traces/succeed/packet-based-metadata/datastream b/tests/ctf-traces/succeed/packet-based-metadata/datastream new file mode 100644 index 0000000000000000000000000000000000000000..13bff2e85551fd761db1228cee985079b8c24817 GIT binary patch literal 131072 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°ws}ItsB&2a6=+did)Y9L{>U&f?gH;TK#3h*%HLOK@yN z*2jTj+HT_#jJ-PBg3)0GtxKOHx}F%cbo*rGADXHe3JynGADYU=Qx{# z*2J%ePqI1mdiV^RgZ9L)hd0<9yDsAb=}6yNyS(zS!9av~oyz3cWffWvhdm1-!0dD$ z$Hv63ho8;okn7>+wa0-GR_i{`3wRu_eZ{PYe~iIF=OnF%U&7=ht%qO6;D}72QN()q zRXh$-$o23qF*w3M3G3n4QygMF{0=IeRl1>NW@>A5 z=TgqP7J8{=zu#3-9CsZ_GfJ>->^tZ9CJBzAd*{ao*T?RX)`+Jh0?}B@ZllV95hZ9$50gk_VPNu;hUy4=j0L$pcFsSn|M<2bMgr LV0_n@YAOG;EBBnBo{22@3ka|wpTtr7=Os!IGF7FNoN7+Cp7 z+@-C`P#RhB(|x@2d-l!IPyKOz`FVAH@%6Smczs_Uk6ZM8AJXrIQOnMzD03|<(8gkh zCCs7H&j=$3LZD1$Rb(zVvrBn!W z*D2)vq@;nJkgzrl_6gUu=5w^;VJ{Uzbv+RX^n|a3CovAZPG1h=(>UueO7(#D>3#V7k8XOlKIVuv@>EE`tsn>bNBdmJ5zt)q;0Ioe#!K(M0@KBC#9maD+(0xK(v jDb=sVHEpcT$b#PkiPa{fe5x@|s=pf7Io{}HG~WCI3;4#p literal 0 HcmV?d00001 -- 2.34.1