]> Pileus Git - ~andy/rsl/blobdiff - dorade.c
Changes from Bart (2009-10-28)
[~andy/rsl] / dorade.c
index 6c692bf5abb5092755a2b1205fdc0ab693340d9d..bf78a1c18d625aa6bfdbca998d8b866252e958df 100644 (file)
--- a/dorade.c
+++ b/dorade.c
@@ -38,6 +38,32 @@ void dorade_verbose_off()
   dorade_verbose = 0;
 }
 
+static int do_swap = 0;
+
+/**********************************************************************/
+/*                                                                    */
+/*                      read_extra_bytes                              */
+/*                                                                    */
+/**********************************************************************/
+int read_extra_bytes(int nbytes, FILE *in)
+{
+  char *extra;
+  int nread;
+  /*
+   * Read and discard nbytes bytes.  The return value is the byte count
+   * returned by fread, unless there is an error, then it is 0.
+   */
+  extra = (char *) malloc(nbytes);
+  if (!extra) {
+    perror("\nError: read_extra_bytes");
+    fprintf(stderr,"Tried to allocate %d bytes\n", nbytes);
+    return 0;
+  }
+  nread = fread(extra, sizeof(char), nbytes, in);
+  free(extra);
+  return nread;
+}
+
 /**********************************************************************/
 /*                                                                    */
 /*                      dorade_read_comment_block                     */
@@ -52,13 +78,25 @@ Comment_block *dorade_read_comment_block(FILE *in)
        return NULL;
   }
   fread(cb->code, sizeof(cb->code), 1, in);
-  fread(&cb->len, sizeof(cb->len), 1, in);   cb->len = ntohl(cb->len);
-  cb->comment = (char *) calloc(cb->len, sizeof(char));
+  fread(&cb->len, sizeof(cb->len), 1, in);
+
+  /* Check for big endian data on little endian platform.  The smallest value
+   * cb->len could have is 8 (length of cb->code + cb->len), so we put that in
+   * first byte of test value, and also test for negative, since sign bit could
+   * be set in a larger value.
+   */
+  if (cb->len > 0x08000000 || cb->len < 0) do_swap = 1;
+  if (do_swap) cb->len = ntohl(cb->len);
+
+  /* Length of cb->comment is cb->len-8 since cb->code and cb->len have
+   * already been read.
+   */
+  cb->comment = (char *) calloc(cb->len-8, sizeof(char));
   if (cb->comment == NULL) {
        perror("dorade_read_comment_block: cb->comment");
        return cb;
   }
-  fread(cb->comment, sizeof(char), cb->len, in);
+  fread(cb->comment, sizeof(char), cb->len-8, in);
   return cb;
 }
 
@@ -79,20 +117,22 @@ Volume_desc    *dorade_read_volume_desc    (FILE *in)
 
   fread(vd, sizeof(Volume_desc), 1, in);
   /* Now, convert from Big Endian. */
-  vd->len = ntohl(vd->len);
-  vd->version = ntohs(vd->version);
-  vd->volume_number = ntohs(vd->volume_number);
-  vd->max_bytes = ntohl(vd->max_bytes);
-  vd->year = ntohs(vd->year);
-  vd->month = ntohs(vd->month);
-  vd->day = ntohs(vd->day);
-  vd->hour = ntohs(vd->hour);
-  vd->minute = ntohs(vd->minute);
-  vd->second = ntohs(vd->second);
-  vd->gen_year = ntohs(vd->gen_year);
-  vd->gen_month = ntohs(vd->gen_month);
-  vd->gen_day = ntohs(vd->gen_day);
-  vd->nsensors = ntohs(vd->nsensors);
+  if (do_swap) {
+      vd->len = ntohl(vd->len);
+      vd->version = ntohs(vd->version);
+      vd->volume_number = ntohs(vd->volume_number);
+      vd->max_bytes = ntohl(vd->max_bytes);
+      vd->year = ntohs(vd->year);
+      vd->month = ntohs(vd->month);
+      vd->day = ntohs(vd->day);
+      vd->hour = ntohs(vd->hour);
+      vd->minute = ntohs(vd->minute);
+      vd->second = ntohs(vd->second);
+      vd->gen_year = ntohs(vd->gen_year);
+      vd->gen_month = ntohs(vd->gen_month);
+      vd->gen_day = ntohs(vd->gen_day);
+      vd->nsensors = ntohs(vd->nsensors);
+  }
   return vd;
 }
 
@@ -120,7 +160,7 @@ Radar_desc     *dorade_read_radar_desc     (FILE *in)
 
   fread(rd, sizeof(Radar_desc), 1, in);
   /* Now, convert from Big Endian. */
-  if (little_endian()) {
+  if (do_swap) {
        swap_4_bytes(&rd->len);
        swap_4_bytes(&rd->radar_constant); /* Yes, even the ieee floating values. */
        swap_4_bytes(&rd->peak_power);
@@ -153,6 +193,13 @@ Radar_desc     *dorade_read_radar_desc     (FILE *in)
          swap_4_bytes(&rd->period[i]);
        }
   }
+  /* If RADD block is longer than structure, read through extra bytes.
+   * This sometimes happens.
+   */
+  if (rd->len > sizeof(Radar_desc)) {
+      if (read_extra_bytes(rd->len - sizeof(Radar_desc), in) <= 0)
+          fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
+  }
   return rd;
 }
 /**********************************************************************/
@@ -172,7 +219,7 @@ Parameter_desc *dorade_read_parameter_desc (FILE *in)
 
   fread(pd, sizeof(Parameter_desc), 1, in);
   /* Now, convert from Big Endian. */
-  if (little_endian()) {
+  if (do_swap) {
        swap_4_bytes(&pd->len);
        swap_2_bytes(&pd->ipp);
        swap_2_bytes(&pd->xmit_freq);
@@ -186,6 +233,12 @@ Parameter_desc *dorade_read_parameter_desc (FILE *in)
        swap_4_bytes(&pd->offset_factor);
        swap_4_bytes(&pd->missing_data_flag);
   }
+  /* If the descriptor block is longer than the structure, read past the extra bytes.
+   */
+  if (pd->len > sizeof(Parameter_desc)) {
+      if (read_extra_bytes(pd->len - sizeof(Parameter_desc), in) <= 0)
+          fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
+  }
   return pd;
 }
 
@@ -209,7 +262,7 @@ Cell_range_vector      *dorade_read_cell_range_vector     (FILE *in)
   fread(&cv->code, sizeof(cv->code), 1, in);
   fread(&cv->len, sizeof(cv->len), 1, in);
   fread(&cv->ncells, sizeof(cv->ncells), 1, in);
-  if (little_endian()) {
+  if (do_swap) {
        swap_4_bytes(&cv->len);
        swap_4_bytes(&cv->ncells);
   }
@@ -220,7 +273,7 @@ Cell_range_vector      *dorade_read_cell_range_vector     (FILE *in)
   }
   fread(cv->range_cell, sizeof(float), cv->ncells, in);
 
-  if (little_endian()) {
+  if (do_swap) {
        for (i=0; i<cv->ncells; i++)
          swap_4_bytes(&cv->range_cell[i]);
   }
@@ -249,6 +302,8 @@ Cell_range_vector      *dorade_read_cell_range_vector     (FILE *in)
 Correction_factor_desc *dorade_read_correction_factor_desc(FILE *in)
 {
   Correction_factor_desc *cf;
+  char *remaining;
+  int is_cfac = 0;
 
   cf = (Correction_factor_desc *) calloc(1, sizeof(Correction_factor_desc));
   if(!cf) {
@@ -256,9 +311,27 @@ Correction_factor_desc *dorade_read_correction_factor_desc(FILE *in)
        return NULL;
   }
 
-  fread(cf, sizeof(Correction_factor_desc), 1, in);
+  /* Make sure we have Correction Factor Descriptor. */
+  while (!is_cfac) {
+      fread(cf->code, sizeof(cf->code), 1, in);
+      if (strncmp(cf->code, "CFAC", 4) == 0)
+         is_cfac = 1;
+      else {
+         fread(&cf->len, sizeof(cf->len), 1, in);
+         if (do_swap) swap_4_bytes(&cf->len);
+         remaining = (char *) malloc(cf->len-8);
+         if (!remaining) {
+             perror("\ndorade_read_correction_factor_desc");
+             fprintf(stderr,"cf->len = %d\n\n", cf->len);
+             return NULL;
+         }
+         fread(remaining, sizeof(char), cf->len-8, in);
+         free(remaining);
+      }
+  }
+  fread(&cf->len, sizeof(Correction_factor_desc)-4, 1, in);
   /* Now, convert from Big Endian. */
-  if (little_endian()) {
+  if (do_swap) {
        swap_4_bytes(&cf->len);
        swap_4_bytes(&cf->azimuth);
        swap_4_bytes(&cf->elevation);
@@ -343,7 +416,7 @@ Sweep_info *dorade_read_sweep_info(FILE *in)
   }
 
   /* Now, convert from Big Endian. */
-  if (little_endian()) {
+  if (do_swap) {
        swap_4_bytes(&si->len);
        swap_4_bytes(&si->sweep_num);
        swap_4_bytes(&si->nrays);
@@ -375,7 +448,7 @@ Ray_info       *dorade_read_ray_info      (FILE *in)
 
   fread(ri, sizeof(Ray_info), 1, in);
   /* Now, convert from Big Endian. */
-  if (little_endian()) {
+  if (do_swap) {
        swap_4_bytes(&ri->len);
        swap_4_bytes(&ri->sweep_num);
        swap_4_bytes(&ri->jday);
@@ -401,6 +474,7 @@ Ray_info       *dorade_read_ray_info      (FILE *in)
 Platform_info  *dorade_read_platform_info (FILE *in)
 {
   Platform_info *pi;
+  int len_first_two;
 
   pi = (Platform_info *) calloc(1, sizeof(Platform_info));
   if(!pi) {
@@ -408,35 +482,61 @@ Platform_info  *dorade_read_platform_info (FILE *in)
        return NULL;
   }
 
-  fread(pi, sizeof(Platform_info), 1, in);
-  /* Now, convert from Big Endian. */
-  if (little_endian()) {
-       swap_4_bytes(&pi->len);
-       swap_4_bytes(&pi->longitude);
-       swap_4_bytes(&pi->latitude);
-       swap_4_bytes(&pi->altitude);
-       swap_4_bytes(&pi->height);
-       swap_4_bytes(&pi->ew_speed);
-       swap_4_bytes(&pi->ns_speed);
-       swap_4_bytes(&pi->v_speed);
-       swap_4_bytes(&pi->heading);
-       swap_4_bytes(&pi->roll);
-       swap_4_bytes(&pi->pitch);
-       swap_4_bytes(&pi->drift);
-       swap_4_bytes(&pi->rotation);
-       swap_4_bytes(&pi->tilt);
-       swap_4_bytes(&pi->ew_wind_speed);
-       swap_4_bytes(&pi->ns_wind_speed);
-       swap_4_bytes(&pi->v_wind_speed);
-       swap_4_bytes(&pi->heading_rate);
-       swap_4_bytes(&pi->pitch_rate);
+  /* Read the id code to make sure we have "ASIB" for platform info.  If
+   * id is ASIB, then read data into the Platform_info structure.  If it is
+   * XSTF, read and discard remainder of block, which will have a different
+   * size than Platform_info.  XSTF is undocumented, but apparently it takes
+   * the place of ASIB when radar is grounded.
+   */
+
+  fread(pi->code, sizeof(pi->code), 1, in);
+  fread(&pi->len, sizeof(pi->len), 1, in);
+  if (do_swap) swap_4_bytes(&pi->len);
+  len_first_two = sizeof(pi->code) + sizeof(pi->len);
+    
+  if (strncmp(pi->code, "ASIB", 4) == 0) {
+      fread(&pi->longitude, sizeof(Platform_info)-len_first_two, 1, in);
+      /* Read past any extra bytes. */
+      if (pi->len > sizeof(Platform_info)) {
+         if (read_extra_bytes(pi->len - sizeof(Platform_info), in) <= 0)
+             fprintf(stderr,"Called from %s, line: %d\n",__FILE__,__LINE__-1);
+      }
+      /* Now, convert from Big Endian. */
+      if (do_swap) {
+         swap_4_bytes(&pi->longitude);
+         swap_4_bytes(&pi->latitude);
+         swap_4_bytes(&pi->altitude);
+         swap_4_bytes(&pi->height);
+         swap_4_bytes(&pi->ew_speed);
+         swap_4_bytes(&pi->ns_speed);
+         swap_4_bytes(&pi->v_speed);
+         swap_4_bytes(&pi->heading);
+         swap_4_bytes(&pi->roll);
+         swap_4_bytes(&pi->pitch);
+         swap_4_bytes(&pi->drift);
+         swap_4_bytes(&pi->rotation);
+         swap_4_bytes(&pi->tilt);
+         swap_4_bytes(&pi->ew_wind_speed);
+         swap_4_bytes(&pi->ns_wind_speed);
+         swap_4_bytes(&pi->v_wind_speed);
+         swap_4_bytes(&pi->heading_rate);
+         swap_4_bytes(&pi->pitch_rate);
+      }
+  } else if (strncmp(pi->code, "XSTF", 4) == 0) {
+      /* Read to end of XSTF block. */
+      if (read_extra_bytes(pi->len - len_first_two, in) <= 0)
+          fprintf(stderr,"Called from %s, line: %d\n", __FILE__, __LINE__ - 1);
+  } else {
+      fprintf(stderr,"Unexpected block id: \"%s\"."
+          "  Expected \"ASIB\" or \"XSTF\"\n", pi->code);
   }
 
   return pi;
 }
+
 /**********************************************************************/
 /*                                                                    */
-/*                      dorade_read_parameter_info                    */
+/*                      dorade_read_parameter_data                    */
 /*                                                                    */
 /**********************************************************************/
 
@@ -454,7 +554,7 @@ Parameter_data *dorade_read_parameter_data(FILE *in)
   fread(&pd->code, sizeof(pd->code), 1, in);
   fread(&pd->len, sizeof(pd->len), 1, in);
   fread(&pd->name, sizeof(pd->name), 1, in);
-  if (little_endian()) swap_4_bytes(&pd->len);
+  if (do_swap) swap_4_bytes(&pd->len);
   /* Length is in parameter data block? or calculate if from pd->len. */
 
   len = pd->len  /* Use pd->len for now. */
@@ -553,7 +653,7 @@ Sweep_record *dorade_read_sweep(FILE *fp, Sensor_desc **sd)
                           parameter_desc[j]->parameter_type == 4)
                sr->data_ray[i]->word_size[j] = 4; /* 4 bytes per word */
                
-         if (little_endian()) { /* Numbers were read big-endian. */
+         if (do_swap) { /* Numbers were read big-endian. */
                if (sr->data_ray[i]->word_size[j] == 2)
                  for (k=0; k<len; k+=2)
                        swap_2_bytes(&pd->data[k]);
@@ -566,13 +666,6 @@ Sweep_record *dorade_read_sweep(FILE *fp, Sensor_desc **sd)
   return sr;
 }
 
-/**********************************************************************/
-/*                                                                    */
-/*                      dorade_read_ray                               */
-/*                                                                    */
-/**********************************************************************/
-Data_ray       *dorade_read_ray           (FILE *in);
-
 
 /* MEMORY MANAGEMENT ROUTINES */