[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