+static
+bool is_tracer_affected_by_lttng_event_after_packet_bug(
+ struct tracer_info *curr_tracer_info)
+{
+ bool is_affected = false;
+
+ if (strcmp(curr_tracer_info->name, "lttng-ust") == 0) {
+ if (curr_tracer_info->major < 2) {
+ is_affected = true;
+ } else if (curr_tracer_info->major == 2) {
+ /* fixed in lttng-ust 2.11.0 */
+ if (curr_tracer_info->minor < 11) {
+ is_affected = true;
+ }
+ }
+ } else if (strcmp(curr_tracer_info->name, "lttng-modules") == 0) {
+ if (curr_tracer_info->major < 2) {
+ is_affected = true;
+ } else if (curr_tracer_info->major == 2) {
+ /* fixed in lttng-modules 2.11.0 */
+ if (curr_tracer_info->minor == 10) {
+ /* fixed in lttng-modules 2.10.10 */
+ if (curr_tracer_info->patch < 10) {
+ is_affected = true;
+ }
+ } else if (curr_tracer_info->minor == 9) {
+ /* fixed in lttng-modules 2.9.13 */
+ if (curr_tracer_info->patch < 13) {
+ is_affected = true;
+ }
+ } else if (curr_tracer_info->minor < 9) {
+ is_affected = true;
+ }
+ }
+ }
+
+ return is_affected;
+}
+
+static
+bool is_tracer_affected_by_barectf_event_before_packet_bug(
+ struct tracer_info *curr_tracer_info)
+{
+ bool is_affected = false;
+
+ if (strcmp(curr_tracer_info->name, "barectf") == 0) {
+ if (curr_tracer_info->major < 2) {
+ is_affected = true;
+ } else if (curr_tracer_info->major == 2) {
+ if (curr_tracer_info->minor < 3) {
+ is_affected = true;
+ } else if (curr_tracer_info->minor == 3) {
+ /* fixed in barectf 2.3.1 */
+ if (curr_tracer_info->patch < 1) {
+ is_affected = true;
+ }
+ }
+ }
+ }
+
+ return is_affected;
+}
+
+static
+bool is_tracer_affected_by_lttng_crash_quirk(
+ struct tracer_info *curr_tracer_info)
+{
+ bool is_affected = false;
+
+ /* All LTTng tracer may be affected by this lttng crash quirk. */
+ if (strcmp(curr_tracer_info->name, "lttng-ust") == 0) {
+ is_affected = true;
+ } else if (strcmp(curr_tracer_info->name, "lttng-modules") == 0) {
+ is_affected = true;
+ }
+
+ return is_affected;
+}
+
+/*
+ * Looks for trace produced by known buggy tracers and fix up the index
+ * produced earlier.
+ */
+static
+int fix_packet_index_tracer_bugs(struct ctf_fs_component *ctf_fs,
+ bt_self_component *self_comp,
+ bt_self_component_class *self_comp_class)
+{
+ int ret = 0;
+ struct tracer_info current_tracer_info;
+ bt_logging_level log_level = ctf_fs->log_level;
+
+ ret = extract_tracer_info(ctf_fs->trace, ¤t_tracer_info);
+ if (ret) {
+ /*
+ * A trace may not have all the necessary environment
+ * entries to do the tracer version comparison.
+ * At least, the tracer name and major version number
+ * are needed. Failing to extract these entries is not
+ * an error.
+ */
+ ret = 0;
+ BT_LOGI_STR("Cannot extract tracer information necessary to compare with buggy versions.");
+ goto end;;
+ }
+
+ /* Check if the trace may be affected by old tracer bugs. */
+ if (is_tracer_affected_by_lttng_event_after_packet_bug(
+ ¤t_tracer_info)) {
+ BT_LOGI_STR("Trace may be affected by LTTng tracer packet timestamp bug. Fixing up.");
+ ret = fix_index_lttng_event_after_packet_bug(ctf_fs->trace);
+ if (ret) {
+ BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
+ self_comp, self_comp_class,
+ "Failed to fix LTTng event-after-packet bug.");
+ goto end;
+ }
+ ctf_fs->trace->metadata->tc->quirks.lttng_event_after_packet = true;
+ }
+
+ if (is_tracer_affected_by_barectf_event_before_packet_bug(
+ ¤t_tracer_info)) {
+ BT_LOGI_STR("Trace may be affected by barectf tracer packet timestamp bug. Fixing up.");
+ ret = fix_index_barectf_event_before_packet_bug(ctf_fs->trace);
+ if (ret) {
+ BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
+ self_comp, self_comp_class,
+ "Failed to fix barectf event-before-packet bug.");
+ goto end;
+ }
+ ctf_fs->trace->metadata->tc->quirks.barectf_event_before_packet = true;
+ }
+
+ if (is_tracer_affected_by_lttng_crash_quirk(
+ ¤t_tracer_info)) {
+ ret = fix_index_lttng_crash_quirk(ctf_fs->trace);
+ if (ret) {
+ BT_COMP_OR_COMP_CLASS_LOGE_APPEND_CAUSE(
+ self_comp, self_comp_class,
+ "Failed to fix lttng-crash timestamp quirks.");
+ goto end;
+ }
+ ctf_fs->trace->metadata->tc->quirks.lttng_crash = true;
+ }
+
+end:
+ return ret;
+}
+
+static
+gint compare_ds_file_groups_by_first_path(gconstpointer a, gconstpointer b)
+{
+ struct ctf_fs_ds_file_group * const *ds_file_group_a = a;
+ struct ctf_fs_ds_file_group * const *ds_file_group_b = b;
+ const struct ctf_fs_ds_file_info *first_ds_file_info_a;
+ const struct ctf_fs_ds_file_info *first_ds_file_info_b;
+
+ BT_ASSERT((*ds_file_group_a)->ds_file_infos->len > 0);
+ BT_ASSERT((*ds_file_group_b)->ds_file_infos->len > 0);
+ first_ds_file_info_a = (*ds_file_group_a)->ds_file_infos->pdata[0];
+ first_ds_file_info_b = (*ds_file_group_b)->ds_file_infos->pdata[0];
+ return strcmp(first_ds_file_info_a->path->str,
+ first_ds_file_info_b->path->str);
+}
+
+int ctf_fs_component_create_ctf_fs_trace(