#include <stdio.h>
#include <string.h>
#include "dbext.h"  /* READ_ONLY, READ_WRITE, *_ERROR, MAXINT */
/*****************************************************************************
*                                                                            *
*      COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS)                       *
*                                                                            *
*      WRITTEN BY:  RAMON CABRERA, ERIC FIRING, and JULIE RANADA             *
*                   JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH      *
*                   1000 POPE ROAD  MSB 404                                  *
*                   HONOLULU, HI 96822                                       *
*                                                                            *
*      VERSION:     3.00                                                     *
*                                                                            *
*      DATE:        APRIL 1989                                               *
*                                                                            *
*****************************************************************************/
/*

    FILE:  io_.c

           General-purpose input-output routines.

*/
/*----------------------------------------------------------------------------

   FUNCTION:  open_binary_file

      It opens a file for binary mode IO.

   PARAMETERS:
   
      filename_ptr = address of first character in filename
                     (string must terminate with NUL)

      accmode = access mode (READ_ONLY, READ_WRITE)

   RETURNS:  file pointer if successful
             NULL         if unsuccessful in opening file

   CALLED FROM:  C

*/
#if PROTOTYPE_ALLOWED
FILE *open_binary_file(char *filename_ptr, int accmode)
#else
FILE *open_binary_file(filename_ptr, accmode)
char *filename_ptr;
int accmode;
#endif
{
   switch(accmode)
   {
      case READ_ONLY:  return(fopen(filename_ptr, "rb"));
      case READ_WRITE: return(fopen(filename_ptr, "r+b"));
      default:         return(NULL);
   }
}

/*-----------------------------------------------------------------------------

   FUNCTION: EXISTS

      It checks whether a file already exists.

   PARAMETER:  

      filename_ptr = address of first character in filename
                     (string must terminate with NUL)

   RETURNS:  1 if file exists
             0 otherwise

   CALLED FROM:  C, FORTRAN

*/
#if PROTOTYPE_ALLOWED
int EXISTS(char *filename_ptr)
#else
int EXISTS(filename_ptr)
char *filename_ptr;
#endif
{
   FILE *fp;

   if ((fp = fopen(filename_ptr, "r")) == NULL)
      return(0);
   fclose(fp);
   return(1);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  read_data

      This is a random access read function.

   PARAMETERS: 
    
      fp = pointer to FILE to read from

      data_add = address of array/struct where data to be read will be stored
               
      data_offset = offset from beginning of file of first byte of data to be
                    read

      nb = number of bytes to read

   RETURNS:  0  if n bytes have been read from the indicated offset
             SEEK_ERROR OR READ_ERROR otherwise

   CALLED FROM:  C

*/
#if PROTOTYPE_ALLOWED
int read_data(FILE *fp, char *data_add, long data_offset, unsigned int nb)
#else
int read_data(fp, data_add, data_offset, nb)
FILE *fp;
char *data_add;
long data_offset;
unsigned int nb;
#endif
{
   if (nb == 0) return(0);
   if (fseek(fp, data_offset, 0)) return(SEEK_ERROR);
   while (nb > MAXINT)                     /*jr+*/
   {
      if (fread(data_add, 1, MAXINT, fp) != MAXINT) return(READ_ERROR);
      nb -= MAXINT;
      data_add += MAXINT;
   }
   if (fread(data_add, 1, nb, fp) != nb) return(READ_ERROR);
   return(0);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  write_data

      This is a random access write function.

   PARAMETERS:
    
      fp = pointer to FILE to write to

      data_add = address of array/struct where the data to be written is stored
               
      data_offset = offset from beginning of file to start writing data

      nb = number of bytes to write

   RETURNS:  0 if n bytes have been written successfully
             SEEK_ERROR OR WRITE_ERROR otherwise

   CALLED FROM:  C

*/
#if PROTOTYPE_ALLOWED
int write_data(FILE *fp, char *data_add, long data_offset, unsigned int nb)
#else
int write_data(fp, data_add, data_offset, nb)
FILE *fp;
char *data_add;
long data_offset;
unsigned int nb;
#endif
{
   if (nb == 0) return(0);
   if (fseek(fp, data_offset, 0)) return(SEEK_ERROR);
   while (nb > MAXINT)
   {
      if (fwrite(data_add, 1, MAXINT, fp) != MAXINT) return(WRITE_ERROR);
      nb -= MAXINT;
      data_add += MAXINT;
   }
   if (fwrite(data_add, 1, nb, fp) != nb) return(WRITE_ERROR);
   return(0);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  copy_data

      It copies data from one file to another.

   PARAMETERS:
   
      fp1 = pointer to source file

      fp2 = pointer to target file

      ofs1 = offset to data in source file
      
      ofs2 = offset to data in target file
      
      nb = number of bytes to copy


   RETURNS:  0 if nb bytes have been successfully copied
             SEEK_ERROR, READ_ERROR, OR WRITE_ERROR otherwise

   CALLED FROM:  C

*/
#if PROTOTYPE_ALLOWED
int copy_data(FILE *fp1, FILE *fp2, long ofs1, long ofs2, unsigned int nb)
#else
int copy_data(fp1, fp2, ofs1, ofs2, nb)
FILE *fp1, *fp2;
long ofs1, ofs2;
unsigned int nb;
#endif
{
   char data[512];

   if (nb == 0) return(0);
   if (fseek(fp1, ofs1, 0)) return(SEEK_ERROR);
   if (fseek(fp2, ofs2, 0)) return(SEEK_ERROR);
   while (nb > 512)   /* copy in blocks of 512 bytes */
   {
      if (fread (data, 1, 512, fp1) != 512) return(READ_ERROR);
      if (fwrite(data, 1, 512, fp2) != 512) return(WRITE_ERROR);
      nb -= 512;
   }                 /* copy remaining bytes <= 512 */
   if (fread (data, 1, nb, fp1) != nb) return(READ_ERROR);
   if (fwrite(data, 1, nb, fp2) != nb) return(WRITE_ERROR);
   return(0);
}

