X-Git-Url: http://pileus.org/git/?p=~andy%2Frsl;a=blobdiff_plain;f=dorade.c;h=bf78a1c18d625aa6bfdbca998d8b866252e958df;hp=6c692bf5abb5092755a2b1205fdc0ab693340d9d;hb=e953e14aeb8c5b83435ee0103f3b069cc1875c96;hpb=012916676d26251849e408aaf574458e196df2c4 diff --git a/dorade.c b/dorade.c index 6c692bf..bf78a1c 100644 --- 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; incells; 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; kdata[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 */