source: trunk/WRF.COMMON/WRFV2/external/io_grib1/MEL_grib1/grib_seek.c

Last change on this file was 11, checked in by aslmd, 14 years ago

spiga@svn-planeto:ajoute le modele meso-echelle martien

File size: 19.0 KB
Line 
1/* File:  grib_seek.c           based on Decoder's trqgetmsg() func;
2   Revised by:
3   28oct96 Alice T. Nakajima (ATN), SAIC, Monterey
4   18jun97 ATN check Edition before reading in entire msg;
5   27aug97 ATN *SEEK_SET to 0 (gcc complains)
6   20Oct97 ATN print #bytes read when fread fails;
7   03nov97 ATN -Realloc
8   22oct98 ATN *error msg;
9*/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <math.h>
14#include "dprints.h"            /* for dprints */
15#include "gribfuncs.h"          /* prototypes */
16
17/*
18**********************************************************************
19* A.  FUNCTION: grib_seek
20*       search the input file starting at the given offset for a GRIB
21*       message.  If found, return it in GRIB_HDR structure.
22*
23*    INTERFACE:
24*       int grib_seek (InFile, offset, Read_Index,  gh, errmsg)
25*
26*    ARGUMENTS (I=input, O=output, I&O=input and output):
27*      (I)  char *InFile;
28*           name of input file to search for message;
29*     (I&O) long  *offset;
30*           number of bytes to skip from the beginning of file;
31*           gets updated upon leaving to absolute #bytes from beginning of
32*           file to beginning of message found;
33*      (I)  int  Read_Index;
34*           if set, only proceed if 'GRIB' starts exactly at the given
35*           byte offset;
36*      (O)  GRIB_HDR *gh;
37*           empty upon entry;  to hold the Message found and its info;
38*      (O)  char *errmsg;
39*           empty array, only filled if error occurred;
40*
41*    RETURN CODE: 
42*      0> no errors, may or may not have a valid message;
43*         If no Msg was Found:
44*          a)  errmsg will hold the Warning msg;
45*          If a valid Msg was Found:
46*          a) long *offset: if succesful, gets updated to absolute
47*             beginning of Mesg;
48*          b) struct GRIB_HDR holds its info:
49*            entire_msg:  is assigned to newly MAlloced
50*                    unsigned char * array to hold entire message;
51*            msg_length:  size of entire_msg array in bytes;
52*            ids_len, pds_len, gds_len, bms_len, bds_len, eds_len:
53*                    size of each defined sections in bytes;
54*            ids_ptr:  pts to message's Ident Data Sect;
55*            pds_ptr:  pts to message's Prod Defn Sect;
56*            gds_ptr:  pts to message's Grid Defn Sect;
57*            bms_ptr:  pts to message's Bitmap Defn Sect;
58*            bds_ptr:  pts to message's Binary Data Sect;
59*            eds_ptr:  pts to message's End Data Sect;
60*         c) errmsg remains empty;
61*      1> fseek/fread error, all ptrs in grib_hdr set to null; errmsg filled;
62*      2> got end of file, all ptrs in grib_hdr set to null; errmsg filled;
63*      3> Null entire_msg pointer; errmsg filled;
64*      4> unable to open input file; errmsg filled;
65*
66**********************************************************************
67*/
68
69#if PROTOTYPE_NEEDED
70int     grib_seek (     char *InFile, long *offset, int Read_Index, 
71                        GRIB_HDR *gh, char *errmsg)
72#else
73int     grib_seek (InFile, offset, Read_Index,gh,errmsg)
74                        char *InFile; 
75                        long *offset; 
76                        int Read_Index; 
77                        GRIB_HDR *gh;
78                        char *errmsg;
79#endif
80{
81   char *func="grib_seek";
82   FILE  *fp=NULL;
83   int status=0;
84
85   DPRINT3 ("Entering %s\nfile=%s, offs=%ld \n", func, InFile, *offset);
86
87/*
88*
89* A.2       OPEN Input file
90*           IF (fails) RETURN w/ error stat 4 !errmsg filled
91*/
92   if ((fp = fopen (InFile, "rb")) == NULL) {
93     DPRINT2 ("%s: Cannot open input file %s\n", func,InFile );
94     sprintf (errmsg,"%s: Cannot open input file '%s'\n", func,InFile );
95     status = 4;
96     goto DONE;
97   }
98
99   status = grib_fseek(fp,offset,Read_Index,gh,errmsg);
100
101DONE:
102/*
103*
104* A.4        CLOSE input file;     !get here when found no messages
105*
106*/
107   if (fp) fclose(fp); 
108
109/*
110* A.6        RETURN with status
111*/
112   return (status); 
113
114}
115
116
117
118#if PROTOTYPE_NEEDED
119int     grib_fseek (    FILE *fp, long *offset, int Read_Index, 
120                        GRIB_HDR *gh, char *errmsg)
121#else
122int     grib_fseek (fp, offset, Read_Index,gh,errmsg)
123                        FILE *fp; 
124                        long *offset; 
125                        int Read_Index; 
126                        GRIB_HDR *gh;
127                        char *errmsg;
128#endif
129 {
130   char *func="grib_fseek";
131   char  *GG, sm_blk[5004], *fwa_msg=NULL;
132   unsigned long lMessageSize;
133   unsigned long Edition;
134   long pos;            /* current byte offs fr. beg. of file */
135   int bytenum;         /* Index w/in sm_blk */
136   int bytestoread=5004; /* #bytes to read into sm_blk at a time */
137   int check_limit;     /* #bytes in sm_blk to check */ 
138   int gotone = 0;      /* set if found good msg */
139   int nread;           /* #bytes got back from Read */
140   int status;
141   unsigned long iskip;           /* for getbyte */
142   int gdsbmsflag, bit_set, sect_len; /* working vars */
143   char *ptr, *end_ptr;
144
145   DPRINT2 ("Entering %s\n, offs=%ld \n", func, *offset);
146/*
147* A.1       INIT variables
148*           !gh structure is cleared out
149*/
150   if (gh->entire_msg==NULL) {
151        DPRINT1 ( "%s:  expecting non-null Grib Hdr;\n",func);
152        sprintf(errmsg, "%s:  expecting non-NULL Grib Hdr;\n",func);
153        status= 3; 
154        goto DONE;
155        }
156
157   gh->msg_length = 0;
158   gh->ids_ptr=gh->pds_ptr= 0;
159   gh->gds_ptr=gh->bms_ptr=gh->bds_ptr=gh->eds_ptr=0;
160   memset ((void *)gh->entire_msg, '\0', gh->abs_size);
161   DPRINT2 ("gh= %ld, gh->entire_msg=%ld\n", gh, gh->entire_msg);
162
163/*
164*
165* A.3       FOR (loop while no error)     !read a block at a time
166*/
167   
168   for (status=0, pos= *offset, gotone= 0; status == 0; pos += check_limit)
169   {
170/*
171* A.3.1        IF (cannot SET file position to correct place)
172*              THEN
173*                 SET Status to 1 !fseek err
174*                 CONTINUE (Loop around to A.3)
175*              ENDIF
176*/
177     if (fseek(fp, pos, 0)!=0) { 
178        DPRINT2 ("%s: Got fseek error to pos= %ld\n",func, pos);
179        sprintf(errmsg,"%s: Got fseek error to pos= %ld\n",func,pos);
180        perror("");
181        status = 1; 
182        goto DONE; 
183        }
184
185/*
186* A.3.2        IF (read less than 40 bytes)
187*              THEN
188*                 FILL error buffer
189*                 RETURN status 2  !eof or <40 bytes left, errmsg filled
190*              ENDIF
191*/
192     nread= fread (sm_blk,sizeof(char), bytestoread,fp);
193     if (nread <= 40) 
194        { 
195          if (nread<=4) {
196                DPRINT0 ("No bytes left to check for msg;\n"); 
197                /* Errmsg left blank cuz its just EOF */
198                }
199          else {
200            sprintf(errmsg,"%s: skip last %d bytes, too few for a Msg\n",
201            func, nread);
202            DPRINT1 ("Only read %d bytes, too few to check for msg;\n",nread); 
203            }
204          status= 2; 
205          goto DONE; 
206        }
207     else check_limit= nread - 4; 
208
209/*
210*              ! search block for the next the 'G'
211*              ! load entire Msg if everything is ok;
212*              ! if No 'G' found, then quit right away if no 'G'
213*              ! if GRIB is not at absolute Offset address, quit too;
214*              !
215* A.3.3        WHILE (there is another 'G' in this block) DO
216*/
217     bytenum= 0;
218     while ((GG= (char *) memchr (sm_blk, 'G', check_limit)))
219        {
220/*--- Saw 'G' ---*/
221/*
222* A.3.3.1          IF ('RIB' is not after 'G') THEN
223*                     IF (Offset from Index file) THEN 
224*                        ABORT search;   !Break out of loop
225*                     ELSE
226*                        CLEAR out the 'G' in temp block
227*                        CONTINUE  !Loop around to A.3.3
228*                     ENDIF
229*                  ENDIF
230*/
231           if (strncmp(GG, "GRIB",4))    /* not 'RIB' after the 'G' */
232                if ( Read_Index) 
233                   break;     /* Offset IS from Indexfile:  Quit here */
234                else 
235                {             /* offset is NOT fr. IndexFile:  keep looping; */
236                   *GG='-';   /* no RIB after G, clear it               */
237                   continue;  /* let Memchr find next G in block        */
238                }
239
240/*--- Saw 'G R I B' ----*/
241/*
242* A.3.3.2           CALCULATE byte position within this block
243*                   where this message begins
244*/
245           bytenum = GG - sm_blk;  /* byte pos w/in this block */
246
247/*
248* A.3.3.3           IF (offset is from Indexfile  AND
249*                       string GRIB found is not at Absolute IndexFile's offset)
250*                   THEN abort search; ENDIF
251*/
252          DPRINT1 ("Found string 'GRIB' at %ld\n", pos+bytenum);
253          if (Read_Index &&  *offset != (bytenum + pos))  {
254              sprintf(errmsg,
255              "%s:   No Grib msg found at offset= %ld;  check Index File\n",
256              func, *offset);
257              break;            /* Abort here, Ret w/ no errros & no msg too */
258            }
259
260/*--- Read Mesg Length, Edition ---*/
261/*
262* A.3.3.4          FUNCTION gbyte !extract lMessageSize
263*/
264          iskip=32;
265          gbyte (sm_blk+bytenum ,&lMessageSize, &iskip,24);
266          DPRINT0 ("lMessageSize\n");
267
268/*--- Make sure it's Edition 1 first ---*/
269/*
270* A.3.3.5          FUNCTION gbyte !extract Grib Edition Number
271*                  IF (not edition 1) THEN
272*                      CLEAR out the 'G' in temp block
273*                      CONTINUE  !Loop around to A.3.3
274*                  ENDIF
275*/
276          gbyte (sm_blk+bytenum, &Edition, &iskip, 8);
277          DPRINT0 ("Edition\n");
278          if (Edition != 1) {
279              DPRINT1 ("Edition (%d) is not 1, start over\n",
280              Edition);
281              *GG='-';   /* blank out G of current GRIB location found */
282              continue;  /* let Memchr find next G in block        */
283           }
284
285
286/*
287* A.3.3.6          IF (cannot MOVE ptr to start of the message) THEN
288*                     RETURN status 1   !errmsg filled
289*                  ENDIF
290*/
291          if (fseek(fp, (long)(pos+bytenum), 0)!=0) {
292                DPRINT2 (
293                "%s: FSEEK error to pos+bytenum= %ld\n",
294                func, pos+bytenum);
295                sprintf(errmsg,
296                "%s: FSEEK error to pos+bytenum= %ld\n",
297                func, pos+bytenum);
298                status= 1;
299                goto DONE;
300                }
301
302/*
303* A.3.3.7          INIT all section length to zero
304*/
305          gh->ids_len= gh->pds_len= gh->gds_len= 0;
306          gh->bds_len= gh->bms_len= gh->eds_len= 0;
307
308/*
309* A.3.3.8          EXPAND Entire_Msg array if it's smaller than msglen
310*                  RETURN Malloc Err (stat=2) if fails  !errmsg filled
311*/
312           if (lMessageSize > gh->abs_size  ) {
313             
314/*            if (realloc((void *)gh->entire_msg, lMessageSize) == NULL) {..}
315*             gh->abs_size = lMessageSize;
316*/
317              if (Expand_gribhdr (gh, lMessageSize, errmsg)) {
318                  upd_child_errmsg (func, errmsg);
319                  status = 1;   /* to get out of Outer loop */
320                  goto DONE;
321               }
322
323              DPRINT1 ("Expanded entire_msg to be %ld bytes long\n",
324              gh->abs_size);
325            } /* size changed */
326
327/*--- READ ENTIRE MSG into GRIB HEADER's Entire_Msg ---*/
328/*
329*
330* A.3.3.9          READ the entire message into Grib Hdr's Entire_Msg;
331*                  IF (failed) THEN
332*                      RETURN Fread error stat=1  !errmsg filled
333*                  ENDIF
334*/
335          fwa_msg = (char *)gh->entire_msg;
336          if ((nread=fread (fwa_msg, 1, lMessageSize, fp)) != lMessageSize) 
337            {
338            DPRINT2 ( "%s:  failed to Fread EntireMsg (sz=%ld)\n",
339            func, lMessageSize);
340            sprintf(errmsg,
341            "%s has truncated msg @offs=%ld (got %ld out of %ld bytes)\n",
342            func, *offset, nread, lMessageSize);
343            status= 1;  /* to get out of Outer loop */
344            goto DONE;  /* get out of WHILE */
345            }
346
347/*--- if see '7777', asssign GH's pointers & len  ---*/
348/*
349* A.3.3.10         IF ('7777' is where expected) THEN
350*/
351          if (!strncmp((fwa_msg + lMessageSize - 4),"7777",4))
352                /*  && fwa_msg[7]==1)  */
353          { 
354                end_ptr = fwa_msg + lMessageSize;
355
356                DPRINT0 ("Found string '7777' where expected\n");
357                gh->msg_length= lMessageSize;
358/*
359* A.3.3.10.a.1         STORE loc & len of section 0 into Grib Hdr;
360*/
361                gh->ids_ptr= (unsigned char *)fwa_msg;    /* mark sect 0 */
362                gh->ids_len= 8L;
363
364/*
365* A.3.3.10.a.2         STORE loc & len of PDS into Grib Hdr;
366*                     FUNCTION gbyte   !get 3-byte length
367*/
368                ptr=  fwa_msg + gh->ids_len;
369                gh->pds_ptr= (unsigned char *)ptr;            /* mark PDS */
370                iskip= 0; gbyte(ptr ,(unsigned long *)&gh->pds_len,&iskip,24); 
371                DPRINT0 (" pds length\n");
372                iskip= 8*7; gbyte(ptr ,(unsigned long*)&gdsbmsflag, &iskip, 8);
373                DPRINT1 (" (%x hex) Gds/Bms flag\n", gdsbmsflag);
374/*
375* A.3.3.10.a.3         IF (location of next Section  is out of bound) THEN
376*                        PRINT message;
377*                        GOTO drop this msg;
378*                     ENDIF
379*/
380                ptr += gh->pds_len;
381                if (ptr > end_ptr) {
382                    sprintf(errmsg,
383                    "%s:  corrupt PDSlen= %ld, Totlen=%ld, drop msg @%ld;\n"
384                    , func,  gh->pds_len, gh->msg_length, *offset);
385                    gh->pds_len= 0;                  /* reset */
386                    goto DROPMSG_N_LOOP;
387                    }
388
389/*
390*                     IF (Debug) FUNCTION hdr_print  !print PDS
391*/
392                DPRINT1 ("gh->pds_len= %ld\n", gh->pds_len);
393                HDR_PRINT("Grib_Seek's PDS",gh->pds_ptr, gh->pds_len);
394
395/*
396* A.3.3.10.a.4         IF (GDS is present) THEN
397*                        STORE location & len of GDS into Grib Hdr's Gds_Ptr
398*                        FUNCTION gbyte   !get 3-byte length
399*                        IF (location of next Section  is out of bound) THEN
400*                           PRINT message;
401*                           DROP this msg & try to find another;
402*                        ENDIF
403*                        IF (Debug) FUNCTION hdr_print  !print GDS
404*                     ENDIF
405*/
406                bit_set= gdsbmsflag >> 7 & 1;   /* mark GDS if present */
407                if (bit_set) {
408                    gh->gds_ptr= (unsigned char *)ptr;
409                    iskip= 0; gbyte(ptr,(unsigned long*)&gh->gds_len,&iskip,24);
410                    DPRINT0 (" Gds length\n");
411                    ptr += gh->gds_len; /* bump PTR to sect*/
412                     if (ptr > end_ptr) {
413                       sprintf(errmsg,
414                       "%s: corrupt GDSlen= %ld, Totlen=%ld, drop msg @%ld\n"
415                        , func,  gh->gds_len, gh->msg_length, *offset);
416                        gh->gds_len= 0;                 /* reset */
417                        goto DROPMSG_N_LOOP;
418                        }
419                       DPRINT1 ("gh->gds_len= %ld\n", gh->gds_len);
420                       HDR_PRINT("Grib_Seek's GDS",gh->gds_ptr,gh->gds_len);
421                    }
422
423/*
424* A.3.3.10.a.5         IF (BMS is present) THEN
425*                        STORE location & len of BMS into Grib Hdr's Bms_Ptr
426*                        FUNCTION gbyte   !get 3-byte length
427*                        IF (location of next Section  is out of bound) THEN
428*                           PRINT message;
429*                           DROP this msg & try to find another;
430*                        ENDIF
431*                        IF (Debug) FUNCTION hdr_print   !byte dump
432*                     ENDIF
433*/
434                bit_set= gdsbmsflag >> 6 & 1;   /* mark BMS if present */
435                if (bit_set) {
436                    gh->bms_ptr= (unsigned char *)ptr; 
437                    iskip= 0; gbyte(ptr,(unsigned long*)&gh->bms_len,&iskip,24); 
438                    DPRINT0 (" Bms length\n");
439
440                    ptr += gh->bms_len;         /* bump PTR to sect */
441                    if (ptr > end_ptr) {
442                       sprintf(errmsg,
443                       "%s: corrupt BMSlen= %ld, Totlen=%ld, drop msg @%ld\n"
444                        , func, gh->bms_len, gh->msg_length, *offset);
445                        gh->bms_len= 0;                 /* reset */
446                        goto DROPMSG_N_LOOP;
447                        }
448                     DPRINT1 ("gh->bms_len= %ld\n", gh->bms_len);
449                     HDR_PRINT ("Grib_Seek's BMS", gh->bms_ptr, 
450                                (gh->bms_len>100? 100: gh->bms_len));
451                  }
452/*
453* A.3.3.10.a.6        STORE location and length of BDS into Grib Hdr's Bds_Ptr
454*                    FUNCTION gbyte !get 3-byte length
455*                    IF (location of next Section  is out of bound) THEN
456*                        PRINT message;
457*                        DROP this msg & try to find another;
458*                    ENDIF
459*                    IF (Debug) FUNCTION hdr_print   !byte dump
460*/
461
462                gh->bds_ptr= (unsigned char *)ptr;      /* mark BDS */
463                iskip= 0; gbyte(ptr,(unsigned long*)&gh->bds_len,&iskip,24);
464                DPRINT0 (" Bds length\n");
465
466                ptr += gh->bds_len;
467                if (ptr > end_ptr) {
468                    sprintf(errmsg,
469                    "%s:  corrupt BDSlen= %ld, Totlen=%ld, drop msg @%ld\n"
470                    , func, gh->gds_len, gh->msg_length, *offset);
471                    gh->gds_len= 0;  /* reset */
472                    goto DROPMSG_N_LOOP;
473                    }
474                    DPRINT1 ("gh->bds_len= %ld\n", gh->bds_len);
475                    HDR_PRINT ("Grib_Seek's BDS", gh->bds_ptr, 
476                        (gh->bds_len>100? 100: gh->bds_len));
477
478/*
479* A.3.3.10.a.7        STORE location & len of EDS into Grib Hdr's Eds_Ptr
480*/
481                gh->eds_ptr= (unsigned char *)ptr;  /* mark EDS */
482                gh->eds_len= 4;   
483
484/*
485* A.3.3.10.a.8        SET 'gotone' flag
486*                    ! Return with Msg in Grib hdr, and good stat
487*/
488                gotone=1;       /* to get out of FOR loop */
489                status=0;       /* Return with Msg , good stat */
490                goto DONE; 
491/*
492* A.3.3.10          ENDIF
493*/
494           } /* saw 77s  */
495        else 
496        if (Read_Index) {
497                sprintf(errmsg,
498                "%s:  no 7777 found for msg at %ld, check indexfile\n",
499                func, *offset);
500                }
501
502/*
503*
504*          !====================================================
505*          ! Drop Msg Area:   Only get here if :
506*          ! - first G found not at Indexfile's offset;
507*          ! - no RIB after G;
508*          ! - GRIB string found not at Indexfile's offset;
509*          ! - no 7777 at expected offset;
510*          ! - got Corrupted Length;
511*          !====================================================
512*/
513DROPMSG_N_LOOP:
514           /* ERRMSG must already be loaded and the corrupted len reset to 0
515              so that Display GH won't go out of bound...
516            */
517           DPRINT1 ("\nDropping, cause=> %s\n", errmsg);
518
519/*
520* A.3.3.11         IF (Debug mode) THEN
521*                     FUNCTION display_gribhdr    !show what got loaded sofar
522*                  ENDIF
523*/
524          if (gh->msg_length > 0) 
525          DISPLAY_GRIBHDR(gh); /* before dropping msg*/
526
527/*
528*                  ! no message found yet, OR Msg Section lens are corrupted
529* A.3.3.12         CLEAR out header struct   !data in array is not valid
530*/     
531          gh->msg_length =0;
532          gh->ids_ptr=gh->pds_ptr= gh->eds_ptr=0;
533          gh->gds_ptr=gh->bms_ptr=gh->bds_ptr= 0;
534          memset ((void *)gh->entire_msg, '\0', gh->abs_size);
535
536/*
537* A.3.3.13         IF (Offset was read from Indexfile)   !quit searching
538* A.3.3.13.a       THEN
539*                      PUT Error msg in buffer
540*                      RETURN with No Error status
541* A.3.3.13.b       ELSE
542*                      CLEAR out 'G' in tmp block        !go find next 'G'
543*                  ENDIF
544*/
545          if (Read_Index) {
546              status = 0;       /* Ret w/ no errors     */
547              goto DONE;        /* send CAUSE back in Errmsg */
548             }
549          else {
550             *GG='-';    /* let Memchr find next 'G' in curr. block */
551             DPRINT1 ("'GRIB' at location %ld is not a valid message\n",
552             bytenum+pos);
553             errmsg[0]='\0';  /* clear out buff */
554             }
555/*
556* A.3.3         ENDWHILE
557*/
558     }  /* WHILE seeing 'G'*/
559
560
561     if (Read_Index) {  /* Catch 3 cases:
562                         - if no 'G' at all ;
563                         - if no RIB after G ;
564                         - if found GRIB but not at expected place
565                        */
566           sprintf(errmsg,
567           "%s:  No Grib Msg found at IndexFile's offset = %ld; "\
568           " Check Index File\n" , func, *offset);
569           status = 0;  /* Return w/no errors  */
570           goto DONE;   /* but w/ Warn Msg in buff*/
571        }
572
573/*
574A.3.4           DEBUG print  !no Sect0 found in this block
575*/
576      DPRINT2 ("No Section 0 found between address %ld and %ld\n", 
577      pos, pos+check_limit);
578/*
579*
580* A.3       ENDFOR    !Outer Loop,  stay until Status changes
581*/
582  }  /* check entire file */
583
584
585
586DONE:
587
588/*
589*
590* A.5        IF (found a msg) THEN
591*                BUMP caller's Offset to absolute Begining of Msg found;
592*                DEBUG Print
593*            ENDIF
594*/
595   if (gotone) 
596       {
597       *offset = (long)(pos+bytenum);  /* bump offset to abs. beg. of Msg */
598       DPRINT3 ("Exiting %s w/stat=%d, offs=%d, msg in GRIB_HDR\n", 
599        func, status, *offset);
600       }
601   else DPRINT2 ("Exiting %s w/stat=%d, no messages\n", func, status);
602
603/*
604* A.6        RETURN with status
605*/
606   return (status); 
607/*
608*
609* END OF FUNCTION
610*
611*/
612}
Note: See TracBrowser for help on using the repository browser.