1 /*
2  * Copyright 2005-2018 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  *
7  * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
8  * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
9  */
10 
11 /***************************************************************************
12  *   Jean Baptiste Filippi - 01.11.2005
13  *   Enrico Fucile
14  *                                                                         *
15  ***************************************************************************/
16 #include "grib_api_internal.h"
17 
18 #if 0
19 /* #if GRIB_PTHREADS */
20  static pthread_once_t once  = PTHREAD_ONCE_INIT;
21  static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
22  static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
23  static void init() {
24     pthread_mutexattr_t attr;
25     pthread_mutexattr_init(&attr);
26     pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
27     pthread_mutex_init(&mutex1,&attr);
28     pthread_mutex_init(&mutex2,&attr);
29     pthread_mutexattr_destroy(&attr);
30  }
31  /* #elif GRIB_OMP_THREADS */
32  static int once = 0;
33  static omp_nest_lock_t mutex1;
34  static omp_nest_lock_t mutex2;
35  static void init()
36  {
37     GRIB_OMP_CRITICAL(lock_grib_handle_c)
38     {
39         if (once == 0)
40         {
41             omp_init_nest_lock(&mutex1);
42             omp_init_nest_lock(&mutex2);
43             once = 1;
44         }
45     }
46  }
47 #endif
48 
49 static grib_handle* grib_handle_new_from_file_no_multi ( grib_context* c, FILE* f,int headers_only,int *error );
50 static grib_handle* grib_handle_new_from_file_multi ( grib_context* c, FILE* f,int *error );
51 static int grib2_get_next_section ( unsigned char* msgbegin,size_t msglen,unsigned char** secbegin,size_t* seclen,int* secnum,int* err );
52 static int grib2_has_next_section ( unsigned char* msgbegin,size_t msglen,unsigned char* secbegin,size_t seclen,int* err );
53 static void grib2_build_message ( grib_context* context,unsigned char* sections[],size_t sections_len[],void** data,size_t* msglen );
54 static grib_multi_support* grib_get_multi_support ( grib_context* c, FILE* f );
55 static grib_multi_support* grib_multi_support_new ( grib_context* c );
56 static grib_handle* grib_handle_new_multi ( grib_context* c,unsigned char** idata,size_t *buflen,int* error );
57 
grib_section_create(grib_handle * h,grib_accessor * owner)58 grib_section* grib_section_create ( grib_handle* h,grib_accessor* owner )
59 {
60     grib_section* s = ( grib_section* ) grib_context_malloc_clear ( h->context,sizeof ( grib_section ) );
61     s->owner       = owner;
62     s->aclength   = NULL;
63     s->h          = h;
64     s->block      = ( grib_block_of_accessors* ) grib_context_malloc_clear ( h->context, sizeof ( grib_block_of_accessors ) );
65     return s;
66 }
67 
update_sections(grib_section * s,grib_handle * h,long offset)68 static void update_sections ( grib_section *s,grib_handle* h,long offset )
69 {
70     grib_accessor *a = s?s->block->first:NULL;
71     if ( s ) s->h = h;
72     while ( a )
73     {
74         a->offset += offset;
75         /* update_sections ( grib_get_sub_section ( a ),h,offset ); */
76         update_sections ( a->sub_section,h,offset );
77         a = a->next;
78     }
79 }
80 
grib_swap_sections(grib_section * the_old,grib_section * the_new)81 void grib_swap_sections ( grib_section* the_old, grib_section *the_new )
82 {
83     grib_accessor* a;
84     grib_block_of_accessors* b = the_old->block;
85 
86     /* printf("SWAPPING -----\n"); grib_dump_section_content(new,stdout); */
87     the_old->block = the_new->block;
88     the_new->block = b;
89 
90     a = the_old->aclength;
91     the_old->aclength = the_new->aclength;
92     the_new->aclength = a;
93 
94     a = the_old->block->first;
95     while ( a )
96     {
97         a->parent = the_old;
98         a = a->next;
99     }
100 
101     update_sections ( the_old, the_old->h, the_old->owner->offset );
102     /* update_sections(new,new->h,new->owner->offset); */
103 
104     /* printf("SWAPPING -----\n"); grib_dump_section_content(old,stdout); */
105 
106 }
107 
grib_empty_section(grib_context * c,grib_section * b)108 void grib_empty_section ( grib_context   *c,grib_section* b )
109 {
110     grib_accessor* current = NULL;
111     if ( !b ) return;
112 
113     b->aclength = NULL;
114 
115     current = b->block->first;
116 
117     while ( current )
118     {
119         grib_accessor* next = current->next;
120         grib_accessor_delete ( c,current );
121         current = next;
122     }
123     b->block->first = b->block->last = 0;
124 }
125 
grib_section_delete(grib_context * c,grib_section * b)126 void grib_section_delete ( grib_context   *c, grib_section* b )
127 {
128     if ( !b ) return;
129 
130     grib_empty_section ( c,b );
131     grib_context_free ( c,b->block );
132     grib_context_free ( c,b );
133 }
134 
grib_handle_delete(grib_handle * h)135 int grib_handle_delete ( grib_handle* h )
136 {
137     if ( h != NULL )
138     {
139         grib_context   *ct =h->context;
140         grib_dependency *d = h->dependencies;
141         grib_dependency *n;
142 
143         Assert ( h->kid == NULL );
144 
145         while ( d )
146         {
147             n = d->next;
148             grib_context_free ( ct,d );
149             d = n;
150         }
151         h->dependencies=0;
152 
153         grib_buffer_delete ( ct,h->buffer );
154         grib_section_delete ( ct,h->root );
155 
156         grib_context_log ( ct,GRIB_LOG_DEBUG,"grib_handle_delete: deleting handle %p",h );
157         grib_context_free ( ct,h );
158         h=NULL;
159     }
160     return GRIB_SUCCESS;
161 }
162 
grib_new_handle(grib_context * c)163 grib_handle* grib_new_handle ( grib_context* c )
164 {
165     grib_handle    *g = NULL;
166     if ( c == NULL ) c = grib_context_get_default();
167     g = ( grib_handle* ) grib_context_malloc_clear ( c,sizeof ( grib_handle ) );
168 
169     if ( g == NULL ) {
170         grib_context_log ( c,GRIB_LOG_ERROR,"grib_new_handle: cannot allocate handle" );
171     } else {
172         g->context = c;
173     }
174 
175     grib_context_log ( c,GRIB_LOG_DEBUG,"grib_new_handle: allocated handle %p",g );
176 
177     return g;
178 }
179 
grib_handle_create(grib_handle * gl,grib_context * c,void * data,size_t buflen)180 static grib_handle* grib_handle_create ( grib_handle  *gl, grib_context* c,void* data, size_t buflen )
181 {
182     grib_action* next = NULL;
183     int err = 0;
184 
185     if ( gl == NULL )
186         return NULL;
187 
188     gl->use_trie = 1;
189     gl->trie_invalid=0;
190     gl->buffer = grib_new_buffer ( gl->context,(unsigned char*)data,buflen );
191 
192     if ( gl->buffer == NULL )
193     {
194         grib_handle_delete ( gl );
195         return NULL;
196     }
197 
198     gl->root     = grib_create_root_section ( gl->context,gl );
199 
200     if ( !gl->root )
201     {
202         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_message: cannot create root section" );
203         grib_handle_delete ( gl );
204         return NULL;
205     }
206 
207     if ( !gl->context->grib_reader || !gl->context->grib_reader->first )
208     {
209         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_message: cannot create handle, no definitions found" );
210         grib_handle_delete ( gl );
211         return NULL;
212     }
213 
214     gl->buffer->property = GRIB_USER_BUFFER;
215 
216     next = gl->context->grib_reader->first->root;
217     while ( next )
218     {
219         if ( grib_create_accessor ( gl->root, next, NULL ) != GRIB_SUCCESS )
220             break;
221         next = next->next;
222     }
223 
224     err = grib_section_adjust_sizes ( gl->root,0,0 );
225     if (err)
226     {
227         grib_handle_delete ( gl );
228         return NULL;
229     }
230 
231     grib_section_post_init ( gl->root );
232 
233     return gl;
234 }
235 
grib_handle_new_from_template(grib_context * c,const char * name)236 grib_handle* grib_handle_new_from_template ( grib_context* c, const char* name )
237 {
238 	if ( !c ) c=grib_context_get_default();
239 	/*grib_context_log(c,GRIB_LOG_WARNING,"grib_handle_new_from_template function is deprecated, please use grib_handle_new_from_samples\n");*/
240 	return grib_handle_new_from_samples ( c,name );
241 }
242 
grib_handle_new_from_samples(grib_context * c,const char * name)243 grib_handle* grib_handle_new_from_samples ( grib_context* c, const char* name )
244 {
245     grib_handle* g = 0;
246     if ( c == NULL ) c = grib_context_get_default();
247     grib_context_set_handle_file_count(c,0);
248     grib_context_set_handle_total_count(c,0);
249 
250     /*
251 	   g = grib_internal_template(c,name);
252 	   if(g) return g;
253      */
254     if (c->debug) {
255         printf("GRIB_API DEBUG: grib_handle_new_from_samples '%s'\n", name);
256     }
257 
258     g=grib_external_template ( c,name );
259     if ( !g )
260         grib_context_log ( c,GRIB_LOG_ERROR,"Unable to load sample file %s.tmpl\n                    in %s",
261                 name, c->grib_samples_path );
262 
263     return g;
264 }
265 
grib_write_message(grib_handle * h,const char * file,const char * mode)266 int grib_write_message(grib_handle* h,const char* file,const char* mode)
267 {
268     FILE* fh=0;
269     int err;
270     const void *buffer; size_t size;
271 
272     fh=fopen(file,mode);
273     if (!fh) {
274         perror(file);
275         return GRIB_IO_PROBLEM;
276     }
277     err=grib_get_message(h,&buffer,&size);
278     if (err) {
279         fclose(fh);
280         return err;
281     }
282 
283     if(fwrite(buffer,1,size,fh) != size) {
284         perror(file);
285         fclose(fh);
286         return GRIB_IO_PROBLEM;
287     }
288     if (fclose(fh) != 0) {
289         perror(file);
290         return GRIB_IO_PROBLEM;
291     }
292     return 0;
293 }
294 
grib_handle_clone(grib_handle * h)295 grib_handle* grib_handle_clone ( grib_handle* h )
296 {
297     return grib_handle_new_from_message_copy ( h->context, h->buffer->data, h->buffer->ulength );
298 }
299 
grib_handle_new_from_message_copy(grib_context * c,const void * data,size_t size)300 grib_handle* grib_handle_new_from_message_copy ( grib_context* c, const void* data, size_t size )
301 {
302     grib_handle *g = NULL;
303     void* copy =NULL;
304     if ( c == NULL ) c = grib_context_get_default();
305 
306     grib_context_set_handle_file_count(c,0);
307     grib_context_set_handle_total_count(c,0);
308     copy = grib_context_malloc ( c,size );
309     if ( !copy ) {
310         return NULL;
311     }
312 
313     memcpy ( copy,data,size );
314 
315     g = grib_handle_new_from_message ( c,copy, size );
316     g->buffer->property = GRIB_MY_BUFFER;
317 
318     return g;
319 }
320 
grib_handle_new_from_partial_message_copy(grib_context * c,const void * data,size_t size)321 grib_handle* grib_handle_new_from_partial_message_copy ( grib_context* c, const void* data, size_t size )
322 {
323     grib_handle *g = NULL;
324     void* copy =NULL;
325     if ( c == NULL ) c = grib_context_get_default();
326     grib_context_set_handle_file_count(c,0);
327     grib_context_set_handle_total_count(c,0);
328     copy = grib_context_malloc ( c,size );
329     if ( !copy )
330         return NULL;
331 
332     memcpy ( copy,data,size );
333 
334     g = grib_handle_new_from_partial_message ( c,copy, size );
335     g->buffer->property = GRIB_MY_BUFFER;
336 
337     return g;
338 }
339 
grib_handle_new_from_partial_message(grib_context * c,void * data,size_t buflen)340 grib_handle* grib_handle_new_from_partial_message ( grib_context* c,void* data, size_t buflen )
341 {
342     grib_handle  *gl = NULL;
343     if ( c == NULL ) c = grib_context_get_default();
344     grib_context_set_handle_file_count(c,0);
345     grib_context_set_handle_total_count(c,0);
346     gl = grib_new_handle ( c );
347     gl->partial = 1;
348     return grib_handle_create ( gl,  c, data,  buflen );
349 }
350 
grib_handle_new_from_message(grib_context * c,void * data,size_t buflen)351 grib_handle* grib_handle_new_from_message ( grib_context* c,void* data, size_t buflen )
352 {
353     grib_handle  *gl = NULL;
354     grib_handle  *h = NULL;
355     if ( c == NULL ) c = grib_context_get_default();
356     gl = grib_new_handle ( c );
357     h=grib_handle_create ( gl,  c, data,  buflen );
358     return h;
359 }
360 
grib_handle_new_from_multi_message(grib_context * c,void ** data,size_t * buflen,int * error)361 grib_handle* grib_handle_new_from_multi_message ( grib_context* c,void** data,
362         size_t *buflen,int* error )
363 {
364     grib_handle  *h = NULL;
365     unsigned char** d= ( unsigned char** ) data;
366     if ( c == NULL ) c = grib_context_get_default();
367 
368     if ( c->multi_support_on ) h=grib_handle_new_multi ( c,d,  buflen,error );
369     else
370     {
371         size_t olen=0;
372         void * message=NULL;
373         *error = grib_read_any_from_memory_alloc ( c, d,buflen,&message, &olen );
374         if ( message==NULL ) return NULL;
375         h = grib_new_handle ( c );
376         grib_handle_create ( h,  c, message,  olen );
377     }
378 
379     return h;
380 }
381 
grib_handle_new_from_file(grib_context * c,FILE * f,int * error)382 grib_handle* grib_handle_new_from_file ( grib_context* c, FILE* f,int *error )
383 {
384     return eccode_grib_new_from_file(c,f,0,error);
385 }
386 
grib_handle_new_multi(grib_context * c,unsigned char ** data,size_t * buflen,int * error)387 static grib_handle* grib_handle_new_multi ( grib_context* c,unsigned char** data,
388         size_t *buflen,int* error )
389 {
390     void * message=NULL;
391     size_t olen = 0,len=0;
392     grib_handle  *gl = NULL;
393     long edition=0;
394     size_t seclen=0;
395     unsigned char* secbegin=0;
396     int secnum=0,seccount=0;
397     int err=0,i=0;
398     grib_multi_support* gm=NULL;
399 
400     if ( c == NULL ) c = grib_context_get_default();
401 
402     gm=grib_get_multi_support ( c,0 );
403 
404     if ( !gm->message )
405     {
406         *error = grib_read_any_from_memory_alloc ( c, data,buflen,&message, &olen );
407         gm->message_length=olen;
408         gm->message=(unsigned char*)message;
409         if ( *error != GRIB_SUCCESS || !message )
410         {
411             if ( *error == GRIB_END_OF_FILE ) *error = GRIB_SUCCESS;
412             gm->message_length = 0;
413             return NULL;
414         }
415     }
416     else
417     {
418         message=gm->message;
419     }
420 
421     edition=grib_decode_unsigned_byte_long ( (const unsigned char*)message,7,1 );
422 
423     if ( edition == 2 )
424     {
425         olen=gm->message_length;
426         if ( gm->section_number == 0 )
427         {
428             gm->sections[0]=(unsigned char*)message;
429         }
430         secbegin=gm->sections[gm->section_number];
431         seclen=gm->sections_length[gm->section_number];
432         secnum=gm->section_number;
433         seccount=0;
434         while ( grib2_get_next_section ( (unsigned char*)message,olen,&secbegin,&seclen,&secnum,&err ) )
435         {
436             seccount++;
437             /*printf("   - %d - section %d length=%d\n",(int)seccount,(int)secnum,(int)seclen);*/
438 
439             gm->sections[secnum]=secbegin;
440             gm->sections_length[secnum]=seclen;
441 
442             if ( secnum == 6 )
443             {
444                 /* Special case for inherited bitmaps */
445                 if ( grib_decode_unsigned_byte_long ( secbegin,5,1 ) == 254 )
446                 {
447                     if ( !gm->bitmap_section )
448                     {
449                         grib_context_log ( c, GRIB_LOG_ERROR,
450                                 "grib_handle_new_from_file : cannot create handle, missing bitmap\n" );
451                         return NULL;
452                     }
453                     gm->sections[secnum]= gm->bitmap_section;
454                     gm->sections_length[secnum]=gm->bitmap_section_length;
455                 }
456                 else
457                 {
458                     if ( gm->bitmap_section )
459                     {
460                         grib_context_free ( c,gm->bitmap_section );
461                         gm->bitmap_section=NULL;
462                     }
463                     gm->bitmap_section = ( unsigned char* ) grib_context_malloc ( c,seclen );
464                     gm->bitmap_section = (unsigned char*)memcpy ( gm->bitmap_section,secbegin,seclen );
465                     gm->bitmap_section_length=seclen;
466                 }
467             }
468 
469             if ( secnum == 7 )
470             {
471                 void* p=message;
472                 len=olen;
473                 grib2_build_message ( c,gm->sections,gm->sections_length,&message,&len );
474 
475                 if ( grib2_has_next_section ( (unsigned char*)p,olen,secbegin,seclen,&err ) )
476                 {
477                     gm->message=(unsigned char*)p;
478                     gm->section_number=secnum;
479                     olen=len;
480                 }
481                 else
482                 {
483                     grib_context_free ( c,gm->message );
484                     gm->message=NULL;
485                     for ( i=0;i<8;i++ ) gm->sections[i]=NULL;
486                     gm->section_number=0;
487                     gm->message_length=0;
488                     olen=len;
489                 }
490 
491                 break;
492             }
493         }
494 
495     }
496     else
497     {
498         gm->message_length=0;
499         gm->message=NULL;
500     }
501 
502     gl = grib_handle_new_from_message ( c, message, olen );
503     if ( !gl )
504     {
505         *error = GRIB_DECODING_ERROR;
506         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle \n" );
507         return NULL;
508     }
509 
510     gl->buffer->property = GRIB_MY_BUFFER;
511     grib_context_increment_handle_file_count(c);
512     grib_context_increment_handle_total_count(c);
513 
514     return gl;
515 }
516 
grib_handle_new_from_file_multi(grib_context * c,FILE * f,int * error)517 static grib_handle* grib_handle_new_from_file_multi ( grib_context* c, FILE* f,int *error )
518 {
519     void* data = NULL,*old_data=NULL;
520     size_t olen = 0,len=0;
521     grib_handle  *gl = NULL;
522     long edition=0;
523     size_t seclen=0;
524     unsigned char* secbegin=0;
525     int secnum=0,seccount=0;
526     int err=0,i=0;
527     grib_multi_support* gm=NULL;
528     off_t gts_header_offset=0;
529     off_t end_msg_offset=0,offset=0;
530     char *gts_header=0,*save_gts_header=0;
531     int gtslen=0;
532 
533     if ( c == NULL ) c = grib_context_get_default();
534 
535     gm=grib_get_multi_support ( c,f );
536 
537     if ( !gm->message )
538     {
539         gts_header_offset=grib_context_tell( c,f);
540         data = wmo_read_grib_from_file_malloc ( f,0, &olen,&offset,error );
541         end_msg_offset=grib_context_tell ( c,f );
542 
543         gm->message_length=olen;
544         gm->message=(unsigned char*)data;
545         gm->offset=offset;
546         if ( *error != GRIB_SUCCESS || !data )
547         {
548             if ( data ) grib_context_free ( c,data );
549 
550             if ( *error == GRIB_END_OF_FILE ) *error = GRIB_SUCCESS;
551             gm->message_length = 0;
552             gm->message=NULL;
553             return NULL;
554         }
555         if ( c->gts_header_on )
556         {
557             int g=0;
558             grib_context_seek ( c,gts_header_offset,SEEK_SET,f );
559             gtslen=offset-gts_header_offset;
560             gts_header=(char *)grib_context_malloc_clear ( c,sizeof ( unsigned char ) *gtslen );
561             save_gts_header=gts_header;
562             grib_context_read ( c,gts_header,gtslen,f );
563             g=gtslen;
564             while ( gts_header!=NULL && g != 0 && *gts_header != '\03' )
565             {
566                 /*printf("--------%d %X \n",gtslen,*gts_header);*/
567                 gts_header++;
568                 g--;
569             }
570             if ( g>8 ) {gts_header++;gtslen=g-1;}
571             else gts_header=save_gts_header;
572             grib_context_seek ( c,end_msg_offset,SEEK_SET,f );
573         }
574 
575     }
576     else
577         data=gm->message;
578 
579     edition=grib_decode_unsigned_byte_long ( (const unsigned char*)data,7,1 );
580 
581     if ( edition == 2 )
582     {
583         olen=gm->message_length;
584         if ( gm->section_number == 0 )
585         {
586             gm->sections[0]=(unsigned char*)data;
587         }
588         secbegin=gm->sections[gm->section_number];
589         seclen=gm->sections_length[gm->section_number];
590         secnum=gm->section_number;
591         seccount=0;
592         while ( grib2_get_next_section ( (unsigned char*)data,olen,&secbegin,&seclen,&secnum,&err ) )
593         {
594             seccount++;
595             /*printf("   - %d - section %d length=%d\n",(int)seccount,(int)secnum,(int)seclen);*/
596 
597             gm->sections[secnum]=secbegin;
598             gm->sections_length[secnum]=seclen;
599 
600             if ( secnum == 6 )
601             {
602                 /* Special case for inherited bitmaps */
603                 if ( grib_decode_unsigned_byte_long ( secbegin,5,1 ) == 254 )
604                 {
605                     if ( !gm->bitmap_section )
606                     {
607                         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle, missing bitmap\n" );
608                         grib_context_free ( c,data );
609                         return NULL;
610                     }
611                     gm->sections[secnum]= gm->bitmap_section;
612                     gm->sections_length[secnum]=gm->bitmap_section_length;
613                 }
614                 else
615                 {
616                     if ( gm->bitmap_section )
617                     {
618                         grib_context_free ( c,gm->bitmap_section );
619                         gm->bitmap_section=NULL;
620                     }
621                     gm->bitmap_section = ( unsigned char* ) grib_context_malloc ( c,seclen );
622                     gm->bitmap_section = (unsigned char*)memcpy ( gm->bitmap_section,secbegin,seclen );
623                     gm->bitmap_section_length=seclen;
624                 }
625             }
626 
627             if ( secnum == 7 )
628             {
629                 old_data=data;
630                 len=olen;
631                 grib2_build_message ( c,gm->sections,gm->sections_length,&data,&len );
632 
633                 if ( grib2_has_next_section ( (unsigned char*)old_data,olen,secbegin,seclen,&err ) )
634                 {
635                     gm->message=(unsigned char*)old_data;
636                     gm->section_number=secnum;
637                     olen=len;
638                 }
639                 else
640                 {
641                     if ( gm->message ) grib_context_free ( c,gm->message );
642                     gm->message=NULL;
643                     for ( i=0;i<8;i++ ) gm->sections[i]=NULL;
644                     gm->section_number=0;
645                     gm->message_length=0;
646                     olen=len;
647                 }
648                 break;
649             }
650         }
651 
652     }
653     else
654     {
655         gm->message_length=0;
656         gm->message=NULL;
657     }
658 
659     gl = grib_handle_new_from_message ( c, data, olen );
660     if ( !gl )
661     {
662         *error = GRIB_DECODING_ERROR;
663         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle \n" );
664         grib_context_free ( c,data );
665         return NULL;
666     }
667 
668     gl->offset=gm->offset;
669     gl->buffer->property = GRIB_MY_BUFFER;
670     grib_context_increment_handle_file_count(c);
671     grib_context_increment_handle_total_count(c);
672 
673     if ( c->gts_header_on && gtslen >=8 )
674     {
675         gl->gts_header=(char*)grib_context_malloc_clear ( c,sizeof ( unsigned char ) *gtslen );
676         memcpy ( gl->gts_header,gts_header,gtslen );
677         gl->gts_header_len=gtslen;
678         grib_context_free ( c,save_gts_header );
679         gtslen=0;
680     } else gl->gts_header=NULL;
681 
682     return gl;
683 }
684 
eccode_grib_new_from_file(grib_context * c,FILE * f,int headers_only,int * error)685 grib_handle* eccode_grib_new_from_file ( grib_context* c, FILE* f,int headers_only,int *error )
686 {
687     grib_handle* h=0;
688     if (!f) {*error=GRIB_IO_PROBLEM; return NULL;}
689 
690     if ( c == NULL ) c = grib_context_get_default();
691 
692     if ( c->multi_support_on ) h=grib_handle_new_from_file_multi ( c,f,error );
693     else h=grib_handle_new_from_file_no_multi ( c,f,headers_only,error );
694 
695     if ( h && h->offset == 0 ) grib_context_set_handle_file_count(c,1);
696 
697     if ( !c->no_fail_on_wrong_length && *error == GRIB_WRONG_LENGTH )
698     {
699         grib_handle_delete ( h );
700         h=NULL;
701     }
702 
703     return h;
704 }
705 
eccode_gts_new_from_file(grib_context * c,FILE * f,int headers_only,int * error)706 grib_handle* eccode_gts_new_from_file ( grib_context* c, FILE* f,int headers_only,int *error )
707 {
708     void *data = NULL;
709     size_t olen = 0;
710     grib_handle  *gl = NULL;
711     off_t offset=0;
712 
713     if ( c == NULL ) c = grib_context_get_default();
714 
715     data = wmo_read_gts_from_file_malloc ( f, headers_only,&olen,&offset,error );
716 
717     if ( *error != GRIB_SUCCESS )
718     {
719         if ( data ) grib_context_free ( c,data );
720 
721         if ( *error == GRIB_END_OF_FILE ) *error = GRIB_SUCCESS;
722         return NULL;
723     }
724 
725     if (headers_only) {
726         gl = grib_handle_new_from_partial_message ( c, data, olen );
727     } else {
728         gl = grib_handle_new_from_message ( c, data, olen );
729     }
730 
731     if ( !gl )
732     {
733         *error = GRIB_DECODING_ERROR;
734         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle \n" );
735         grib_context_free ( c,data );
736         return NULL;
737     }
738 
739     gl->offset=offset;
740     gl->buffer->property = GRIB_MY_BUFFER;
741     grib_context_increment_handle_file_count(c);
742     grib_context_increment_handle_total_count(c);
743 
744     return gl;
745 }
746 
eccode_bufr_new_from_file(grib_context * c,FILE * f,int headers_only,int * error)747 grib_handle* eccode_bufr_new_from_file ( grib_context* c, FILE* f,int headers_only,int *error )
748 {
749     void *data = NULL;
750     size_t olen = 0;
751     grib_handle  *gl = NULL;
752     off_t offset=0;
753 
754     if ( c == NULL ) c = grib_context_get_default();
755 
756     data = wmo_read_bufr_from_file_malloc ( f, headers_only,&olen,&offset,error );
757 
758     if ( *error != GRIB_SUCCESS )
759     {
760         if ( data ) grib_context_free ( c,data );
761 
762         if ( *error == GRIB_END_OF_FILE ) *error = GRIB_SUCCESS;
763         return NULL;
764     }
765 
766     if (headers_only) {
767         gl = grib_handle_new_from_partial_message ( c, data, olen );
768     } else {
769         gl = grib_handle_new_from_message ( c, data, olen );
770     }
771 
772     if ( !gl )
773     {
774         *error = GRIB_DECODING_ERROR;
775         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle \n" );
776         grib_context_free ( c,data );
777         return NULL;
778     }
779 
780     gl->offset=offset;
781     gl->buffer->property = GRIB_MY_BUFFER;
782     grib_context_increment_handle_file_count(c);
783     grib_context_increment_handle_total_count(c);
784 
785     return gl;
786 }
787 
eccode_any_new_from_file(grib_context * c,FILE * f,int headers_only,int * error)788 grib_handle* eccode_any_new_from_file ( grib_context* c, FILE* f,int headers_only,int *error )
789 {
790     void *data = NULL;
791     size_t olen = 0;
792     grib_handle  *gl = NULL;
793     off_t offset=0;
794 
795     if ( c == NULL ) c = grib_context_get_default();
796 
797     data = wmo_read_any_from_file_malloc ( f, headers_only,&olen,&offset,error );
798 
799     if ( *error != GRIB_SUCCESS )
800     {
801         if ( data ) grib_context_free ( c,data );
802 
803         if ( *error == GRIB_END_OF_FILE ) *error = GRIB_SUCCESS;
804         return NULL;
805     }
806 
807     if (headers_only) {
808         gl = grib_handle_new_from_partial_message ( c, data, olen );
809     } else {
810         gl = grib_handle_new_from_message ( c, data, olen );
811     }
812 
813     if ( !gl )
814     {
815         *error = GRIB_DECODING_ERROR;
816         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle \n" );
817         grib_context_free ( c,data );
818         return NULL;
819     }
820 
821     gl->offset=offset;
822     gl->buffer->property = GRIB_MY_BUFFER;
823     grib_context_increment_handle_file_count(c);
824     grib_context_increment_handle_total_count(c);
825 
826     return gl;
827 }
828 
grib_handle_new_from_file_no_multi(grib_context * c,FILE * f,int headers_only,int * error)829 static grib_handle* grib_handle_new_from_file_no_multi ( grib_context* c,FILE* f,int headers_only,int *error )
830 {
831     void *data = NULL;
832     size_t olen = 0;
833     grib_handle  *gl = NULL;
834     off_t gts_header_offset=0;
835     off_t offset=0,end_msg_offset=0;
836     char *gts_header=0,*save_gts_header=0;
837     int gtslen=0;
838 
839     if ( c == NULL ) c = grib_context_get_default();
840     data = wmo_read_grib_from_file_malloc ( f, headers_only,&olen,&offset,error );
841     end_msg_offset=offset+olen;
842 
843     if ( *error != GRIB_SUCCESS )
844     {
845         if ( data ) grib_context_free ( c,data );
846 
847         if ( *error == GRIB_END_OF_FILE ) *error = GRIB_SUCCESS;
848         return NULL;
849     }
850 
851     if ( c->gts_header_on )
852     {
853         int g=0;
854         grib_context_seek ( c,gts_header_offset,SEEK_SET,f );
855         gtslen=offset-gts_header_offset;
856         gts_header=(char*)grib_context_malloc ( c,sizeof ( unsigned char ) *gtslen );
857         save_gts_header=gts_header;
858         grib_context_read ( c,gts_header,gtslen,f );
859         g=gtslen;
860         while ( gts_header!=NULL && g != 0 && *gts_header != '\03' )
861         {
862             /*printf("--------%d %X \n",gtslen,*gts_header);*/
863             gts_header++;
864             g--;
865         }
866         if ( g>8 ) {gts_header++;gtslen=g-1;}
867         else gts_header=save_gts_header;
868         grib_context_seek ( c,end_msg_offset,SEEK_SET,f );
869     }
870 
871     if (headers_only) {
872         gl = grib_handle_new_from_partial_message ( c, data, olen );
873     } else {
874         gl = grib_handle_new_from_message ( c, data, olen );
875     }
876 
877     if ( !gl )
878     {
879         *error = GRIB_DECODING_ERROR;
880         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_file : cannot create handle \n" );
881         grib_context_free ( c,data );
882         return NULL;
883     }
884 
885     gl->offset=offset;
886     gl->buffer->property = GRIB_MY_BUFFER;
887 
888     grib_context_increment_handle_file_count(c);
889     grib_context_increment_handle_total_count(c);
890 
891     if ( c->gts_header_on && gtslen >=8 )
892     {
893         gl->gts_header=(char*)grib_context_malloc ( c,sizeof ( unsigned char ) *gtslen );
894         memcpy ( gl->gts_header,gts_header,gtslen );
895         gl->gts_header_len=gtslen;
896         grib_context_free ( c,save_gts_header );
897         gtslen=0;
898     }
899 
900     return gl;
901 }
902 
grib_multi_handle_new(grib_context * c)903 grib_multi_handle* grib_multi_handle_new ( grib_context* c )
904 {
905     grib_multi_handle* h;
906     if ( c==NULL ) c=grib_context_get_default();
907     if ( !c->multi_support_on ) c->multi_support_on=1;
908 
909     h= ( grib_multi_handle* ) grib_context_malloc_clear ( c,sizeof ( grib_multi_handle ) );
910     if ( h==NULL )
911     {
912         grib_context_log ( c,GRIB_LOG_ERROR,
913                 "grib_multi_handle_new: unable to allocate memory. %s",
914                 grib_get_error_message ( GRIB_OUT_OF_MEMORY ) );
915         return NULL;
916     }
917     h->buffer = grib_create_growable_buffer ( c );
918     h->buffer->ulength=0;
919     h->context=c;
920 
921     return h;
922 }
923 
grib_multi_handle_delete(grib_multi_handle * h)924 int grib_multi_handle_delete ( grib_multi_handle* h )
925 {
926     if ( h==NULL ) return GRIB_SUCCESS;
927 
928     grib_buffer_delete ( h->context,h->buffer );
929     grib_context_free ( h->context,h );
930     return GRIB_SUCCESS;
931 }
932 
grib_multi_handle_append(grib_handle * h,int start_section,grib_multi_handle * mh)933 int grib_multi_handle_append ( grib_handle* h,int start_section,grib_multi_handle* mh )
934 {
935     const void* mess=NULL;
936     unsigned char* p=NULL;
937     int err=0;
938     size_t mess_len = 0;
939     size_t total_len=0;
940 
941     if ( !h )  return GRIB_NULL_HANDLE;
942     if ( !mh ) return GRIB_NULL_HANDLE;
943 
944     if ( start_section==0 || mh->buffer->ulength==0 )
945     {
946         err=grib_get_message ( h,&mess,&mess_len );
947         if ( err!=0 ) return err;
948         total_len=mh->buffer->ulength+mess_len;
949 
950         if ( total_len > mh->buffer->length )
951             grib_grow_buffer ( h->context,mh->buffer,total_len );
952 
953         p=mh->buffer->data+mh->buffer->ulength;
954         memcpy ( p,mess,mess_len );
955         mh->offset=mh->buffer->ulength;
956         mh->buffer->ulength=total_len;
957         mh->length=mess_len;
958 
959     }
960     else
961     {
962         long off=0;
963         err=grib_get_partial_message ( h,&mess,&mess_len,start_section );
964         if ( err!=0 ) return err;
965         total_len=mh->buffer->ulength+mess_len-4;
966 
967         while ( total_len > mh->buffer->length )
968             grib_grow_buffer ( h->context,mh->buffer,total_len );
969 
970         p=mh->buffer->data+mh->buffer->ulength-4;
971         memcpy ( p,mess,mess_len );
972         mh->length+=mess_len-4;
973 
974         off=mh->offset+64;
975 
976         grib_encode_unsigned_long ( mh->buffer->data, mh->length,  &off,  64 );
977         mh->buffer->ulength=total_len;
978     }
979     return err;
980 }
981 
grib_multi_handle_write(grib_multi_handle * h,FILE * f)982 int grib_multi_handle_write ( grib_multi_handle* h,FILE* f )
983 {
984     if ( f==NULL ) return GRIB_INVALID_FILE;
985     if ( h==NULL ) return GRIB_INVALID_GRIB;
986 
987     if ( fwrite ( h->buffer->data,1,h->buffer->ulength,f ) != h->buffer->ulength )
988     {
989         grib_context_log ( h->context,GRIB_LOG_PERROR,"grib_multi_handle_write writing on file" );
990         return GRIB_IO_PROBLEM;
991     }
992 
993     return 0;
994 }
995 
grib_get_partial_message(grib_handle * h,const void ** msg,size_t * len,int start_section)996 int grib_get_partial_message ( grib_handle* h,const void** msg,size_t* len,int start_section )
997 {
998     size_t partial_len=0;
999     long section_offset=0;
1000     if ( !h ) return GRIB_NULL_HANDLE;
1001 
1002     if ( start_section>h->sections_count )
1003         return GRIB_INVALID_SECTION_NUMBER;
1004 
1005     grib_get_long ( h,h->section_offset[start_section],&section_offset );
1006     partial_len=h->buffer->ulength-section_offset;
1007 
1008     *len=partial_len;
1009     *msg  = h->buffer->data+section_offset;
1010 
1011     return GRIB_SUCCESS;
1012 }
1013 
grib_get_partial_message_copy(grib_handle * h,void * message,size_t * len,int start_section)1014 int grib_get_partial_message_copy ( grib_handle* h ,  void* message,size_t *len,
1015         int start_section )
1016 {
1017     size_t partial_len=0;
1018     long section_offset=0;
1019     if ( !h ) return GRIB_NULL_HANDLE;
1020 
1021     if ( start_section>h->sections_count )
1022         return GRIB_INVALID_SECTION_NUMBER;
1023 
1024     grib_get_long ( h,h->section_offset[start_section],&section_offset );
1025     partial_len=h->buffer->ulength-section_offset;
1026 
1027     if ( *len < partial_len ) return GRIB_BUFFER_TOO_SMALL;
1028 
1029     *len=partial_len;
1030 
1031     memcpy ( message,h->buffer->data+section_offset,*len );
1032     return GRIB_SUCCESS;
1033 }
1034 
grib_get_message_copy(grib_handle * h,void * message,size_t * len)1035 int grib_get_message_copy ( grib_handle* h ,  void* message,size_t *len )
1036 {
1037     if ( !h )
1038         return GRIB_NOT_FOUND;
1039 
1040     if ( *len < h->buffer->ulength )
1041         return GRIB_BUFFER_TOO_SMALL;
1042 
1043     *len=h->buffer->ulength;
1044 
1045     memcpy ( message,h->buffer->data,*len );
1046     return GRIB_SUCCESS;
1047 }
1048 
grib_get_message_offset(grib_handle * h,off_t * offset)1049 int grib_get_message_offset ( grib_handle* h,off_t* offset )
1050 {
1051     if (h) *offset=h->offset;
1052     else return GRIB_INTERNAL_ERROR;
1053 
1054     return 0;
1055 }
1056 
grib_get_message_size(grib_handle * h,size_t * size)1057 int grib_get_message_size ( grib_handle* h,size_t* size )
1058 {
1059     long totalLength=0;
1060     int ret=0;
1061     *size =  h->buffer->ulength;
1062     ret=grib_get_long(h,"totalLength",&totalLength);
1063     if (!ret) *size=totalLength;
1064     return ret;
1065 }
1066 
grib_get_message(grib_handle * h,const void ** msg,size_t * size)1067 int grib_get_message ( grib_handle* h,const void** msg,size_t* size )
1068 {
1069     long totalLength=0;
1070     int ret=0;
1071     *msg  =  h->buffer->data;
1072     *size =  h->buffer->ulength;
1073 
1074     ret=grib_get_long(h,"totalLength",&totalLength);
1075     if (!ret) *size=totalLength;
1076 
1077     if ( h->context->gts_header_on && h->gts_header )
1078     {
1079         char strbuf[10];
1080         sprintf ( strbuf,"%.8d", ( int ) ( h->buffer->ulength+h->gts_header_len-6 ) );
1081         memcpy ( h->gts_header,strbuf,8 );
1082     }
1083     return 0;
1084 }
1085 
grib_get_message_headers(grib_handle * h,const void ** msg,size_t * size)1086 int grib_get_message_headers ( grib_handle* h,const void** msg,size_t* size )
1087 {
1088     int ret=0;
1089     size_t endOfHeadersMaker;
1090     *msg  =  h->buffer->data;
1091     *size =  h->buffer->ulength;
1092 
1093     if ((ret=grib_get_offset(h,"endOfHeadersMaker",&endOfHeadersMaker))!=GRIB_SUCCESS) {
1094         grib_context_log(h->context,GRIB_LOG_FATAL,
1095                 "grib_get_message_headers unable to get offset of endOfHeadersMaker");
1096         return ret;
1097     }
1098 
1099     *size=endOfHeadersMaker;
1100 
1101     return ret;
1102 }
1103 
grib_handle_new(grib_context * c)1104 grib_handle *grib_handle_new ( grib_context* c )
1105 {
1106     grib_handle* h;
1107 
1108     if ( !c ) c = grib_context_get_default();
1109     h  = grib_new_handle ( c );
1110     h->buffer = grib_create_growable_buffer ( c );
1111     if ( h->buffer == NULL )
1112     {
1113         grib_handle_delete ( h );
1114         return NULL;
1115     }
1116     h->root   = grib_create_root_section ( h->context,h );
1117 
1118     if ( !h->root )
1119     {
1120         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_message: cannot create root section" );
1121         grib_handle_delete ( h );
1122         return NULL;
1123     }
1124 
1125     if ( !h->context->grib_reader || !h->context->grib_reader->first )
1126     {
1127         grib_context_log ( c, GRIB_LOG_ERROR, "grib_handle_new_from_message: cannot create handle, no definitions found" );
1128         grib_handle_delete ( h );
1129         return NULL;
1130     }
1131 
1132     h->buffer->property = GRIB_USER_BUFFER;
1133 
1134     h->header_mode=1;
1135 
1136     return h;
1137 }
1138 
grib_action_from_filter(const char * filter)1139 grib_action* grib_action_from_filter ( const char* filter )
1140 {
1141     grib_action* a = NULL;
1142     grib_context* context=grib_context_get_default();
1143     a = grib_parse_file ( context, filter );
1144     context->grib_reader=NULL;
1145     return a;
1146 }
1147 
grib_handle_apply_action(grib_handle * h,grib_action * a)1148 int grib_handle_apply_action ( grib_handle* h,grib_action* a )
1149 {
1150     int err;
1151     grib_action* ao = a;
1152 
1153     if ( !a ) return GRIB_SUCCESS; /* TODO: return error */
1154 
1155     while ( a )
1156     {
1157         err = grib_action_execute ( a,h );
1158         if ( err != GRIB_SUCCESS )
1159             return err;
1160         a = a->next;
1161     }
1162 
1163     a=ao;
1164 
1165     return GRIB_SUCCESS;
1166 }
1167 
grib_handle_prepare_action(grib_handle * h,grib_action * a)1168 int grib_handle_prepare_action ( grib_handle* h,grib_action* a )
1169 {
1170     int err;
1171     grib_action* ao = a;
1172 
1173     if ( !a ) return GRIB_SUCCESS; /* TODO: return error */
1174 
1175     while ( a )
1176     {
1177         err = grib_action_execute ( a,h );
1178         if ( err != GRIB_SUCCESS )
1179             return err;
1180         a = a->next;
1181     }
1182 
1183     a=ao;
1184 
1185     return GRIB_SUCCESS;
1186 }
1187 
grib2_get_next_section(unsigned char * msgbegin,size_t msglen,unsigned char ** secbegin,size_t * seclen,int * secnum,int * err)1188 static int grib2_get_next_section ( unsigned char* msgbegin,size_t msglen,unsigned char** secbegin,size_t* seclen,int* secnum,int* err )
1189 {
1190     if ( !grib2_has_next_section ( msgbegin,msglen,*secbegin,*seclen,err ) )
1191         return 0;
1192 
1193     *secbegin+=*seclen;
1194     *seclen=grib_decode_unsigned_byte_long ( *secbegin,0,4 );
1195     *secnum=grib_decode_unsigned_byte_long ( *secbegin,4,1 );
1196 
1197     if ( *secnum < 1 || *secnum > 7 )
1198     {
1199         *err=GRIB_INVALID_SECTION_NUMBER;
1200         return 0;
1201     }
1202     return 1;
1203 }
1204 
grib2_has_next_section(unsigned char * msgbegin,size_t msglen,unsigned char * secbegin,size_t seclen,int * err)1205 static int grib2_has_next_section ( unsigned char* msgbegin,size_t msglen,unsigned char* secbegin,size_t seclen,int* err )
1206 {
1207     long next_seclen;
1208     *err=0;
1209 
1210     next_seclen= ( msgbegin+msglen )- ( secbegin+seclen );
1211 
1212     if ( next_seclen < 5 )
1213     {
1214         if ( ( next_seclen > 3 ) && !strncmp ( ( char* ) secbegin,"7777",4 ) )
1215             *err=GRIB_SUCCESS;
1216         else *err=GRIB_7777_NOT_FOUND;
1217         return 0;
1218     }
1219 
1220     secbegin+=seclen;
1221 
1222     return 1;
1223 }
1224 
grib2_build_message(grib_context * context,unsigned char * sections[],size_t sections_len[],void ** data,size_t * len)1225 static void grib2_build_message ( grib_context* context,unsigned char* sections[],size_t sections_len[],void** data,size_t* len )
1226 {
1227     int i=0;
1228     char* theEnd="7777";
1229     unsigned char* p=0;
1230     size_t msglen=0;
1231     long bitp=64;
1232     if ( !sections[0] )
1233     {
1234         *data=NULL;
1235         return;
1236     }
1237 
1238     for ( i=0;i<8;i++ ) msglen+= sections_len[i];
1239     msglen+=4;
1240     if ( *len<msglen ) msglen=*len;
1241 
1242     *data= ( unsigned char* ) grib_context_malloc ( context,msglen );
1243     p=(unsigned char*)*data;
1244 
1245     for ( i=0;i<8;i++ )
1246     {
1247         if ( sections[i] )
1248         {
1249             memcpy ( p,sections[i],sections_len[i] );
1250             p+=sections_len[i];
1251         }
1252     }
1253 
1254     memcpy ( p,theEnd,4 );
1255 
1256     grib_encode_unsigned_long ( (unsigned char*)*data,msglen,&bitp,64 );
1257 
1258     *len=msglen;
1259 }
1260 
grib_multi_support_on(grib_context * c)1261 void grib_multi_support_on ( grib_context* c )
1262 {
1263     if ( !c ) c=grib_context_get_default();
1264     c->multi_support_on=1;
1265 }
1266 
grib_multi_support_off(grib_context * c)1267 void grib_multi_support_off ( grib_context* c )
1268 {
1269     if ( !c ) c=grib_context_get_default();
1270     c->multi_support_on=0;
1271 }
1272 
1273 /* For multi support mode: Reset all file handles equal to f. See GRIB-249 */
grib_multi_support_reset_file(grib_context * c,FILE * f)1274 void grib_multi_support_reset_file(grib_context* c, FILE* f)
1275 {
1276     grib_multi_support* gm = NULL;
1277     if ( !c ) c = grib_context_get_default();
1278     gm = c->multi_support;
1279     while ( gm ) {
1280         if ( gm->file == f ) {
1281             gm->file = NULL;
1282         }
1283         gm=gm->next;
1284     }
1285 }
1286 
grib_gts_header_on(grib_context * c)1287 void grib_gts_header_on ( grib_context* c )
1288 {
1289     if ( !c ) c=grib_context_get_default();
1290     c->gts_header_on=1;
1291 }
1292 
grib_gts_header_off(grib_context * c)1293 void grib_gts_header_off ( grib_context* c )
1294 {
1295     if ( !c ) c=grib_context_get_default();
1296     c->gts_header_on=0;
1297 }
1298 
grib_get_gribex_mode(grib_context * c)1299 int grib_get_gribex_mode ( grib_context* c)
1300 {
1301     if ( !c ) c=grib_context_get_default();
1302     return c->gribex_mode_on;
1303 }
1304 
grib_gribex_mode_on(grib_context * c)1305 void grib_gribex_mode_on ( grib_context* c )
1306 {
1307     if ( !c ) c=grib_context_get_default();
1308     c->gribex_mode_on=1;
1309 }
1310 
grib_gribex_mode_off(grib_context * c)1311 void grib_gribex_mode_off ( grib_context* c )
1312 {
1313     if ( !c ) c=grib_context_get_default();
1314     c->gribex_mode_on=0;
1315 }
1316 
grib_get_multi_support(grib_context * c,FILE * f)1317 static grib_multi_support* grib_get_multi_support ( grib_context* c, FILE* f )
1318 {
1319     int i=0;
1320     grib_multi_support* gm=c->multi_support;
1321     grib_multi_support* prev=NULL;
1322 
1323     while ( gm )
1324     {
1325         if ( gm->file == f ) return gm;
1326         prev=gm;
1327         gm=gm->next;
1328     }
1329 
1330     if ( !gm )
1331     {
1332         gm=grib_multi_support_new ( c );
1333         if ( !c->multi_support ) c->multi_support=gm;
1334         else prev->next=gm;
1335     }
1336 
1337     gm->next=0;
1338     if ( gm->message ) grib_context_free ( c,gm->message );
1339     gm->message=NULL;
1340     gm->section_number=0;
1341     gm->sections_length[0]=16;
1342     for ( i=1;i<8;i++ ) gm->sections_length[i]=0;
1343     gm->sections_length[8]=4;
1344     gm->file=f;
1345 
1346     return gm;
1347 }
1348 
grib_multi_support_reset(grib_context * c)1349 void grib_multi_support_reset ( grib_context* c )
1350 {
1351     grib_multi_support* gm=c->multi_support;
1352     grib_multi_support* next=NULL;
1353     int i=0;
1354     while ( next )
1355     {
1356         next=gm->next;
1357         if ( gm->file ) fclose ( gm->file );
1358         if ( gm->message ) grib_context_free ( c,gm->message );
1359         gm->message=NULL;
1360         for ( i=0;i<8;i++ ) gm->sections[i]=0;
1361         if ( gm->bitmap_section ) grib_context_free ( c,gm->bitmap_section );
1362         gm->bitmap_section=NULL;
1363         grib_context_free ( c,gm );
1364         gm=NULL;
1365     }
1366 }
1367 
grib_multi_support_new(grib_context * c)1368 static grib_multi_support* grib_multi_support_new ( grib_context* c )
1369 {
1370     int i=0;
1371     grib_multi_support* gm=
1372             ( grib_multi_support* ) grib_context_malloc_clear ( c,sizeof ( grib_multi_support ) );
1373     gm->file=NULL;
1374     gm->message=NULL;
1375     gm->message_length=0;
1376     gm->bitmap_section=NULL;
1377     gm->bitmap_section_length=0;
1378     gm->section_number=0;
1379     gm->next=0;
1380     gm->sections_length[0]=16;
1381     for ( i=1;i<8;i++ ) gm->sections_length[i]=0;
1382     gm->sections_length[8]=4;
1383 
1384     return gm;
1385 }
1386