SURFEX v8.1
General documentation of Surfex
bytes_io.c
Go to the documentation of this file.
1 
234 /*
235 // bytes_io.c
236 */
237 #include <unistd.h>
238 #include <stdio.h>
239 #include <string.h>
240 #include <stdlib.h>
241 #include <sys/types.h>
242 #include <sys/stat.h>
243 #include <fcntl.h>
244 #include <ctype.h>
245 
246 #ifdef PTHREADS
247 #include <pthread.h>
248 #endif
249 
250 static FILE** fptable = NULL;
251 static int fptableSize = 0;
252 
253 #ifdef PTHREADS
254 static pthread_mutex_t fpTableBusy = PTHREAD_MUTEX_INITIALIZER;
255 #endif
256 #define BUFFLEN 4096
257 
258 /*
259 // Default buffer size for I/O operations (set via setvbuf)
260 */
261 #define SIZE BUFSIZ
262 static long size = SIZE;
263 static int sizeSet = 0;
264 static char * envSize;
265 static char** fileBuffer = NULL;
266 
267 /*
268 // Debug flags.
269 */
270 #define DEBUGOFF 1
271 #define DEBUG (debugSet > DEBUGOFF )
272 static char * debugLevel;
273 static int debugSet = 0;
274 
275 #define NAMEBUFFLEN 256
276 #define MODEBUFFLEN 10
277 
278 #define CURRENT_FILE (fptable[*unit])
279 
280 /*
281 //------------------------------------------------------------------------
282 // BYTES_IO_OPEN - Open file (from FORTRAN)
283 //------------------------------------------------------------------------
284 */
285 void c_bytes_io_open_( int* unit, char* name, char* mode, int* iret,
286  int l1, int l2 ) {
287 
288 /*
289 // Purpose:
290 // Opens file, returns the index of a UNIX FILE pointer held in
291 // an internal table (fptable).
292 //
293 // First time through, reads value in environment variable BYTES_IO_BUFSIZE
294 // (if it is set) and uses it as the size to be used for internal file
295 // buffers; the value is passed to setvbuf. If BYTES_IO_BUFSIZE is not set,
296 // a default value is used.
297 //
298 // Function accepts:
299 // name = filename
300 // mode = r, r+, w
301 //
302 // Note: l1 and l2 are the lengths of the FORTRAN character strings
303 // in name and mode, and should not be passed.
304 //
305 // Function returns:
306 // INTEGER iret:
307 // -1 = Could not open file.
308 // -2 = Invalid file name.
309 // -3 = Invalid open mode specified
310 // 0 = OK.
311 */
312 int n;
313 char *p;
314 char flags[4];
315 
316 char namebuff[NAMEBUFFLEN+1], modebuff[MODEBUFFLEN+1];
317 
318 /*
319 // See if DEBUG switched on.
320 */
321  if( ! debugSet ) {
322  debugLevel = getenv("BYTES_IO_DEBUG");
323  if( debugLevel == NULL )
324  debugSet = DEBUGOFF; /* off */
325  else {
326  int loop;
327  for( loop = 0; loop < strlen(debugLevel) ; loop++ ) {
328  if( ! isdigit(debugLevel[loop]) ) {
329  printf("Invalid number string in BYTES_IO_DEBUG: %s\n", debugLevel);
330  printf("BYTES_IO_DEBUG must comprise only digits [0-9].\n");
331  debugSet = DEBUGOFF;
332  }
333  }
334  debugSet = DEBUGOFF + atol( debugLevel );
335  }
336  if( DEBUG ) printf("BYTES_IO_OPEN: debug switched on\n");
337  }
338 
339 /*
340 // Put the character strings into buffers and ensure that there is a
341 // null terminator (for SGI case when FORTRAN CHARACTER variable is full
342 // right to end with characters
343 */
344  {
345  int n1, n2;
346  n1 = (l1>NAMEBUFFLEN) ? NAMEBUFFLEN : l1;
347  n2 = (l2>MODEBUFFLEN) ? MODEBUFFLEN : l2;
348 
349  strncpy( namebuff, name, n1);
350  strncpy( modebuff, mode, n2);
351  namebuff[n1] = '\0';
352  modebuff[n2] = '\0';
353  }
354 
355  strcpy(flags,"");
356 
357  /* *unit = (int) NULL; sami bug fix */
358  *unit = 0;
359  *iret = 0;
360 
361 /*
362 // Strip trailing blanks
363 */
364  p = namebuff + strlen(namebuff) - 1 ;
365  while(*p == ' ') {
366  *p = 0;
367  p--;
368  }
369 
370  if( DEBUG ) printf("BYTES_IO_OPEN: filename = [%s]\n", namebuff);
371 /*
372 // Build open flags from "modes"
373 */
374  p = modebuff;
375 
376  switch(*p) {
377 
378  case 'a':
379  case 'A': strcat(flags, "a");
380  break;
381 
382  case 'c':
383  case 'C':
384  case 'w':
385  case 'W': strcat(flags, "w");
386  break;
387 
388  case 'r':
389  case 'R':
390  if( *(p+1) == '+' )
391  strcat(flags, "r+");
392  else
393  strcat(flags, "r");
394  break;
395 
396  default: *iret = -3;
397  return;
398 
399  }
400  if( DEBUG ) printf("BYTES_IO_OPEN: file open mode = %s\n", flags);
401 
402 /*
403 // Look for a free slot in fptable.
404 // (Create the table the first time through).
405 */
406 #ifdef PTHREADS
407 /*
408 // Wait if another thread opening a file
409 */
410  pthread_mutex_lock(&fpTableBusy);
411 #endif
412 
413  n = 0;
414  if( fptableSize == 0 ) {
415  int i;
416  fptableSize = 2;
417  fptable = (FILE **) malloc(fptableSize*sizeof(FILE *));
418  if( fptable == NULL ) {
419  perror("Unable to allocate space for table of FILE pointers");
420  exit(1);
421  }
422 
423  fileBuffer = (char **) malloc(fptableSize*sizeof(char *));
424  if( fileBuffer == NULL ) {
425  perror("Unable to allocate space for FILE buffers");
426  exit(1);
427  }
428 
429  for( i = 0; i < fptableSize; i++ ) {
430  fptable[i] = 0;
431  fileBuffer[i] = NULL;
432  }
433  }
434  else {
435  while( n < fptableSize ) {
436  if(fptable[n]==0) {
437  *unit = n;
438  break;
439  }
440  n++;
441  }
442  }
443 /*
444 // If the table overflows, double its size.
445 */
446  if( n == fptableSize) {
447  int i;
449  fptable = (FILE **) realloc(fptable, fptableSize*sizeof(FILE *));
450  if( fptable == NULL ) {
451  perror("Unable to reallocate space for table of FILE pointers");
452  exit(1);
453  }
454  n = fptableSize/2;
455 
456  fileBuffer = (char **) realloc(fileBuffer, fptableSize*sizeof(char *));
457  if( fileBuffer == NULL ) {
458  perror("Unable to allocate space for FILE buffers");
459  exit(1);
460  }
461 
462  n = fptableSize/2;
463  for( i = n; i < fptableSize; i++ ) {
464  fptable[i] = 0;
465  fileBuffer[i] = NULL;
466  }
467 
468  *unit = n;
469  }
470 
471  if( DEBUG ) printf("BYTES_IO_OPEN: fptable slot = %d\n", *unit);
472 
473  if( DEBUG ) printf("BYTES_IO_OPEN: using fopen\n");
474  fptable[n] = fopen(namebuff, flags );
475 
476  if(fptable[n] == NULL) {
477  perror(namebuff);
478  *iret = -1;
479 #ifdef PTHREADS
480  pthread_mutex_unlock(&fpTableBusy);
481 #endif
482  return;
483  }
484 
485 /*
486 // Now allocate a buffer for the file, if necessary.
487 */
488  if( ! sizeSet ) {
489  envSize = getenv("BYTES_IO_BUFSIZE");
490  if( envSize == NULL )
491  size = SIZE; /* default */
492  else {
493  int loop;
494  for( loop = 0; loop < strlen(envSize) ; loop++ ) {
495  if( ! isdigit(envSize[loop]) ) {
496  printf("Invalid number string in BYTES_IO_BUFSIZE: %s\n", envSize);
497  printf("BYTES_IO_BUFSIZE must comprise only digits [0-9].\n");
498  exit(1);
499  }
500  }
501  size = atol( envSize );
502  }
503  if( size <= 0 ) {
504  printf("Invalid buffer size in BYTES_IO_BUFSIZE: %s\n", envSize);
505  printf("Buffer size defined by BYTES_IO_BUFSIZE must be positive.\n");
506  exit(1);
507  }
508  sizeSet = 1;
509  }
510 
511  if( DEBUG ) printf("BYTES_IO_OPEN: file buffer size = %ld\n", size);
512 
513  if( fileBuffer[n] == NULL ) {
514  fileBuffer[n] = (char *) malloc(size);
515  }
516 
517  if( setvbuf(CURRENT_FILE, fileBuffer[*unit], _IOFBF, size) ) {
518  perror("setvbuf failed");
519  *iret = -1;
520  }
521 
522 #ifdef PTHREADS
523  pthread_mutex_unlock(&fpTableBusy);
524 #endif
525 }
526 
527 void c_bytes_io_open__( int* unit, char* name, char* mode, int* iret, int l1, int l2 ) {
528  c_bytes_io_open_(unit,name,mode,iret,l1,l2);
529 }
530 void c_bytes_io_open( int* unit, char* name, char* mode, int* iret, int l1, int l2 ) {
531  c_bytes_io_open_(unit,name,mode,iret,l1,l2);
532 }
533 
534 /*
535 //------------------------------------------------------------------------
536 // BYTES_IO_SEEK - Seek (from FORTRAN)
537 //------------------------------------------------------------------------
538 */
539 void c_bytes_io_seek_(int* unit,int* offset,int* whence,int* iret) {
540 /*
541 //
542 // Purpose:
543 // Seeks to a specified location in file.
544 //
545 // Function accepts:
546 // unit = the index of a UNIX FILE pointer held in
547 // an internal table (fptable).
548 //
549 // offset = byte count
550 //
551 // whence = 0, from start of file
552 // = 1, from current position
553 // = 2, from end of file.
554 //
555 // Returns:
556 // iret:
557 // -2 = error in handling file,
558 // -1 = end-of-file
559 // otherwise, = byte offset from start of file.
560 */
561 int my_offset = (int) *offset;
562 int my_whence = (int) *whence;
563 
564 /*
565 // Must use negative offset if working from end-of-file
566 */
567  if( DEBUG ) {
568  printf("BYTES_IO_SEEK: fptable slot = %d\n", *unit);
569  printf("BYTES_IO_SEEK: Offset = %d\n", my_offset);
570  printf("BYTES_IO_SEEK: Type of offset = %d\n", my_whence);
571  }
572 
573  if( my_whence == 2) my_offset = - abs(my_offset);
574 
575  *iret = ftell(CURRENT_FILE);
576  if( DEBUG ) printf("BYTES_IO_SEEK: current position = %d\n", *iret);
577  if( *iret == my_offset && my_whence == 0)
578  *iret = 0;
579  else
580  *iret = fseek(CURRENT_FILE, my_offset, my_whence);
581 
582  if( DEBUG ) printf("BYTES_IO_SEEK: fseek return code = %d\n",*iret);
583 
584  if( *iret != 0 ) {
585  if( ! feof(CURRENT_FILE) ) {
586  *iret = -2; /* error in file-handling */
587  perror("bytes_io_seek");
588  }
589  else
590  *iret = -1; /* end-of-file */
591 
592  clearerr(CURRENT_FILE);
593  return;
594  }
595 
596 /*
597 // Return the byte offset from start of file
598 */
599  *iret = ftell(CURRENT_FILE);
600 
601  if( DEBUG )
602  printf("BYTES_IO_SEEK: byte offset from start of file = %d\n",*iret);
603 
604  return;
605 
606 }
607 
608 void c_bytes_io_seek(int* unit,int* offset,int* whence,int* iret) {
609  c_bytes_io_seek_(unit,offset,whence,iret);
610 }
611 
612 
613 /*
614 //------------------------------------------------------------------------
615 // BYTES_IO_TELL - Tells current file position (from FORTRAN)
616 //------------------------------------------------------------------------
617 */
618 void c_bytes_io_tell_(int* unit,int* iret) {
619 /*
620 //
621 // Purpose:
622 // Tells current byte offset in file.
623 //
624 // Function accepts:
625 // unit = the index of a UNIX FILE pointer held in
626 // an internal table (fptable).
627 //
628 // Returns:
629 // iret:
630 // -2 = error in handling file,
631 // otherwise, = byte offset from start of file.
632 */
633 
634 
635 /*
636 // Return the byte offset from start of file
637 */
638  *iret = ftell(CURRENT_FILE);
639 
640  if( *iret < 0 ) {
641  if( DEBUG ) { /* error in file-handling */
642  printf("BYTES_IO_TELL: fptable slot = %d. ", *unit);
643  printf("Error status = %d\n", *iret);
644  }
645  perror("bytes_io_tell");
646  *iret = -2;
647  }
648 
649  if( DEBUG ) {
650  printf("BYTES_IO_TELL: fptable slot = %d. ", *unit);
651  printf("Byte offset from start of file = %d\n",*iret);
652  }
653 
654  return;
655 }
656 
657 void c_bytes_io_tell__(int* unit,int* iret) {
658  c_bytes_io_tell_(unit,iret);
659 }
660 
661 void c_bytes_io_tell(int* unit,int* iret) {
662  c_bytes_io_tell_(unit,iret);
663 }
664 
665 
666 /*
667 //------------------------------------------------------------------------
668 // BYTES_IO_READ - Read (from FORTRAN)
669 //------------------------------------------------------------------------
670 */
671 void c_bytes_io_read_(int* unit,char* buffer,int* nbytes,int* iret) {
672 /*
673 // Purpose:
674 // Reads a block of bytes from a file..
675 //
676 // Function accepts:
677 // unit = the index of a UNIX FILE pointer held in
678 // an internal table (fptable).
679 //
680 // nbytes = number of bytes to read.
681 //
682 // Returns:
683 // iret:
684 // -2 = error in reading file,
685 // -1 = end-of-file,
686 // otherwise, = number of bytes read.
687 */
688  if( DEBUG ) {
689  printf("BYTES_IO_READ: fptable slot = %d. ", *unit);
690  printf("Number of bytes to read = %d\n", *nbytes);
691  }
692 
693  if( (*iret = fread(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
694  if( ! feof(CURRENT_FILE) ) {
695  *iret = -2; /* error in file-handling */
696  perror("bytes_io_read");
697  clearerr(CURRENT_FILE);
698  return;
699  }
700  else {
701  *iret = -1; /* end-of-file */
702  clearerr(CURRENT_FILE);
703  }
704  }
705 
706  if( DEBUG ) {
707  printf("BYTES_IO_READ: fptable slot = %d. ", *unit);
708  printf("Number of bytes read = %d\n", *nbytes);
709  }
710 
711  return;
712 }
713 
714 void c_bytes_io_read__(int* unit,char* buffer,int* nbytes,int* iret) {
715  c_bytes_io_read_(unit,buffer,nbytes,iret);
716 }
717 
718 void c_bytes_io_read(int* unit,char* buffer,int* nbytes,int* iret) {
719  c_bytes_io_read_(unit,buffer,nbytes,iret);
720 }
721 
722 
723 /*
724 //------------------------------------------------------------------------
725 // BYTES_IO_WRITE - Write (from FORTRAN)
726 //------------------------------------------------------------------------
727 */
728 void c_bytes_io_write_(int* unit,char* buffer,int* nbytes,int* iret) {
729 /*
730 // Purpose:
731 // Writes a block of bytes to a file.
732 //
733 // Function accepts:
734 // unit = the index of a UNIX FILE pointer held in
735 // an internal table (fptable).
736 //
737 // nbytes = number of bytes to write.
738 //
739 // Returns:
740 // iret:
741 // -1 = Could not write to file.
742 // >=0 = Number of bytes written.
743 */
744  if( DEBUG ) {
745  printf("BYTES_IO_WRITE: fptable slot = %d. ", *unit);
746  printf("Number of bytes to write = %d\n", *nbytes);
747  }
748 
749  if( (*iret = fwrite(buffer, 1, *nbytes, CURRENT_FILE) ) != *nbytes) {
750  perror("bytes_io_write");
751  *iret = -1;
752  }
753 
754  if( DEBUG ) {
755  printf("BYTES_IO_WRITE: fptable slot = %d. ", *unit);
756  printf("BYTES_IO_WRITE: number of bytes written = %d\n", *iret);
757  }
758 
759  return;
760 }
761 
762 void c_bytes_io_write__(int* unit,char* buffer,int* nbytes,int* iret) {
763  c_bytes_io_write_(unit,buffer,nbytes,iret);
764 }
765 
766 void c_bytes_io_write(int* unit,char* buffer,int* nbytes,int* iret) {
767  c_bytes_io_write_(unit,buffer,nbytes,iret);
768 }
769 
770 /*
771 //------------------------------------------------------------------------
772 // BYTES_IO_CLOSE - close (from FORTRAN)
773 //------------------------------------------------------------------------
774 */
775 void c_bytes_io_close_(int* unit,int* iret) {
776 /*
777 // Purpose:
778 // Closes file.
779 //
780 // Function accepts:
781 // unit = the index of a UNIX FILE pointer held in
782 // an internal table (fptable).
784 // iret:
785 // 0 = OK.
786 // otherwise = error in handling file.
787 */
788  if( DEBUG )
789  printf("BYTES_IO_CLOSE: fptable slot = %d\n", *unit);
790 
791  if( ( *iret = fclose(CURRENT_FILE) ) != 0 ) perror("bytes_io_close");
792  CURRENT_FILE = 0;
793 
794  return;
795 }
796 
797 void c_bytes_io_close__(int* unit,int* iret) {
798  c_bytes_io_close_(unit,iret);
799 }
800 
801 void c_bytes_io_close(int* unit,int* iret) {
802  c_bytes_io_close_(unit,iret);
803 }
804 
805 /*
806 //------------------------------------------------------------------------
807 // BYTES_IO_FLUSH - flush (from FORTRAN)
808 //------------------------------------------------------------------------
809 */
810 void c_bytes_io_flush_(int * unit) {
811 /*
812 // Purpose: Flushes file.
813 */
814  if( DEBUG )
815  printf("BYTES_IO_FLUSH: fptable slot = %d\n", *unit);
816 
817  fflush(CURRENT_FILE);
818 }
819 
820 void c_bytes_io_flush__(int * unit) {
821  c_bytes_io_flush_(unit);
822 }
823 
824 void c_bytes_io_flush(int * unit) {
825  c_bytes_io_flush_(unit);
826 }
static int fptableSize
Definition: bytes_io.c:251
static long size
Definition: bytes_io.c:262
void c_bytes_io_write__(int *unit, char *buffer, int *nbytes, int *iret)
Definition: bytes_io.c:762
void c_bytes_io_close_(int *unit, int *iret)
Definition: bytes_io.c:775
void c_bytes_io_open(int *unit, char *name, char *mode, int *iret, int l1, int l2)
Definition: bytes_io.c:530
static pthread_mutex_t fpTableBusy
Definition: bytes_io.c:254
static char * envSize
Definition: bytes_io.c:264
void c_bytes_io_open_(int *unit, char *name, char *mode, int *iret, int l1, int l2)
Definition: bytes_io.c:285
void c_bytes_io_tell_(int *unit, int *iret)
Definition: bytes_io.c:618
void c_bytes_io_write_(int *unit, char *buffer, int *nbytes, int *iret)
Definition: bytes_io.c:728
integer(kind=jpim) iret
Definition: distio_mix.F90:26
quick &counting sorts only inumt inumt name
void c_bytes_io_seek_(int *unit, int *offset, int *whence, int *iret)
Definition: bytes_io.c:539
void c_bytes_io_close__(int *unit, int *iret)
Definition: bytes_io.c:797
void c_bytes_io_write(int *unit, char *buffer, int *nbytes, int *iret)
Definition: bytes_io.c:766
static int debugSet
Definition: bytes_io.c:273
void c_bytes_io_read_(int *unit, char *buffer, int *nbytes, int *iret)
Definition: bytes_io.c:671
static char ** fileBuffer
Definition: bytes_io.c:265
void c_bytes_io_flush__(int *unit)
Definition: bytes_io.c:820
void c_bytes_io_open__(int *unit, char *name, char *mode, int *iret, int l1, int l2)
Definition: bytes_io.c:527
ERROR in n
Definition: ecsort_shared.h:90
void c_bytes_io_tell(int *unit, int *iret)
Definition: bytes_io.c:661
static int sizeSet
Definition: bytes_io.c:263
void c_bytes_io_close(int *unit, int *iret)
Definition: bytes_io.c:801
static char * debugLevel
Definition: bytes_io.c:272
void c_bytes_io_tell__(int *unit, int *iret)
Definition: bytes_io.c:657
void c_bytes_io_read__(int *unit, char *buffer, int *nbytes, int *iret)
Definition: bytes_io.c:714
void c_bytes_io_flush_(int *unit)
Definition: bytes_io.c:810
void c_bytes_io_flush(int *unit)
Definition: bytes_io.c:824
void c_bytes_io_seek(int *unit, int *offset, int *whence, int *iret)
Definition: bytes_io.c:608
void c_bytes_io_read(int *unit, char *buffer, int *nbytes, int *iret)
Definition: bytes_io.c:718
static FILE ** fptable
Definition: bytes_io.c:250