1 /**
2 * Copyright 1981-2016 ECMWF.
3 *
4 * This software is licensed under the terms of the Apache Licence
5 * Version 2.0 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
8 * granted to it by virtue of its status as an intergovernmental organisation
9 * nor does it submit to any jurisdiction.
10 */
11 
12 /*
13 // pbio.c
14 */
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <ctype.h>
22 
23 #ifdef PTHREADS
24 #include <pthread.h>
25 #endif
26 
27 #ifdef FOPEN64
28 #define OFF_T off64_t
29 extern FILE *fopen64(const char *, const char *);
30 #else
31 #define OFF_T off_t
32 #endif
33 
34 static FILE** fptable = NULL;
35 static int fptableSize = 0;
36 
37 #ifdef PTHREADS
38 static pthread_mutex_t fpTableBusy = PTHREAD_MUTEX_INITIALIZER;
39 #endif
40 #define BUFFLEN 4096
41 
42 /*
43 // Default buffer size for I/O operations (set via setvbuf)
44 */
45 #define SIZE BUFSIZ
46 static long size = SIZE;
47 static int sizeSet = 0;
48 static char * envSize;
49 static char** fileBuffer = NULL;
50 
51 /*
52 // Debug flags.
53 */
54 #define DEBUGOFF 1
55 #define DEBUG (debugSet > DEBUGOFF )
56 static char * debugLevel;
57 static int debugSet = 0;
58 
59 #include "bufrgrib.h"
60 #include "fort2c.h"
61 #include "common/fortint.h"
62 #include "fileRead.h"
63 
64 #define NAMEBUFFLEN 256
65 #define MODEBUFFLEN 10
66 
67 #define CURRENT_FILE (fptable[*unit])
68 
pbfp(long index)69 FILE* pbfp(long index) {
70   if( (fptable == NULL) || ((int)index < 0) || ((int)index >= fptableSize) )
71     return (FILE *) NULL;
72   else
73     return fptable[index];
74 }
75 
76 /*
77 //------------------------------------------------------------------------
78 // PBOPEN - Open file (from FORTRAN)
79 //------------------------------------------------------------------------
80 */
81 #if defined hpR64 || defined hpiaR64
pbopen_(fortint * unit,_fcd name,_fcd mode,fortint * iret,long l1,long l2)82 void pbopen_(fortint* unit,_fcd name,_fcd mode,fortint* iret,long l1,long l2) {
83 #else
84 void pbopen_(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
85 #endif
86 /*
87 // Purpose:
88 //  Opens file, returns the index of a UNIX FILE pointer held in
89 //  an internal table (fptable).
90 //
91 // First time through, reads value in environment variable PBIO_BUFSIZE
92 // (if it is set) and uses it as the size to be used for internal file
93 // buffers; the value is passed to setvbuf. If PBIO_BUFSIZE is not set,
94 // a default value is used.
95 //
96 // Function  accepts:
97 //    name = filename
98 //    mode = r, r+, w
99 //
100 //    Note: l1 and l2 are the lengths of the FORTRAN character strings
101 //          in name and mode.
102 //
103 // Function returns:
104 //   INTEGER iret:
105 //     -1 = Could not open file.
106 //     -2 = Invalid file name.
107 //     -3 = Invalid open mode specified
108 //      0 = OK.
109 */
110 int n;
111 char *p;
112 char  flags[4];
113 
114 #if (!defined CRAY) && (!defined VAX)
115 char namebuff[NAMEBUFFLEN+1], modebuff[MODEBUFFLEN+1];
116 #else
117 char * namebuff, * modebuff;
118 #endif
119 
120 /*
121 // See if DEBUG switched on.
122 */
123     if( ! debugSet ) {
124       debugLevel = getenv("PBIO_DEBUG");
125       if( debugLevel == NULL )
126         debugSet = DEBUGOFF;              /* off */
127       else {
128         int loop;
129         for( loop = 0; loop < strlen(debugLevel) ; loop++ ) {
130           if( ! isdigit(debugLevel[loop]) ) {
131             printf("Invalid number string in PBIO_DEBUG: %s\n", debugLevel);
132             printf("PBIO_DEBUG must comprise only digits [0-9].\n");
133             debugSet = DEBUGOFF;
134           }
135         }
136         debugSet = DEBUGOFF + atol( debugLevel );
137       }
138       if( DEBUG ) printf("PBIO_PBOPEN: debug switched on\n");
139     }
140 
141 #if (!defined CRAY) && (!defined VAX)
142 /*
143 // Put the character strings into buffers and ensure that there is a
144 // null terminator (for SGI case when FORTRAN CHARACTER variable is full
145 // right to end with characters
146 */
147     {
148      int n1, n2;
149 
150       n1 = (l1>NAMEBUFFLEN) ? NAMEBUFFLEN : l1;
151       n2 = (l2>MODEBUFFLEN) ? MODEBUFFLEN : l2;
152 
153       strncpy( namebuff, name, n1);
154       strncpy( modebuff, mode, n2);
155       namebuff[n1] = '\0';
156       modebuff[n2] = '\0';
157     }
158 #else
159     if(!(namebuff = fcd2char(name))) {
160       *iret = -2;
161       return;
162     }
163     if(!(modebuff = fcd2char(mode))) {
164       free(namebuff);
165       *iret = -2;
166       return;
167     }
168 #endif
169 
170     strcpy(flags,"");
171 
172     /* *unit = (fortint) NULL;  sami bug fix */
173     *unit = 0;
174     *iret = 0;
175 
176 /*
177 // Strip trailing blanks
178 */
179     p  = namebuff + strlen(namebuff) - 1 ;
180     while(*p == ' ') {
181       *p = 0;
182       p--;
183     }
184     if( DEBUG ) printf("PBIO_PBOPEN: filename = %s\n", namebuff);
185 /*
186 // Build open flags from "modes"
187 */
188     p = modebuff;
189 
190     switch(*p) {
191 
192       case 'a':
193       case 'A': strcat(flags, "a");
194                       break;
195 
196       case 'c':
197       case 'C':
198       case 'w':
199       case 'W': strcat(flags, "w");
200                 break;
201 
202       case 'r':
203       case 'R':
204                 if( *(p+1) == '+' )
205                   strcat(flags, "r+");
206                 else
207                   strcat(flags, "r");
208                 break;
209 
210       default:  *iret = -3;
211                 return;
212 
213     }
214     if( DEBUG ) printf("PBIO_PBOPEN: file open mode = %s\n", flags);
215 
216 /*
217 // Look for a free slot in fptable.
218 // (Create the table the first time through).
219 */
220 #ifdef PTHREADS
221 /*
222 // Wait if another thread opening a file
223 */
224     pthread_mutex_lock(&fpTableBusy);
225 #endif
226 
227     n = 0;
228     if( fptableSize == 0 ) {
229       int i;
230       fptableSize = 2;
231       fptable = (FILE **) malloc(fptableSize*sizeof(FILE *));
232       if( fptable == NULL ) {
233         perror("Unable to allocate space for table of FILE pointers");
234         exit(1);
235       }
236 
237       fileBuffer = (char **) malloc(fptableSize*sizeof(char *));
238       if( fileBuffer == NULL ) {
239         perror("Unable to allocate space for FILE buffers");
240         exit(1);
241       }
242 
243       for( i = 0; i < fptableSize; i++ ) {
244         fptable[i] = 0;
245         fileBuffer[i] = NULL;
246       }
247     }
248     else {
249       while( n < fptableSize ) {
250         if(fptable[n]==0) {
251           *unit = n;
252           break;
253         }
254         n++;
255       }
256     }
257 /*
258 // If the table overflows, double its size.
259 */
260     if( n == fptableSize) {
261       int i;
262       fptableSize = 2*fptableSize;
263       fptable = (FILE **) realloc(fptable, fptableSize*sizeof(FILE *));
264       if( fptable == NULL ) {
265         perror("Unable to reallocate space for table of FILE pointers");
266         exit(1);
267       }
268       n = fptableSize/2;
269 
270       fileBuffer = (char **) realloc(fileBuffer, fptableSize*sizeof(char *));
271       if( fileBuffer == NULL ) {
272         perror("Unable to allocate space for FILE buffers");
273         exit(1);
274       }
275 
276       n = fptableSize/2;
277       for( i = n; i < fptableSize; i++ ) {
278         fptable[i] = 0;
279         fileBuffer[i] = NULL;
280       }
281 
282       *unit = n;
283     }
284 
285     if( DEBUG ) printf("PBIO_PBOPEN: fptable slot = %d\n", *unit);
286 
287 #ifdef FOPEN64
288     if( DEBUG ) printf("PBIO_PBOPEN: using fopen64\n");
289     fptable[n] = fopen64(namebuff, flags );
290 #else
291     if( DEBUG ) printf("PBIO_PBOPEN: using fopen\n");
292     fptable[n] = fopen(namebuff, flags );
293 #endif
294 
295     if(fptable[n] == NULL) {
296       perror(namebuff);
297       *iret = -1;
298 #if (defined CRAY) || (defined VAX)
299       free(namebuff);
300       free(modebuff);
301 #endif
302 #ifdef PTHREADS
303       pthread_mutex_unlock(&fpTableBusy);
304 #endif
305       return;
306     }
307 
308 /*
309 // Now allocate a buffer for the file, if necessary.
310 */
311     if( ! sizeSet ) {
312       envSize = getenv("PBIO_BUFSIZE");
313       if( envSize == NULL )
314         size = SIZE;             /* default */
315       else {
316         int loop;
317         for( loop = 0; loop < strlen(envSize) ; loop++ ) {
318           if( ! isdigit(envSize[loop]) ) {
319             printf("Invalid number string in PBIO_BUFSIZE: %s\n", envSize);
320             printf("PBIO_BUFSIZE must comprise only digits [0-9].\n");
321             exit(1);
322           }
323         }
324         size = atol( envSize );
325       }
326       if( size <= 0 ) {
327         printf("Invalid buffer size in PBIO_BUFSIZE: %s\n", envSize);
328         printf("Buffer size defined by PBIO_BUFSIZE must be positive.\n");
329         exit(1);
330       }
331       sizeSet = 1;
332     }
333 
334     if( DEBUG ) printf("PBIO_PBOPEN: file buffer size = %d\n", size);
335 
336     if( fileBuffer[n] == NULL ) {
337       fileBuffer[n] = (char *) malloc(size);
338     }
339 
340     if( setvbuf(CURRENT_FILE, fileBuffer[*unit], _IOFBF, size) ) {
341         perror("setvbuf failed");
342         *iret = -1;
343     }
344 
345 #ifdef PTHREADS
346     pthread_mutex_unlock(&fpTableBusy);
347 #endif
348 
349 #if (defined CRAY) || (defined VAX)
350     free(namebuff);
351     free(modebuff);
352 #endif
353 
354 }
355 
356 #if (defined hpR64) || (defined hpiaR64)
357 void pbopen(fortint* unit,_fcd name,_fcd mode,fortint* iret,long l1,long l2) {
358 #else
359 void pbopen(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
360 #endif
361 
362   pbopen_(unit,name,mode,iret,l1,l2);
363 }
364 
365 /*
366 //------------------------------------------------------------------------
367 // PBSEEK - Seek (from FORTRAN)
368 //------------------------------------------------------------------------
369 */
370 void pbseek_(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
371 /*
372 //
373 // Purpose:
374 //   Seeks to a specified location in file.
375 //
376 //  Function  accepts:
377 //    unit = the index of a UNIX FILE pointer held in
378 //           an internal table (fptable).
379 //
380 //    offset = byte count
381 //
382 //    whence  = 0, from start of file
383 //            = 1, from current position
384 //            = 2, from end of file.
385 //
386 //  Returns:
387 //    iret:
388 //      -2 = error in handling file,
389 //      -1 = end-of-file
390 //      otherwise,  = byte offset from start of file.
391 */
392 int my_offset = (int) *offset;
393 int my_whence = (int) *whence;
394 
395 /*
396 // Must use negative offset if working from end-of-file
397 */
398     if( DEBUG ) {
399       printf("PBIO_PBSEEK: fptable slot = %d\n", *unit);
400       printf("PBIO_PBSEEK: Offset = %d\n", my_offset);
401       printf("PBIO_PBSEEK: Type of offset = %d\n", my_whence);
402     }
403 
404     if( my_whence == 2) my_offset = - abs(my_offset);
405 
406     *iret = fileTell(CURRENT_FILE);
407     if( DEBUG ) printf("PBIO_PBSEEK: current position = %d\n", *iret);
408     if( *iret == my_offset && my_whence == 0)
409       *iret = 0;
410     else
411       *iret = fileSeek(CURRENT_FILE, my_offset, my_whence);
412 
413     if( DEBUG ) printf("PBIO_PBSEEK: fileSeek return code = %d\n",*iret);
414 
415     if( *iret != 0 ) {
416       if( ! feof(CURRENT_FILE) ) {
417         *iret = -2;             /* error in file-handling */
418         perror("pbseek");
419       }
420       else
421         *iret = -1;             /* end-of-file  */
422 
423       clearerr(CURRENT_FILE);
424       return;
425     }
426 
427 /*
428 // Return the byte offset from start of file
429 */
430     *iret = fileTell(CURRENT_FILE);
431 
432     if( DEBUG )
433       printf("PBIO_PBSEEK: byte offset from start of file = %d\n",*iret);
434 
435     return;
436 
437 }
438 
439 void pbseek(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
440 
441   pbseek_(unit,offset,whence,iret);
442 }
443 
444 
445 void pbseek64_(fortint* unit,long long* offset,fortint* whence,long long* iret) {
446 /*
447 //
448 // Purpose:
449 //   Seeks to a specified location in file.
450 //
451 //  Function  accepts:
452 //    unit = the index of a UNIX FILE pointer held in
453 //           an internal table (fptable).
454 //
455 //    offset = byte count
456 //
457 //    whence  = 0, from start of file
458 //            = 1, from current position
459 //            = 2, from end of file.
460 //
461 //  Returns:
462 //    iret:
463 //      -2 = error in handling file,
464 //      -1 = end-of-file
465 //      otherwise,  = byte offset from start of file.
466 */
467 long long my_offset = (long long) *offset;
468 int my_whence = (int) *whence;
469 
470 /*
471 // Must use negative offset if working from end-of-file
472 */
473     if( DEBUG ) {
474       printf("PBIO_PBSEEK: fptable slot = %d\n", *unit);
475       printf("PBIO_PBSEEK: Offset = %d\n", my_offset);
476       printf("PBIO_PBSEEK: Type of offset = %d\n", my_whence);
477     }
478 
479     if( my_whence == 2) my_offset = - abs(my_offset);
480 
481     *iret = fileTell(CURRENT_FILE);
482     if( DEBUG ) printf("PBIO_PBSEEK: current position = %d\n", *iret);
483     if( *iret == my_offset && my_whence == 0)
484       *iret = 0;
485     else
486       *iret = fileSeek(CURRENT_FILE, my_offset, my_whence);
487 
488     if( DEBUG ) printf("PBIO_PBSEEK: fileSeek return code = %d\n",*iret);
489 
490     if( *iret != 0 ) {
491       if( ! feof(CURRENT_FILE) ) {
492         *iret = -2;             /* error in file-handling */
493         perror("pbseek");
494       }
495       else
496         *iret = -1;             /* end-of-file  */
497 
498       clearerr(CURRENT_FILE);
499       return;
500     }
501 
502 /*
503 // Return the byte offset from start of file
504 */
505     *iret = fileTell(CURRENT_FILE);
506 
507     if( DEBUG )
508       printf("PBIO_PBSEEK: byte offset from start of file = %d\n",*iret);
509 
510     return;
511 
512 }
513 
514 void pbseek64(fortint* unit,long long* offset,fortint* whence,long long* iret) {
515 
516   pbseek64_(unit,offset,whence,iret);
517 }
518 
519 /*
520 //------------------------------------------------------------------------
521 // PBTELL - Tells current file position (from FORTRAN)
522 //------------------------------------------------------------------------
523 */
524 void pbtell_(fortint* unit,fortint* iret) {
525 /*
526 //
527 // Purpose:
528 //   Tells current byte offset in file.
529 //
530 //  Function  accepts:
531 //    unit = the index of a UNIX FILE pointer held in
532 //           an internal table (fptable).
533 //
534 //  Returns:
535 //    iret:
536 //      -2 = error in handling file,
537 //      otherwise,  = byte offset from start of file.
538 */
539 
540 
541 /*
542 // Return the byte offset from start of file
543 */
544     *iret = fileTell(CURRENT_FILE);
545 
546     if( *iret < 0 ) {
547       if( DEBUG ) {           /* error in file-handling */
548         printf("PBIO_PBTELL: fptable slot = %d. ", *unit);
549         printf("Error status = %d\n", *iret);
550       }
551       perror("pbtell");
552       *iret = -2;
553     }
554 
555     if( DEBUG ) {
556       printf("PBIO_PBTELL: fptable slot = %d. ", *unit);
557       printf("Byte offset from start of file = %d\n",*iret);
558     }
559 
560     return;
561 }
562 
563 void pbtell(fortint* unit,fortint* iret) {
564 
565   pbtell_(unit,iret);
566 }
567 
568 /*
569 //------------------------------------------------------------------------
570 // PBTELL64 - Tells current file position (from FORTRAN)
571 //------------------------------------------------------------------------
572 */
573 void pbtell64_(fortint* unit,long long* iret) {
574 /*
575 //
576 // Purpose:
577 //   Tells current byte offset in file.
578 //
579 //  Function  accepts:
580 //    unit = the index of a UNIX FILE pointer held in
581 //           an internal table (fptable).
582 //
583 //  Returns:
584 //    iret:
585 //      -2 = error in handling file,
586 //      otherwise,  = byte offset from start of file.
587 */
588 
589 
590 /*
591 // Return the byte offset from start of file
592 */
593     *iret = fileTell(CURRENT_FILE);
594 
595     if( *iret < 0 ) {
596       if( DEBUG ) {           /* error in file-handling */
597         printf("PBIO_PBTELL64: fptable slot = %d. ", *unit);
598         printf("Error status = %d\n", *iret);
599       }
600       perror("pbtell64");
601       *iret = -2;
602     }
603 
604     if( DEBUG ) {
605       printf("PBIO_PBTELL: fptable slot = %d. ", *unit);
606       printf("Byte offset from start of file = %d\n",*iret);
607     }
608 
609     return;
610 }
611 
612 void pbtell64(fortint* unit,long long* iret) {
613 
614   pbtell64_(unit,iret);
615 }
616 
617 /*
618 //------------------------------------------------------------------------
619 //  PBREAD - Read (from FORTRAN)
620 //------------------------------------------------------------------------
621 */
622 void pbread_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
623 /*
624 // Purpose:
625 //  Reads a block of bytes from a file..
626 //
627 //  Function  accepts:
628 //    unit = the index of a UNIX FILE pointer held in
629 //           an internal table (fptable).
630 //
631 //    nbytes = number of bytes to read.
632 //
633 //  Returns:
634 //    iret:
635 //      -2 = error in reading file,
636 //      -1 = end-of-file,
637 //      otherwise, = number of bytes read.
638 */
639     if( DEBUG ) {
640       printf("PBIO_READ: fptable slot = %d. ", *unit);
641       printf("Number of bytes to read = %d\n", *nbytes);
642     }
643 
644     if( (*iret = fread(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
645       if( ! feof(CURRENT_FILE) ) {
646         *iret = -2;             /*  error in file-handling  */
647         perror("pbread");
648         clearerr(CURRENT_FILE);
649         return;
650       }
651       else {
652         *iret = -1;             /*  end-of-file */
653         clearerr(CURRENT_FILE);
654       }
655     }
656 
657     if( DEBUG ) {
658       printf("PBIO_READ: fptable slot = %d. ", *unit);
659       printf("Number of bytes read = %d\n", *nbytes);
660     }
661 
662     return;
663 }
664 
665 void pbread(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
666 
667   pbread_(unit,buffer,nbytes,iret);
668 }
669 
670 /*
671 //------------------------------------------------------------------------
672 //  PBREAD2 - Read (from FORTRAN)
673 //------------------------------------------------------------------------
674 */
675 void pbread2_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
676 /*
677 // Purpose:
678 //  Reads a block of bytes from a file..
679 //
680 //  Function  accepts:
681 //    unit = the index of a UNIX FILE pointer held in
682 //           an internal table (fptable).
683 //
684 //    nbytes = number of bytes to read.
685 //
686 //  Returns:
687 //    iret:
688 //      -2 = error in reading file,
689 //      -1 = end-of-file,
690 //      otherwise, = number of bytes read.
691 */
692     if( DEBUG ) {
693       printf("PBIO_READ2: fptable slot = %d. ", *unit);
694       printf("Number of bytes to read = %d\n", *nbytes);
695     }
696 
697    if( (*iret = fread(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
698      if( ! feof(CURRENT_FILE) ) {
699        *iret = -2;             /*  error in file-handling  */
700        perror("pbread2");
701        clearerr(CURRENT_FILE);
702      }
703    }
704 
705   if( DEBUG )
706     printf("PBIO_READ2: Number of bytes read = %d\n", *iret);
707 
708    return;
709 }
710 
711 void pbread2(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
712 
713   pbread2_(unit,buffer,nbytes,iret);
714 }
715 
716 /*
717 //------------------------------------------------------------------------
718 //  PBWRITE - Write (from FORTRAN)
719 //------------------------------------------------------------------------
720 */
721 void pbwrite_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
722 /*
723 // Purpose:
724 //  Writes a block of bytes to a file.
725 //
726 //  Function  accepts:
727 //    unit = the index of a UNIX FILE pointer held in
728 //           an internal table (fptable).
729 //
730 //    nbytes = number of bytes to write.
731 //
732 //  Returns:
733 //    iret:
734 //      -1 = Could not write to file.
735 //     >=0 = Number of bytes written.
736 */
737     if( DEBUG ) {
738       printf("PBIO_WRITE: fptable slot = %d. ", *unit);
739       printf("Number of bytes to write = %d\n", *nbytes);
740     }
741 
742     if( (*iret = fwrite(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
743       perror("pbwrite");
744       *iret = -1;
745     }
746 
747     if( DEBUG ) {
748       printf("PBIO_WRITE: fptable slot = %d. ", *unit);
749       printf("PBIO_WRITE: number of bytes written = %d\n", *iret);
750     }
751 
752     return;
753 }
754 
755 void pbwrite(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
756 
757   pbwrite_(unit,buffer,nbytes,iret);
758 }
759 
760 /*
761 //------------------------------------------------------------------------
762 //   PBCLOSE - close (from FORTRAN)
763 //------------------------------------------------------------------------
764 */
765 void pbclose_(fortint* unit,fortint* iret) {
766 /*
767 // Purpose:
768 //  Closes file.
769 //
770 //  Function  accepts:
771 //    unit = the index of a UNIX FILE pointer held in
772 //           an internal table (fptable).
773 ////  Returns:
774 //    iret:
775 //      0 = OK.
776 //      otherwise = error in handling file.
777 */
778     if( DEBUG )
779       printf("PBIO_CLOSE: fptable slot = %d\n", *unit);
780 
781     if( ( *iret = fclose(CURRENT_FILE) ) != 0 ) perror("pbclose");
782     CURRENT_FILE = 0;
783 
784     return;
785 }
786 
787 void pbclose(fortint* unit,fortint* iret) {
788 
789   pbclose_(unit,iret);
790 }
791 
792 /*
793 //------------------------------------------------------------------------
794 //  PBFLUSH - flush (from FORTRAN)
795 //------------------------------------------------------------------------
796 */
797 void pbflush_(fortint * unit) {
798 /*
799 // Purpose:     Flushes file.
800 */
801     if( DEBUG )
802       printf("PBIO_FLUSH: fptable slot = %d\n", *unit);
803 
804     fflush(CURRENT_FILE);
805 }
806 
807 void pbflush(fortint * unit) {
808 
809   pbflush_(unit);
810 }
811 
812 /*
813 //------------------------------------------------------------------------
814 //  PBREAD3 - read (from FORTRAN)
815 //------------------------------------------------------------------------
816 */
817 void pbread3_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
818 /*
819 // Purpose:
820 //  Reads a block of bytes from a file..
821 //
822 //  Function returns:
823 //    status :   -2 = error in reading file,
824 //               -1 = end-of-file,
825 //               otherwise, = number of bytes read.
826 */
827     if( DEBUG )
828       printf("PBIO_READ3: number of bytes to read = %d\n", *nbytes);
829 
830     *iret = read(*unit, buffer, *nbytes);
831 
832     if( DEBUG )
833       printf("PBIO_READ3: number of bytes read = %d\n", *iret);
834 /*
835 // Error in file-handling
836 */
837     if(*iret == -1) {
838       *iret = -2;
839       perror("pbread3");
840       return;
841     }
842 /*
843 // Read problem
844 */
845     else if(*iret != *nbytes) {
846       printf("EOF; pbread3; bytes requested %d; read in: %d\n",
847              *nbytes,*iret);
848       *iret = -1;
849       return;
850     }
851 
852 }
853 
854 void pbread3(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
855 
856   pbread3_(unit,buffer,nbytes,iret);
857 }
858 
859 void pbread4_(fortint* unit,char* buffer,size_t* nbytes,size_t* iret) {
860 /*
861 // Purpose:
862 //  Reads a block of bytes from a file..
863 //
864 //  Function returns:
865 //    status :   -2 = error in reading file,
866 //               -1 = end-of-file,
867 //               otherwise, = number of bytes read.
868       printf("PBIO_READ4: sizeof = %ld\n", sizeof(buffer));
869 */
870 /*    if( DEBUG ) */
871      printf("PBIO_READ4: number of bytes to read = %ld\n", *nbytes);
872 
873 /* Is 4MB ok ? */
874 size_t left   = *nbytes;
875 size_t len    = 0;
876 size_t chunk = 4*1024*1024; /* Is 4MB ok ? */
877 size_t pos    = 0;
878 
879    while((left > 0) && (len = read(*unit,(buffer+pos),chunk)) > 0)
880    {
881        left -= len;
882        pos += len;
883        if(left < chunk)
884            chunk = left;
885    }
886    if(len>0)
887        *iret = pos;
888    else
889        *iret = len;
890 
891     if( DEBUG )
892          printf("PBIO_READ4: number of bytes READ = %ld\n", pos);
893 
894     if(*iret == -1) {
895       *iret = -2;
896       perror("pbread4");
897       return;
898     }
899 /*
900 // Read problem
901 */
902     else if(pos != *nbytes) {
903       printf("EOF; pbread4; bytes requested %ld; read in: %ld\n",
904              *nbytes,pos);
905       *iret = -1;
906       return;
907     }
908       printf("PBIO_READ4: number of bytes read = %ld\n", pos);
909       printf("PBIO_READ4: return code *iret = %ld\n", *iret);
910 
911 }
912 
913 void pbread4(fortint* unit,char* buffer,size_t* nbytes,size_t* iret) {
914 
915   pbread4_(unit,buffer,nbytes,iret);
916 }
917 void pbread5_(fortint* unit,char* buffer,size_t* nbytes,size_t* iret) {
918 /*
919 // Purpose:
920 //  Reads a block of bytes from a file..
921 //
922 //  Function returns:
923 //    status :   -2 = error in reading file,
924 //               -1 = end-of-file,
925 //               otherwise, = number of bytes read.
926 */
927     if( DEBUG )
928       printf("PBIO_READ5: number of bytes to read = %lu\n", *nbytes);
929 
930     *iret = read(*unit, buffer, *nbytes);
931 
932     if( DEBUG )
933       printf("PBIO_READ5: number of bytes read = %lun", *iret);
934 /*
935 // Error in file-handling
936 */
937     if(*iret == -1) {
938       *iret = -2;
939       perror("pbread5");
940       return;
941     }
942 /*
943 // Read problem
944 */
945     else if(*iret != *nbytes) {
946       printf("EOF; pbread5; bytes requested %lu; read in: %lu\n",
947              *nbytes,*iret);
948       *iret = -1;
949       return;
950     }
951 
952 }
953 
954 void pbread5(fortint* unit,char* buffer,size_t* nbytes,size_t* iret) {
955   pbread5_(unit,buffer,nbytes,iret);
956 }
957 
958 /*
959 //------------------------------------------------------------------------
960 //  oct_bin3
961 //------------------------------------------------------------------------
962 */
963 static int oct_bin3(int onum) {
964 /*
965 // Converts an integer to octal digits
966 */
967    char tmp[20];
968    int  rc;
969 
970    sprintf(tmp,"%d",onum);
971    sscanf(tmp,"%o",&rc);
972    return rc;
973 }
974 
975 /*
976 //------------------------------------------------------------------------
977 //  PBOPEN3 - Open file (from FORTRAN)
978 //------------------------------------------------------------------------
979 */
980 void pbopen3_(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
981 /*
982 // Purpose:
983 //   Opens file, return UNIX FILE pointer.
984 //
985 // Function returns:
986 //   iret:  -1 = Could not open file.
987 //          -2 = Invalid file name.
988 //          -3 = Invalid open mode specified
989 //           0 = OK.
990 //
991 // Note: l1 and l2 are the lengths of the character strings in
992 //       name and mode on SGI.
993 */
994 char *p;
995 int oflag;
996 int dmas;
997 int filemode;
998 char  flags[4];
999 
1000 #if (!defined CRAY) && (!defined VAX)
1001 char namebuff[NAMEBUFFLEN], modebuff[MODEBUFFLEN];
1002 #else
1003 char * namebuff, * modebuff;
1004 #endif
1005 
1006 /*
1007 // See if DEBUG switched on.
1008 */
1009     if( ! debugSet ) {
1010       debugLevel = getenv("PBIO_DEBUG");
1011       if( debugLevel == NULL )
1012         debugSet = DEBUGOFF;              /* off */
1013       else {
1014         int loop;
1015         for( loop = 0; loop < strlen(debugLevel) ; loop++ ) {
1016           if( ! isdigit(debugLevel[loop]) ) {
1017             printf("Invalid number string in PBIO_DEBUG: %s\n", debugLevel);
1018             printf("PBIO_DEBUG must comprise only digits [0-9].\n");
1019             debugSet = DEBUGOFF;
1020           }
1021         }
1022         debugSet = DEBUGOFF + atol( debugLevel );
1023       }
1024       if( DEBUG ) printf("PBIO_PBOPEN3: debug switched on\n");
1025     }
1026 
1027 #if (!defined CRAY) && (!defined VAX)
1028 /*
1029 // Put the character strings into buffers and ensure that there is a
1030 // null terminator (for SGI case when FORTRAN CHARACTER variable is full
1031 // right to end with characters
1032 */
1033     {
1034      int n1, n2;
1035 
1036       n1 = (l1>NAMEBUFFLEN) ? NAMEBUFFLEN : l1;
1037       n2 = (l2>MODEBUFFLEN) ? MODEBUFFLEN : l2;
1038 
1039       strncpy( namebuff, name, n1);
1040       strncpy( modebuff, mode, n2);
1041       namebuff[n1] = '\0';
1042       modebuff[n2] = '\0';
1043     }
1044 #else
1045     if(!(namebuff = fcd2char(name))) {
1046       *iret = -2;
1047       return;
1048     }
1049     if(!(modebuff = fcd2char(mode))) {
1050       free(namebuff);
1051       *iret = -2;
1052       return;
1053     }
1054 #endif
1055 
1056     strcpy(flags,"");
1057 
1058     *unit = 0;
1059     *iret = 0;
1060 
1061 /*
1062 // Strip trailing blanks
1063 */
1064     p  = namebuff + strlen(namebuff) - 1 ;
1065 
1066     while(*p == ' ') {
1067       *p = 0;
1068       p--;
1069     }
1070     if( DEBUG ) printf("PBIO_PBOPEN: filename = %s\n", namebuff);
1071 
1072 /*
1073 // Build open flags from "modes"
1074 */
1075     p = modebuff;
1076 
1077     switch(*p) {
1078 
1079       case 'a':
1080       case 'A': oflag = 0x100 | O_CREAT | 2 | 0x08;
1081                 filemode = 766;
1082                 break;
1083 
1084       case 'c':
1085       case 'C':
1086       case 'w':
1087       case 'W': oflag = 0x100 | O_CREAT | 1;
1088                 filemode = 766;
1089                 break;
1090 
1091       case 'r':
1092       case 'R': oflag = 0;
1093                 filemode = 444;
1094                 break;
1095 
1096       default:  *iret = -3;
1097                 return;
1098 
1099     }
1100 
1101     if( DEBUG ) printf("PBIO_PBOPEN: file open mode = %s\n", modebuff);
1102 
1103     dmas = umask(000);
1104     *unit = open(namebuff, oflag, oct_bin3(filemode));
1105     umask(dmas);
1106 
1107     if(*unit == -1) {
1108       perror(namebuff);
1109       perror("pbopen3");
1110       *iret = -2;
1111     }
1112 
1113     if( DEBUG ) printf("PBIO_PBOPEN3: file pointer = %0x\n", *unit);
1114 
1115 #if (defined CRAY) || (defined VAX)
1116     free(namebuff);
1117     free(modebuff);
1118 #endif
1119 
1120 }
1121 
1122 void pbopen3(fortint* unit,_fcd name,_fcd mode,fortint* iret,fortint l1,fortint l2) {
1123 
1124   pbopen3_(unit,name,mode,iret,l1,l2);
1125 }
1126 
1127 /*
1128 //------------------------------------------------------------------------
1129 //  PBCLOSE3 - Close file (from FORTRAN)
1130 //------------------------------------------------------------------------
1131 */
1132 void pbclose3_(fortint* unit,fortint* iret) {
1133 /*
1134 //
1135 // Purpose:  Closes file.
1136 //
1137 // Function returns:
1138 //   status : non-0 = error in handling file.
1139 //            0 = OK.
1140 */
1141     if( DEBUG ) printf("PBIO_PBCLOSE3: file pointer = %0x\n", *unit);
1142 
1143     *iret = close(*unit);
1144 
1145     if(*iret != 0) perror("pbclose3");
1146 }
1147 
1148 void pbclose3(fortint* unit,fortint* iret) {
1149 
1150   pbclose3_(unit,iret);
1151 }
1152 
1153 /*
1154 //------------------------------------------------------------------------
1155 //  PBSEEK3 - Seek (from FORTRAN)
1156 //------------------------------------------------------------------------
1157 */
1158 void pbseek3_(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
1159 /*
1160 //
1161 // Purpose:  Seeks to specified location in file.
1162 //
1163 // Function returns:
1164 //   status: -2 = error in handling file,
1165 //           -1 = end-of-file
1166 //           otherwise,         = byte offset from start of file.
1167 //
1168 //   whence  = 0, from start of file
1169 //           = 1, from current position
1170 //           = 2, from end of file.
1171 */
1172 fortint my_offset = *offset;
1173 int my_whence;
1174 
1175     if( DEBUG ) {
1176       printf("PBIO_PBSEEK3: file pointer = %0x\n", *unit);
1177       printf("PBIO_PBSEEK3: offset = %d\n", my_offset);
1178       printf("PBIO_PBSEEK3: type of offset = %d\n", *whence);
1179     }
1180 
1181 /*
1182 // Must use negative offset if working from end-of-file
1183 */
1184     if( *whence == 2) {
1185       my_offset = - abs(my_offset);
1186       my_whence = 2;
1187     }
1188     else if(*whence == 0)
1189     {
1190       my_whence = 0;
1191     }
1192     else
1193     {
1194       my_whence = 1;
1195     }
1196 
1197     if((*iret=lseek(*unit, my_offset, my_whence)) < 0) {
1198       perror("pbseek3;");
1199       *iret = -1;           /* end-of-file  */
1200     }
1201 
1202     if( DEBUG )
1203       printf("PBIO_PBSEEK3: byte offset from start of file = %d\n",*iret);
1204 
1205 }
1206 
1207 void pbseek3(fortint* unit,fortint* offset,fortint* whence,fortint* iret) {
1208 
1209   pbseek3_(unit,offset,whence,iret);
1210 }
1211 
1212 /*
1213 //------------------------------------------------------------------------
1214 //  PBWRITE3 - Write (from FORTRAN)
1215 //------------------------------------------------------------------------
1216 */
1217 void pbwrite3_(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
1218 /*
1219 // Purpose:  Writes a block of bytes to a file.
1220 //
1221 // Function returns:
1222 //   status: -1 = Could not write to file.
1223 //           >=0 = Number of bytes written.
1224 */
1225     if( DEBUG ) {
1226       printf("PBIO_PBWRITE3: file pointer = %0x\n", *unit);
1227       printf("PBIO_WRITE#: number of bytes to write = %d\n", *nbytes);
1228     }
1229 
1230     *iret = write(*unit, buffer, *nbytes);
1231     if( DEBUG )
1232       printf("PBIO_WRITE3: number of bytes written = %d\n", *iret);
1233 
1234     if( *iret != *nbytes ) {
1235       perror("pbwrite3: ");
1236       *iret = -1;
1237     }
1238 
1239 }
1240 
1241 void pbwrite3(fortint* unit,char* buffer,fortint* nbytes,fortint* iret) {
1242 
1243   pbwrite3_(unit,buffer,nbytes,iret);
1244 }
1245 
1246 /*
1247 //------------------------------------------------------------------------
1248 //  GRIBREAD
1249 //------------------------------------------------------------------------
1250 */
1251 void gribread_(
1252 char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
1253 /*
1254 //  Called as a FORTRAN subroutine:
1255 //
1256 //    CALL GRIBREAD( KARRAY, KINLEN, KOUTLEN, IRET, KUNIT )
1257 //
1258 */
1259 fortint holdsize = *buffsize;
1260 
1261 /*
1262 // Read GRIB product
1263 */
1264 
1265     *status = readprod("GRIB",buffer,&holdsize,fileRead,fileSeek,fileTell,
1266                        CURRENT_FILE);
1267     *readsize = abs(holdsize );
1268 
1269     if( DEBUG ) {
1270       printf("PBIO_GRIBREAD: fptable slot = %d. ", *unit);
1271       printf("Number of bytes read = %d\n", *readsize);
1272     }
1273 
1274     return;
1275 }
1276 
1277 void gribread(
1278 char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
1279 
1280   gribread_(buffer,buffsize,readsize,status,unit);
1281 }
1282 
1283 /*
1284 //------------------------------------------------------------------------
1285 //  BUFRREAD
1286 //------------------------------------------------------------------------
1287 */
1288 void bufrread_(
1289 char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
1290 /*
1291 //  Called as a FORTRAN subroutine:
1292 //
1293 //    CALL BUFRREAD( KARRAY, KINLEN, KOUTLEN, IRET, KUNIT )
1294 //
1295 */
1296 fortint holdsize = *buffsize;
1297 
1298 /*
1299 // Read BUFR product
1300 */
1301     *status = readprod("BUFR",buffer,&holdsize,fileRead,fileSeek,fileTell,
1302                        CURRENT_FILE);
1303     *readsize =  abs(holdsize );
1304 
1305     if( DEBUG ) {
1306       printf("PBIO_BUFRREAD: fptable slot = %d. ", *unit);
1307       printf("Number of bytes read = %d\n", *readsize);
1308     }
1309 
1310     return;
1311 }
1312 
1313 void bufrread(
1314 char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
1315 
1316   bufrread_(buffer,buffsize,readsize,status,unit);
1317 }
1318 
1319 /*
1320 //------------------------------------------------------------------------
1321 //  PSEUREAD
1322 //------------------------------------------------------------------------
1323 */
1324 void pseuread_(
1325 char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
1326 /*
1327 //  Called as a FORTRAN subroutine:
1328 //
1329 //    CALL PSEUREAD( KARRAY, KINLEN, KOUTLEN, IRET, KUNIT )
1330 //
1331 */
1332 fortint holdsize = *buffsize;
1333 
1334 /*
1335 // Read GRIB product
1336 */
1337     *status = readprod(NULL,buffer,&holdsize,fileRead,fileSeek,fileTell,
1338                        CURRENT_FILE);
1339     *readsize = abs(holdsize );
1340 
1341     if( DEBUG ) {
1342       printf("PBIO_PSEUREAD: fptable slot = %d. ", *unit);
1343       printf("Number of bytes read = %d\n", *readsize);
1344     }
1345 
1346     return;
1347 }
1348 
1349 void pseuread(
1350 char* buffer,fortint* buffsize,fortint* readsize,fortint* status,fortint* unit){
1351 
1352   pseuread_(buffer,buffsize,readsize,status,unit);
1353 }
1354 
1355 /*
1356 //------------------------------------------------------------------------
1357 //  PBSIZE
1358 //------------------------------------------------------------------------
1359 */
1360 void pbsize_(fortint* unit,fortint* plen) {
1361 /*
1362 //  Returns the size in bytes of the next GRIB, BUFR, TIDE, BUDG, DIAG
1363 //  product.
1364 //
1365 //  Called from FORTRAN:
1366 //      CALL PBSIZE( KUNIT, LENGTH)
1367 //
1368 //  unit  = file id returned from PBOPEN.
1369 //  plen  = size in bytes of the next product.
1370 //        = -2 if error allocating memory for internal buffer.
1371 //
1372 //  The input file is left positioned where it started.
1373 */
1374 fortint iret;
1375 char statbuff[BUFFLEN];
1376 char * buff;
1377 long offset, loop = 1;
1378 
1379 /*
1380 //  Use a smallish buffer for processing; this should suffice for all cases
1381 //  except versions -1 and 0 of GRIB and large BUFR products
1382 */
1383     offset = (fortint) fileTell( CURRENT_FILE);
1384     if( DEBUG ) {
1385       printf("PBIO_SIZE: fptable slot = %d. ", *unit);
1386       printf("Current file position = %lu\n", offset);
1387     }
1388 
1389     *plen = BUFFLEN;
1390     if( DEBUG )
1391       printf("PBIO_SIZE: current buffer size = %d\n", *plen);
1392 
1393     iret = readprod(NULL,statbuff,plen,fileRead,fileSeek,fileTell,CURRENT_FILE);
1394     if( iret == -2 ) {
1395       printf("readprod error %d\n", iret);
1396       *plen = -2;
1397       return;
1398     }
1399 /*
1400 //  If the smallish buffer is too small, progressively increase it until
1401 //  big enough
1402 */
1403     while ( iret == -4 ) {
1404       loop++;
1405       buff = (char *) malloc( BUFFLEN*loop);
1406       if( buff == NULL) {
1407         perror("malloc failed in PBSIZE");
1408         *plen = -2;
1409         return;
1410       }
1411       *plen = BUFFLEN*loop;
1412       if( DEBUG )
1413         printf("PBIO_SIZE: buffer size increased to: %d\n", *plen);
1414 
1415       offset = (fortint) fileSeek( CURRENT_FILE, offset, SEEK_SET);
1416       offset = (fortint) fileTell( CURRENT_FILE);
1417       iret = readprod(NULL,buff,plen,fileRead,fileSeek,fileTell,CURRENT_FILE);
1418       free(buff);
1419     }
1420 
1421     if( iret == -2 ) {
1422       printf("readprod error %d\n", iret);
1423       *plen = -2;
1424     }
1425 /*
1426 //  Put the file pointer back where it started
1427 */
1428     if( DEBUG ) {
1429       printf("PBIO_SIZE: file pointer set back to: %lu\n", offset);
1430       printf("PBIO_SIZE: Product size = %d\n", *plen);
1431     }
1432     offset = (fortint) fileSeek( CURRENT_FILE, offset, SEEK_SET);
1433 
1434     return ;
1435 }
1436 
1437 void pbsize(fortint* unit,fortint* plen) {
1438 
1439   pbsize_(unit,plen);
1440 }
1441 
1442 /*
1443 //------------------------------------------------------------------------
1444 //  CREXRD
1445 //------------------------------------------------------------------------
1446 */
1447 #define END_OF_FILE -1
1448 #define FILE_READ_ERROR -2
1449 #define USER_BUFFER_TOO_SMALL -3
1450 #define FILE_TOO_SMALL -5
1451 #define MINIMUM_CREX_SIZE 13
1452 #define CREX 0x43524558
1453 
1454 typedef char * String;
1455 
1456 void crexrd_(String buffer,int* bufflen,int* size,int* status,fortint * unit) {
1457 /*
1458 //  Called from FORTRAN:
1459 //    CALL CREXRD( KARRAY, KINLEN, NREAD, IRET, KUNIT )
1460 */
1461 int loop;
1462 OFF_T foundPosition;
1463 int number, crexFound = 0, endFound = 0;
1464 String endBuffer;
1465 String next;
1466 char plplcrcrlf7777[10] = {0,0,0,0,0,0,0,0,0,0};
1467 char PlPlCrCrLf7777[10] = {0x2b,0x2b,0x0d,0x0d,0x0a,0x37,0x37,0x37,0x37,0x00};
1468 
1469 /*
1470 // Check buffer big enough for CREX search
1471 */
1472   if( *bufflen < MINIMUM_CREX_SIZE ) {
1473     *status = USER_BUFFER_TOO_SMALL;
1474     return;
1475   }
1476 
1477 /*
1478 // Look for CREX
1479 */
1480   for( loop = 0; loop <= 4; loop++) buffer[loop] = '\0';
1481 
1482   while( !crexFound ) {
1483     buffer[0] = buffer[1];
1484     buffer[1] = buffer[2];
1485     buffer[2] = buffer[3];
1486     number = fread((buffer+3), 1, 1, CURRENT_FILE);
1487     if( feof(CURRENT_FILE) ) {
1488       *status = END_OF_FILE;
1489       return;
1490     }
1491     if( (number != 1) || ferror(CURRENT_FILE) ) {
1492       perror("crexrd file read error");
1493       *status = FILE_READ_ERROR;
1494       return;
1495     }
1496     if( strcmp(buffer,"CREX") == 0 ) {
1497       crexFound = 1;
1498 #ifdef FOPEN64
1499       foundPosition = ftello64(CURRENT_FILE) - 4;
1500 #else
1501       foundPosition = ftell(CURRENT_FILE) - 4;
1502 #endif
1503     }
1504   }
1505 
1506 /*
1507 // Read some more characters into the buffer
1508 */
1509   number = fread((buffer+4), 1, ((*bufflen)-4), CURRENT_FILE);
1510   if( ferror(CURRENT_FILE) ) {
1511     perror("crexrd file read error");
1512     *status = FILE_READ_ERROR;
1513     return;
1514   }
1515   endBuffer = buffer + number + 3;
1516 
1517 /*
1518 // Look for ++CrCrLf7777 at end of product
1519 */
1520   next = buffer+4;
1521   endFound = 0;
1522   for( loop = 0; loop < 8; loop++ )
1523     plplcrcrlf7777[loop] = *(next++);
1524   plplcrcrlf7777[9] = '\0';
1525 
1526   while( (!endFound) && (next<=endBuffer) ) {
1527     plplcrcrlf7777[8] = *(next++);
1528     if( strcmp(plplcrcrlf7777,PlPlCrCrLf7777) == 0 ) {
1529       endFound = 1;
1530       *size = (int) (next - buffer);
1531     }
1532 
1533     for( loop = 0; loop < 8; loop++ )
1534       plplcrcrlf7777[loop] = plplcrcrlf7777[loop+1];
1535   }
1536 
1537   if( !endFound ) {
1538     if( feof(CURRENT_FILE) )
1539       *status = END_OF_FILE;
1540     else
1541       *status = USER_BUFFER_TOO_SMALL;
1542     return;
1543   }
1544 
1545 /*
1546 // Position file at end of CREX product
1547 */
1548 #ifdef FOPEN64
1549   *status = fseeko64(CURRENT_FILE, (foundPosition+(*size)), 0);
1550 #else
1551   *status = fseek(CURRENT_FILE, (foundPosition+(*size)), 0);
1552 #endif
1553 
1554 }
1555 
1556 void crexrd(String buffer,int* bufflen,int* size,int* status,fortint * unit) {
1557 
1558   crexrd_(buffer,bufflen,size,status,unit);
1559 }
1560