/************************************************************
Abstract
ewiscomp.c - Compress and Expand ewis file

(C) Copyright AU-System Communication AB 1994.

Change activity
1994-12-12      Arg  Created

Description
************************************************************                */

#ifdef   VMS
#include <types.h>
#include <stdio.h>
#include <string.h>
#include <stat.h>
#include <errno.h>
#else
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <malloc.h>
#endif
#include "api.h"
#include "ewiscomp.h"
#include "comp.h"
#include "ewis_fileheader.h"

/*----------------------------------------------------------
*       Macros
*---------------------------------------------------------                  */
#define  READ_MODE     0
#define  WRITE_MODE    1
#define  MAX_INDEX     0xFFFFF
#define  LONG_DATA_SIZE 16383

/*----------------------------------------------------------
*       Functions
*---------------------------------------------------------                  */
/*----------------------------------------------------------
*       Structures
*---------------------------------------------------------                  */
/* -------------------------------------------------------                  */
/* ***************<  COMPRESS  >**************************                  */
/* -------------------------------------------------------                  */
/*----------------------------------------------------------
*  call pckCompressEwisFile - 
*---------------------------------------------------------                  */

INT32 pckCompressEwisFile (char *SourceFileStr,char *DestFileStr)
{
  INT32 iRc = PCK_OK;
  INT32 iStatus;
  char	Header [512];
  ewis_fileheader_t *pHeader;

  FILE  *InFile;
  FILE  *OutFile;
  INT32 iBytesWritten, iBytesRead;
  INT32	iInFileSize, iOutFileSize, iReadSize;
  int	iSaveErrno;
  size_t iMallocSize;
  struct stat FileInfo;
  PixBuffer_t *pInData;
  PixBuffer_t *pOutData;


  pHeader = (ewis_fileheader_t *) Header;

  /* Open infile */
  if ((InFile = fopen(SourceFileStr,"rb","ctx=stm")) == NULL)  
    {
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Read header */
  iBytesRead = fread(Header,1,512,InFile);
  if (iBytesRead != 512)
  {
    iSaveErrno = errno;
    fclose(InFile);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
  }

  /* Check that file is an EWIS product */
  if (strncmp(pHeader->ident, pic_check_data,8) != 0)
  {
    fclose(InFile);
    iRc = PCK_ILLEGALFILE; 
    return iRc;
  } 

  /* Check that file is not already compressed */
  if (pHeader->compressed == TRUE)
    {
    fclose(InFile);
    iRc = PGFALRCNV; 
    return iRc;
    } 

  /* Get size of infile */
  iStatus = fstat(fileno(InFile),&FileInfo);
  iInFileSize = FileInfo.st_size;

  /* Get size of outfile */
  iOutFileSize = pHeader->pixel_cnt;

  /* Allocate buffers for input and output data */
  iMallocSize = (size_t)(iInFileSize + sizeof(PixBuffer_t));
  pInData = (PixBuffer_t *) malloc(iMallocSize);
  if (pInData == NULL)
    {
    fclose(InFile);
    iRc = PCK_NOMEM; 
    return iRc;
    } 

  pInData->Compressed = FALSE;
  pInData->iMaxSize = iMallocSize;
  pInData->Data.iMaxSize = iInFileSize;

  /* Allow outbuffer to be bigger than input buffer   */
  /* Sad combinations of data could make a compressed */
  /* file bigger than the uncompressed!		      */

  iMallocSize = iMallocSize + (iMallocSize / 10);	
  pOutData = (PixBuffer_t *) malloc(iMallocSize);
  if (pOutData == NULL)
    {
    fclose(InFile);
    free (pInData);
    iRc = PCK_NOMEM; 
    return iRc;
    } 

  pOutData->Compressed = TRUE;
  pOutData->iMaxSize = iMallocSize;
  pOutData->Data.iMaxSize = iOutFileSize;

  /* Read input file */
  iReadSize = iInFileSize - 512;
  iBytesRead = fread(&pInData->Data.ByteData[0],1,iReadSize,InFile);
  if (iBytesRead != iReadSize)
    {
    iSaveErrno = errno;
    fclose(InFile);
    free (pInData);
    free (pOutData);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Create output file */
  if ((OutFile = fopen(DestFileStr,"wb")) == NULL)  
    {
    iSaveErrno = errno;
    fclose(InFile);
    free (pInData);
    free (pOutData);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Update and write header */
  pHeader->compressed = TRUE;
  if (fwrite(Header,512,1,OutFile) != 1)
    {
    iSaveErrno = errno;
    fclose(InFile);
    fclose(OutFile);
    remove(DestFileStr);
    free (pInData);
    free (pOutData);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Compress the inbuffer into the outbuffer */
  if ((iRc = pckPixReset(READ_MODE, 
                         pInData)) == PCK_OK)
     if ((iRc = pckPixReset(WRITE_MODE, 
     			    pOutData)) == PCK_OK)
        iRc = pckPixCopy(pInData, 
        		 pOutData, 
                         iOutFileSize);
     if (iRc == PCK_OK)
       {
       iBytesWritten = fwrite(&pOutData->Data.ByteData[0], 
          		      sizeof(char), 
			      pOutData->Data.iLen,
			      OutFile);
       if (iBytesWritten != pOutData->Data.iLen)
         {
	 iSaveErrno = errno;
	 fclose(InFile);
	 fclose(OutFile);
	 remove(DestFileStr);
	 free(pInData);
	 free(pOutData);
	 errno = iSaveErrno;
	 return  PCK_IO_ERROR;
         } 
       } /* if (iRc == PCK_OK) */
     else
       {
       fclose(InFile);
       fclose(OutFile);
       remove(DestFileStr);
       free(pInData);
       free(pOutData);
       return  PCK_FAIL;
       }

    fclose(InFile);
    fclose(OutFile);
    free (pInData);
    free (pOutData);
    return  iRc;
} 

/* -------------------------------------------------------                  */
/* ***************<  EXPAND >**************************                  */
/* -------------------------------------------------------                  */
/*----------------------------------------------------------
*  call pckExpandEwisFile - 
*---------------------------------------------------------                  */

INT32 pckExpandEwisFile (char *SourceFileStr,char *DestFileStr)
{
  INT32 iRc = PCK_OK;
  INT32 iStatus;
  char	Header [512];
  ewis_fileheader_t *pHeader;

  FILE  *InFile;
  FILE  *OutFile;
  int	iSaveErrno;
  INT32 iBytesWritten, iBytesRead;
  INT32	iInFileSize, iOutFileSize, iReadSize;
  size_t iMallocSize;
  struct stat FileInfo;
  PixBuffer_t *pInData;
  PixBuffer_t *pOutData;


  pHeader = (ewis_fileheader_t *) Header;

  /* Open infile */
  if ((InFile = fopen(SourceFileStr,"rb","ctx=stm")) == NULL)  
    {
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Read header */
  iBytesRead = fread(Header,1,512,InFile);
  if (iBytesRead != 512)
  {
    iSaveErrno = errno;
    fclose(InFile);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
  }

  /* Check that file is an EWIS product */
  if (strncmp(pHeader->ident,pic_check_data,8)  != 0)
  {
    fclose(InFile);
    iRc = PCK_ILLEGALFILE; 
    return iRc;
  } 

  /* Check that file is not already expanded */
  if (pHeader->compressed == FALSE)
    {
    fclose(InFile);
    iRc = PGFALRCNV; 
    return iRc;
    } 

  /* Get size of infile */
  iStatus = fstat(fileno(InFile),&FileInfo);
  iInFileSize = FileInfo.st_size;

  /* Get size of outfile */
  iOutFileSize = pHeader->pixel_cnt;

  /* Allocate buffers for input and output data */
  iMallocSize = (size_t)(iInFileSize + sizeof(PixBuffer_t));
  pInData = (PixBuffer_t *) malloc(iMallocSize);
  if (pInData == NULL)
    {
    fclose(InFile);
    iRc = PCK_NOMEM; 
    return iRc;
    } 

  pInData->Compressed = TRUE;
  pInData->iMaxSize = iMallocSize;
  pInData->Data.iMaxSize = iInFileSize;

  iMallocSize = (size_t)(iOutFileSize + sizeof(PixBuffer_t));
  pOutData = (PixBuffer_t *) malloc(iMallocSize);
  if (pOutData == NULL)
    {
    fclose(InFile);
    free (pInData);
    iRc = PCK_NOMEM; 
    return iRc;
    } 

  pOutData->Compressed = FALSE;
  pOutData->iMaxSize = iMallocSize;
  pOutData->Data.iMaxSize = iOutFileSize;

  /* Read input file */
  iReadSize = iInFileSize - 512;
  iBytesRead = fread(&pInData->Data.ByteData[0],1,iReadSize,InFile);
  if (iBytesRead != iReadSize)
    {
    iSaveErrno = errno;
    fclose(InFile);
    free (pInData);
    free (pOutData);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Create output file */
  if ((OutFile = fopen(DestFileStr,"wb")) == NULL)  
    {
    iSaveErrno = errno;
    fclose(InFile);
    free (pInData);
    free (pOutData);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Update and write header */
  pHeader->compressed = FALSE;
  iBytesWritten = fwrite(Header,1,512,OutFile);
  if (iBytesWritten != 512)
    {
    iSaveErrno = errno;
    fclose(InFile);
    fclose(OutFile);
    remove(DestFileStr);
    free (pInData);
    free (pOutData);
    errno = iSaveErrno;
    iRc = PCK_IO_ERROR;
    return iRc;
    }

  /* Expand the inbuffer into the outbuffer */
  if ((iRc = pckPixReset(READ_MODE, 
                         pInData)) == PCK_OK)
     if ((iRc = pckPixReset(WRITE_MODE, 
     			    pOutData)) == PCK_OK)
        iRc = pckPixCopy(pInData, 
        		 pOutData, 
                         iOutFileSize);
     if (iRc == PCK_OK)
       {
       iBytesWritten = fwrite(&pOutData->Data.ByteData[0], 
          		      sizeof(char), 
			      pOutData->Data.iLen,
			      OutFile);
       if (iBytesWritten != pOutData->Data.iLen)
          {
	  iSaveErrno = errno;
	  fclose(InFile);
	  fclose(OutFile);
	  remove(DestFileStr);
	  free(pInData);
	  free(pOutData);
	  errno = iSaveErrno;
	  return  PCK_IO_ERROR;
          } 
       } /* if (iRc == PCK_OK) */
     else
       {
       fclose(InFile);
       fclose(OutFile);
       remove(DestFileStr);
       free(pInData);
       free(pOutData);
       return  PCK_FAIL;
       } 
    fclose(InFile);
    fclose(OutFile);
    free (pInData);
    free (pOutData);
    return  iRc;
} 
