home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / dos / prg / midas / rawfile.c < prev    next >
C/C++ Source or Header  |  1994-08-06  |  13KB  |  480 lines

  1. /*      RAWFILE.C
  2.  *
  3.  * Raw file I/O for MIDAS Sound System
  4.  *
  5.  * Copyright 1994 Petteri Kangaslampi and Jarno Paananen
  6.  *
  7.  * This file is part of the MIDAS Sound System, and may only be
  8.  * used, modified and distributed under the terms of the MIDAS
  9.  * Sound System license, LICENSE.TXT. By continuing to use,
  10.  * modify or distribute this file you indicate that you have
  11.  * read the license and understand and accept it fully.
  12. */
  13.  
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <errno.h>
  18. #include "lang.h"
  19. #include "mtypes.h"
  20. #include "errors.h"
  21. #include "mmem.h"
  22. #include "rawfile.h"
  23.  
  24.  
  25. /****************************************************************************\
  26. *
  27. * Function:     int ErrorCode(void)
  28. *
  29. * Description:  Get the MIDAS error code corresponding to errno.
  30. *
  31. * Returns:      MIDAS error code
  32. *
  33. \****************************************************************************/
  34.  
  35. static int ErrorCode(void)
  36. {
  37.     switch ( errno )
  38.     {
  39.         case ENOENT:
  40.             return errFileNotFound;
  41.  
  42.         case ENODEV:
  43.         #ifdef ENOPATH
  44.         case ENOPATH:
  45.         #endif
  46.             return errInvalidPath;
  47.  
  48.         case EMFILE:
  49.             return errTooManyFiles;
  50.  
  51.         case EBADF:
  52.             return errInvalidFileHandle;
  53.  
  54.         case EACCES:
  55.             return errAccessDenied;
  56.  
  57.         case ENOMEM:
  58.             return errOutOfMemory;
  59.  
  60.         case EEXIST:
  61.             return errFileExists;
  62.  
  63.         default:
  64.             return errUndefined;
  65.     }
  66. }
  67.  
  68.  
  69.  
  70.  
  71. /****************************************************************************\
  72. *
  73. * Function:     int rfOpen(char *fileName, int openMode, rfHandle *file);
  74. *
  75. * Description:  Opens a file for reading or writing
  76. *
  77. * Input:        char *fileName          name of file
  78. *               int openMode            file opening mode, see enum rfOpenMode
  79. *               rfHandle *file          pointer to file handle
  80. *
  81. * Returns:      MIDAS error code.
  82. *               File handle is stored in *file.
  83. *
  84. \****************************************************************************/
  85.  
  86. int CALLING rfOpen(char *fileName, int openMode, rfHandle *file)
  87. {
  88.     int         error;
  89.     rfHandle    hdl;
  90.  
  91.     /* allocate file structure */
  92.     if ( (error = memAlloc(sizeof(rfFile), (void**) &hdl)) != OK )
  93.         PASSERROR(ID_rfOpen)
  94.  
  95.     switch ( openMode )
  96.     {
  97.         case rfOpenRead:        /* open file for reading */
  98.             hdl->f = fopen(fileName, "rb");
  99.             break;
  100.  
  101.         case rfOpenWrite:       /* open file for writing */
  102.             hdl->f = fopen(fileName, "wb");
  103.             break;
  104.  
  105.         case rfOpenReadWrite:   /* open file for reading and writing */
  106.             hdl->f = fopen(fileName, "r+b");
  107.             break;
  108.     }
  109.  
  110.     /* If an error occurred during opening file, return the error code
  111.        specified by errno: */
  112.     if ( hdl->f == NULL )
  113.     {
  114.         error = ErrorCode();
  115.         ERROR(error, ID_rfOpen);
  116.         return error;
  117.     }
  118.  
  119.     /* store file handle in *file: */
  120.     *file = hdl;
  121.  
  122.     return OK;
  123. }
  124.  
  125.  
  126.  
  127.  
  128. /****************************************************************************\
  129. *
  130. * Function:     int rfClose(rfHandle file);
  131. *
  132. * Description:  Closes a file opened with rfOpen().
  133. *
  134. * Input:        rfHandle file           handle of an open file
  135. *
  136. * Returns:      MIDAS error code
  137. *
  138. \****************************************************************************/
  139.  
  140. int CALLING rfClose(rfHandle file)
  141. {
  142.     int         error;
  143.  
  144.     /* close file: */
  145.     if ( fclose(file->f) != 0 )
  146.     {
  147.         /* error occurred - return error code specified by errno: */
  148.         error = ErrorCode();
  149.         ERROR(error, ID_rfClose);
  150.         return error;
  151.     }
  152.  
  153.     /* deallocate file structure: */
  154.     if ( (error = memFree(file)) != OK )
  155.         PASSERROR(ID_rfClose)
  156.  
  157.     return OK;
  158. }
  159.  
  160.  
  161.  
  162.  
  163. /****************************************************************************\
  164. *
  165. * Function:     int rfGetSize(rfHandle file, long *fileSize);
  166. *
  167. * Description:  Get the size of a file
  168. *
  169. * Input:        rfHandle file           handle of an open file
  170. *               ulong *fileSize         pointer to file size
  171. *
  172. * Returns:      MIDAS error code.
  173. *               File size is stored in *fileSize.
  174. *
  175. \****************************************************************************/
  176.  
  177. int CALLING rfGetSize(rfHandle file, long *fileSize)
  178. {
  179.     int         error;
  180.     long        fpos;
  181.  
  182.     /* store current file position: */
  183.     if ( (error = rfGetPosition(file, &fpos)) != OK )
  184.         PASSERROR(ID_rfGetSize)
  185.  
  186.     /* seek to end of file: */
  187.     if ( (error = rfSeek(file, 0, rfSeekEnd)) != OK )
  188.         PASSERROR(ID_rfGetSize)
  189.  
  190.     /* read file position to *filesize: */
  191.     if ( (error = rfGetPosition(file, fileSize)) != OK )
  192.         PASSERROR(ID_rfGetSize)
  193.  
  194.     /* return original file position: */
  195.     if ( (error = rfSeek(file, fpos, rfSeekAbsolute)) != OK )
  196.         PASSERROR(ID_rfGetSize)
  197.  
  198.     return OK;
  199. }
  200.  
  201.  
  202.  
  203.  
  204. /****************************************************************************\
  205. *
  206. * Function:     int rfRead(rfHandle file, void *buffer, ulong numBytes);
  207. *
  208. * Description:  Reads binary data from a file
  209. *
  210. * Input:        rfHandle file           file handle
  211. *               void *buffer            reading buffer
  212. *               ulong numBytes          number of bytes to read
  213. *
  214. * Returns:      MIDAS error code.
  215. *               Read data is stored in *buffer, which must be large enough
  216. *               for it.
  217. *
  218. \****************************************************************************/
  219.  
  220. int CALLING rfRead(rfHandle file, void *buffer, ulong numBytes)
  221. {
  222.     FILE        *f = file->f;
  223.     int         error;
  224.     ulong       readCount = numBytes;
  225.     size_t      readNow;
  226.     size_t      readOK;
  227.  
  228. #if sizeof(size_t) < 2
  229.     #error sizeof(size_t) is below 16 bits!
  230.  
  231. #elif sizeof(size_t) < 4
  232.     uchar huge  *rbuf;
  233.     /* Size of size_t is below 32 bits - data must be read at chunks of
  234.        49152 bytes (size_t is assumed to be unsigned) */
  235.     rbuf = (uchar huge*) buffer;
  236.  
  237.     while ( readCount > 0 )
  238.     {
  239.         if ( readCount > 49152 )
  240.         {
  241.             /* More than 49152 bytes left to read - read 49152 bytes and
  242.                advance buffer pointer */
  243.             if ( (readOK = fread(rbuf, 49152, 1, f)) != 1 )
  244.                 break;
  245.             readCount -= 49152;
  246.             rbuf += 49152;
  247.         }
  248.         else
  249.         {
  250.             /* 49152 or less bytes remaining - read them to *rbuf */
  251.             if ( (readOK = fread(rbuf, readCount, 1, f)) != 1 )
  252.                 break;
  253.             readCount = 0;
  254.         }
  255.     }
  256.  
  257. #else
  258.     /* Size of size_t is at least 32 bits - all data can be read at one
  259.        call to fread */
  260.     readOK = fread(buffer, numBytes, 1, f);
  261. #endif
  262.     if ( readOK != 1 )
  263.     {
  264.         /* Error occurred when reading file. Check if there is an error, and
  265.            if is, return an error code corresponding to errno: */
  266.         if ( ferror(f) )
  267.         {
  268.             error = ErrorCode();
  269.             ERROR(error, ID_rfRead);
  270.             return error;
  271.         }
  272.  
  273.         /* no error - check if end of file: */
  274.         if ( feof(f) )
  275.         {
  276.             ERROR(errEndOfFile, ID_rfRead);
  277.             return errEndOfFile;
  278.         }
  279.  
  280.         /* no error or end of file - return "Unable to read file" */
  281.         ERROR(errFileRead, ID_rfRead);
  282.         return errFileRead;
  283.     }
  284.  
  285.     return OK;
  286. }
  287.  
  288.  
  289.  
  290.  
  291. /****************************************************************************\
  292. *
  293. * Function:     int rfWrite(rfHandle file, void *buffer, ulong numBytes);
  294. *
  295. * Description:  Writes binary data to a file
  296. *
  297. * Input:        rfHandle file           file handle
  298. *               void *buffer            pointer to data to be written
  299. *               ulong numBytes          number of bytes to write
  300. *
  301. * Returns:      MIDAS error code
  302. *
  303. \****************************************************************************/
  304.  
  305. int CALLING rfWrite(rfHandle file, void *buffer, ulong numBytes)
  306. {
  307.     FILE        *f = file->f;
  308.     int         error;
  309.     ulong       writeCount = numBytes;
  310.     size_t      writeNow;
  311.     size_t      writeOK;
  312.  
  313. #if sizeof(size_t) < 2
  314.     #error sizeof(size_t) is below 16 bits!
  315.  
  316. #elif sizeof(size_t) < 4
  317.     uchar huge  *wbuf;
  318.     /* Size of size_t is below 32 bits - data must be written in chunks of
  319.        49152 bytes (size_t is assumed to be unsigned) */
  320.     wbuf = (uchar huge*) buffer;
  321.  
  322.     while ( writeCount > 0 )
  323.     {
  324.         if ( writeCount > 49152 )
  325.         {
  326.             /* More than 49152 bytes left to write - write 49152 bytes and
  327.                advance buffer pointer */
  328.             if ( (writeOK = fwrite(wbuf, 49152, 1, f)) != 1 )
  329.                 break;
  330.             writeCount -= 49152;
  331.             wbuf += 49152;
  332.         }
  333.         else
  334.         {
  335.             /* 49152 or less bytes remaining - write all */
  336.             if ( (writeOK = fwrite(wbuf, writeCount, 1, f)) != 1 )
  337.                 break;
  338.             writeCount = 0;
  339.         }
  340.     }
  341.  
  342. #else
  343.     /* Size of size_t is at least 32 bits - all data can be written at one
  344.        call to fwrite */
  345.     writeOK = fwrite(buffer, numBytes, 1, f);
  346. #endif
  347.     if ( writeOK != 1 )
  348.     {
  349.         /* Error occurred when writing file. Check if there is an error, and
  350.            if is, return an error code corresponding to errno: */
  351.         if ( ferror(f) )
  352.         {
  353.             error = ErrorCode();
  354.             ERROR(error, ID_rfWrite);
  355.             return error;
  356.         }
  357.  
  358.         /* no error - return "Unable to write file" */
  359.         ERROR(errFileWrite, ID_rfWrite);
  360.         return errFileWrite;
  361.     }
  362.  
  363.     return OK;
  364. }
  365.  
  366.  
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373. /****************************************************************************\
  374. *
  375. * Function:     int rfSeek(rfHandle file, long newPosition, int seekMode);
  376. *
  377. * Description:  Seeks to a new position in file. Subsequent reads and writes
  378. *               go to the new position.
  379. *
  380. * Input:        rfHandle file           file handle
  381. *               long newPosition        new file position
  382. *               int seekMode            file seek mode, see enum rfSeekMode
  383. *
  384. * Returns:      MIDAS error code
  385. *
  386. \****************************************************************************/
  387.  
  388. int CALLING rfSeek(rfHandle file, long newPosition, int seekMode)
  389. {
  390.     FILE        *f = file->f;
  391.     int         error;
  392.     int         fseekMode;
  393.  
  394.     /* select seek mode for fseek() corresponding to seekMode: */
  395.     switch ( seekMode )
  396.     {
  397.         case rfSeekAbsolute:            /* seek to an absolute offset */
  398.             fseekMode = SEEK_SET;
  399.             break;
  400.  
  401.         case rfSeekRelative:            /* seek relative to current */
  402.             fseekMode = SEEK_CUR;       /* position */
  403.             break;
  404.  
  405.         case rfSeekEnd:
  406.             fseekMode = SEEK_END;       /* seek from end of file */
  407.             break;
  408.  
  409.         default:
  410.             /* invalid seek mode: */
  411.             ERROR(errInvalidArguments, ID_rfSeek);
  412.             return errInvalidArguments;
  413.     }
  414.  
  415.     /* seek to new position: */
  416.     if ( fseek(f, newPosition, fseekMode) != 0 )
  417.     {
  418.         /* Error during seeking.  Check if there is an error, and if is,
  419.            return an error code corresponding to errno: */
  420.         if ( ferror(f) )
  421.         {
  422.             error = ErrorCode();
  423.             ERROR(error, ID_rfSeek);
  424.             return error;
  425.         }
  426.  
  427.         /* no error - return "Unable to read file" */
  428.         ERROR(errFileRead, ID_rfSeek);
  429.         return errFileRead;
  430.     }
  431.  
  432.     return OK;
  433. }
  434.  
  435.  
  436.  
  437.  
  438. /****************************************************************************\
  439. *
  440. * Function:     int rfGetPosition(rfHandle file, long *position);
  441. *
  442. * Description:  Reads the current position in a file
  443. *
  444. * Input:        rfHandle file           file handle
  445. *               long *position          pointer to file position
  446. *
  447. * Returns:      MIDAS error code.
  448. *               Current file position is stored in *position.
  449. *
  450. \****************************************************************************/
  451.  
  452. int CALLING rfGetPosition(rfHandle file, long *position)
  453. {
  454.     FILE        *f = file->f;
  455.     int         error;
  456.     long        fpos;
  457.  
  458.     /* get current position to fpos: */
  459.     if ( (fpos = ftell(f)) == -1L )
  460.     {
  461.         /* Error - if errno is nonzero, return error code corresponding
  462.            to it. Otherwise return undefined error. */
  463.         if ( errno )
  464.         {
  465.             error = ErrorCode();
  466.             ERROR(error, ID_rfGetPosition);
  467.             return error;
  468.         }
  469.         else
  470.         {
  471.             ERROR(errUndefined, ID_rfGetPosition);
  472.             return errUndefined;
  473.         }
  474.     }
  475.  
  476.     *position = fpos;                   /* store position in *position */
  477.  
  478.     return OK;
  479. }
  480.