[PATCH] Survive CCR dive logs w/o marked DILUENT/OXYGEN cylinders

Giuseppe Bilotta giuseppe.bilotta at gmail.com
Sat Nov 22 07:54:48 PST 2014


Some broken CCR dive logs might not have DILUENT and/or OXYGEN cylinders
marked as such (see e.g. dives/Poseidon_MkVILog.xml in the repository).

However, the recent set of CCR patches (and fixes on top of it) caused a
number of places in the code to break by trying to use negative cylinder
index.

Fix this by making sure that a CCR dive has both a DILUENT and an
OXYGEN cylinder, during the dive computer fixup.
---
 dive.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)


Ok, apparently this was all that was needed, and the other segfault I was
chasing was due to unrelated changes I still had laying around.

The proposed fix is a little braindead, but it should work in a pinch.

diff --git a/dive.c b/dive.c
index 5a8da01..27d56d9 100644
--- a/dive.c
+++ b/dive.c
@@ -967,6 +967,30 @@ static void sanitize_cylinder_info(struct dive *dive)
 	}
 }
 
+/* If a CCR dive is missing DILUENT/OXYGEN cylinders, we
+ * go over the existing cylinders and promote OC_GAS cylinders
+ * to the (needed) type. Return the index of the 'fixed' cylinder,
+ * -1 if nothing was done.
+ */
+static int sanitize_ccr_cylinder_info(struct dive *dive, enum cylinderuse use)
+{
+	int i;
+
+	/* TODO FIXME this approach is a little braindead, we should only touch
+	 * cylinders that are not touched by other, non-CCR dive computers
+	 */
+	for (i = 0; i < MAX_CYLINDERS; i++) {
+		cylinder_t *cyl = dive->cylinder + i;
+		if (cyl->cylinder_use == OC_GAS) {
+			printf("CCR fixup: changing cylinder %d use to %s\n", i,
+				cylinderuse_text[use]);
+			cyl->cylinder_use = use;
+			return i;
+		}
+	}
+	return -1;
+}
+
 /* some events should never be thrown away */
 static bool is_potentially_redundant(struct event *event)
 {
@@ -1181,6 +1205,42 @@ static void fixup_dive_dc(struct dive *dive, struct divecomputer *dc)
 
 	/* make sure we know for which tank the pressure values are intended */
 	first_cylinder = explicit_first_cylinder(dive, dc);
+
+	/* borked CCR dive imports might be missing DILUENT and/or OXYGEN cylinders. This
+	 * will typically manifest by the first_cylinder being -1 (i.e. not found),
+	 * but for the love of sanity of the rest of the code we will check _now_ that
+	 * we have both a DILUENT and an OXYGEN cylinder. */
+
+	/* First of all, check that the first cylinder is non-negative */
+	if (first_cylinder < 0) {
+		fprintf(stderr, "Missing first cylinder for %s (S/N %s Firmware %s) in dive at %s\n",
+			dc->model, dc->serial, dc->fw_version, dive->location);
+
+		/* Fall back to 0, which is the default for explicit_first_cylinder
+		 * anyway */
+		first_cylinder = 0;
+	}
+
+	/* Now, if we are a CCR dive, let's check that the first_cylinder is a DILUENT,
+	 * and also check that we have an OXYGEN cylinder
+	 */
+	if (dc->dctype == CCR) {
+		if (dive->cylinder[first_cylinder].cylinder_use != DILUENT)
+			first_cylinder = sanitize_ccr_cylinder_info(dive, DILUENT);
+		if (first_cylinder < 0) {
+			fprintf(stderr, "Unable to find a DILUENT cylinder!\n");
+			exit(1); /* we're going to segfault all around anyway, so just quit */
+		}
+		/* Ok, we have a DILUENT cylinder. Now check for an OXYGEN one, and
+		 * run some further sanitation, bailing if it fails too
+		 */
+		if ((get_cylinder_idx_by_use(dive, OXYGEN) < 0) &&
+			(sanitize_ccr_cylinder_info(dive, OXYGEN) < 0)) {
+			fprintf(stderr, "Unable to find an OXYGEN cylinder!\n");
+			exit(1); /* we're going to segfault all around anyway, so just quit */
+		}
+	}
+
 	for (i = 0; i < dc->samples; i++) {
 		struct sample *sample = dc->sample + i;
 		int time = sample->time.seconds;
-- 
2.1.2.766.gaa23a90



More information about the subsurface mailing list