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

_______________________________________________
subsurface mailing list
[email protected]
http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface

Reply via email to