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 */
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;
}
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;
}
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);
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;
}
/**********************************************************************/
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);
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;
}
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);
}
}
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]);
}
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) {
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);
}
/* 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);
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);
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) {
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 */
/* */
/**********************************************************************/
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. */
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]);
return sr;
}
-/**********************************************************************/
-/* */
-/* dorade_read_ray */
-/* */
-/**********************************************************************/
-Data_ray *dorade_read_ray (FILE *in);
-
/* MEMORY MANAGEMENT ROUTINES */