home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_02_11 / 2n11023a < prev    next >
Text File  |  1991-09-13  |  7KB  |  248 lines

  1. /* ----------------------------------------------------
  2.  *  LISTING 3
  3.  *
  4.  *  Filename:           bfile.c
  5.  *  Summary:            extended file i/o interface
  6.  *  Author:             T.W. Nelson
  7.  *  Compile options:    
  8.  *  Version:            1.00
  9.  *  Date:               12-Sep-1991
  10.  *  Notes:
  11.  *
  12.  *  Source code Copyright (c) 1991 T.W. Nelson. May be
  13.  *  used only for non-commercial purposes with
  14.  *  appropriate acknowledgement of copyright.
  15.  * ------------------------------------------------- */
  16.  
  17. #include <stdio.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20. #include <sys\stat.h>
  21. #include <alloc.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <assert.h>
  25. #include "bfile.h"
  26.  
  27. //Utility function prototypes (in dos.c) .......
  28. void move_mem( bufp_t *dest, bufp_t *src,
  29.                                      size_t nbytes );
  30. int read_file(  int fd, bufp_t *buf, size_t nbytes );
  31. int write_file( int fd, bufp_t *buf, size_t nbytes );
  32.  
  33. /* ------------------------------------------------- */
  34. static void fproc(idnt_t *idnt,     //cache id
  35.                   ulong bnum,       //block number
  36.                   bufp_t *p)        //-> cache buffer
  37. {
  38.    /* Free block processing (writing) routine. Called
  39.     * when cache buffer space must be reused for a new
  40.     * block.  'idnt' was set up by open_b() as a
  41.     * pointer to a BFILE object for the file. If the
  42.     * file was not pre-existent, one will be created
  43.     * here when (and if) the data overflows the cache.
  44.     */
  45.  
  46.     BFILE *ff = (BFILE *) idnt;
  47.  
  48.     if( ff->fd == -1 )  {    //file doesn't exist ....
  49.         if((ff->fd = open(ff->fname,O_CREAT+O_BINARY,
  50.                          S_IREAD+S_IWRITE)) == -1)
  51.                 return;         //error
  52.     }
  53.  
  54.     lseek( ff->fd, (long) (bnum * ff->cac.bsiz),
  55.                                         SEEK_SET );
  56.     write_file( ff->fd, p, ff->cac.bsiz );
  57. }
  58.  
  59. BFILE *open_b( const char *path,    //file pathname
  60.                int bmax,            //#blocks in cache
  61.                int bsize,           //blocksize, bytes
  62.                int mode   )         //caching mode
  63. {
  64.    /* Open a block-cached file. Pathname is saved in
  65.     * the BFILE descriptor; the file need not be pre-
  66.     * existent. Cache id is set up as a pointer to the
  67.     * malloced BFILE object. Returns pointer to BFILE
  68.     * object or null if we're out of memory.
  69.     */
  70.  
  71.     BFILE *ff;
  72.  
  73.     if( (ff = (BFILE *) malloc( sizeof(BFILE) ))
  74.                                    == (BFILE *) 0 ) {
  75.             errno = ENOMEM;
  76.             return (BFILE *) 0;
  77.     }
  78.  
  79.     assert( strlen(path) < MAXPATHNAME );
  80.     strcpy( ff->fname, path );
  81.     ff->fd = -1;
  82.     ff->mode = mode;
  83.  
  84.     #ifdef COMPILE_EMM
  85.     if( emm_check() == 0 )
  86.             bc_setalloc( emm_allocate );
  87.     #endif
  88.  
  89.     if( bc_open( &(ff->cac), bmax,
  90.         bsize, fproc, (idnt_t *) ff ) == BC_NOMEMORY) {
  91.             free( (void *) ff );
  92.             ff->mode = 0;
  93.             errno = ENOMEM;
  94.             return (BFILE *) 0;
  95.     }
  96.  
  97.     ff->mode |= IS_OPEN;
  98.     ff->fd = open( ff->fname, O_RDWR + O_BINARY );
  99.  
  100.     return ff;
  101. }
  102.  
  103. int read_b( BFILE *ff,          //-> BFILE descriptor
  104.             void *buf,          //destination buffer
  105.             ulong blockno )     //block# to read
  106. {
  107.    /* Read a block from a cached file. The cache is
  108.     * checked for the block; if found, it's copied
  109.     * directly to 'buf'.  Otherwise, the lfru block
  110.     * is re-used for the new block, to be read from
  111.     * disk.
  112.     */
  113.  
  114.     bufp_t *bufptr;
  115.  
  116.     if( !(ff->mode & IS_OPEN) )     {
  117.             errno = EBADF;
  118.             return -1;
  119.     }
  120.  
  121.     #ifdef COMPILE_EMM
  122.     emm_map_pages( &(ff->cac) );
  123.     #endif
  124.  
  125.     if( bc_search( &(ff->cac), blockno,
  126.                          &bufptr) == BC_NOTFOUND )  {
  127.         bc_addnew( &(ff->cac), blockno, &bufptr);
  128.  
  129.         //read block from file into cache ......
  130.         lseek( ff->fd, (long) (blockno *
  131.                            ff->cac.bsiz), SEEK_SET );
  132.         if( read_file( ff->fd, bufptr,
  133.                                ff->cac.bsiz ) == -1 )
  134.                 return -1;
  135.     }
  136.  
  137.     //move block from cache to application buffer ....
  138.     move_mem( (bufp_t *) buf, bufptr, ff->cac.bsiz );
  139.  
  140.     #ifdef COMPILE_EMM
  141.     emm_unmap_pages( &(ff->cac) );
  142.     #endif
  143.  
  144.     return 0;
  145. }
  146.  
  147. int write_b( BFILE *ff,         //-> BFILE descriptor
  148.              void *buf,         //source buffer
  149.              ulong blockno )    //block# to write
  150. {
  151.    /* Write a data block to a cached file. If using a
  152.     * write-through strategy, the block is written
  153.     * immediately to the file after copying to the
  154.     * cache. Otherwise, the block is marked for
  155.     * delayed processing.
  156.     */
  157.  
  158.     bufp_t *bufptr;
  159.  
  160.     if( !(ff->mode & IS_OPEN) )     {
  161.             errno = EBADF;
  162.             return -1;
  163.     }
  164.  
  165.     #ifdef COMPILE_EMM
  166.     emm_map_pages( &(ff->cac) );
  167.     #endif
  168.  
  169.     if( bc_search( &(ff->cac),
  170.             blockno, &bufptr) == BC_NOTFOUND )  {
  171.             bc_addnew( &(ff->cac), blockno, &bufptr);
  172.     }
  173.  
  174.     //move block from application buffer to cache ....
  175.     move_mem( bufptr, (bufp_t *) buf, ff->cac.bsiz );
  176.  
  177.     if( ff->mode & WRITE_THRU )
  178.             fproc( (idnt_t *) ff, blockno, bufptr );
  179.     else
  180.             bc_mark( &(ff->cac), blockno, MARK );
  181.  
  182.     #ifdef COMPILE_EMM
  183.     emm_unmap_pages( &(ff->cac) );
  184.     #endif
  185.  
  186.     return 0;
  187. }
  188.  
  189. int close_b( BFILE *ff )
  190. {
  191.        /* Close down a block-cached file, freeing
  192.         * all cache memory.  The file is not
  193.         * deleted.
  194.         */
  195.  
  196.         if( !(ff->mode & IS_OPEN) )     {
  197.                 errno = EBADF;
  198.                 return -1;
  199.         }
  200.  
  201.         #ifdef COMPILE_EMM
  202.         emm_map_pages( &(ff->cac) );
  203.         #endif
  204.  
  205.         bc_flush( &(ff->cac) );
  206.         close( ff->fd );
  207.         ff->mode &= ~IS_OPEN;
  208.  
  209.         #ifdef COMPILE_EMM
  210.         emm_unmap_pages( &(ff->cac) );
  211.         #endif
  212.  
  213.         bc_free( &(ff->cac) );
  214.         free( (void *) ff );
  215.  
  216.         return 0;
  217. }
  218.  
  219. int remove_b( BFILE *ff )
  220. {
  221.        /* Close and delete a cached file */
  222.  
  223.         if( !(ff->mode & IS_OPEN) )     {
  224.                 errno = EBADF;
  225.                 return -1;
  226.         }
  227.  
  228.         #ifdef COMPILE_EMM
  229.         emm_map_pages( &(ff->cac) );
  230.         #endif
  231.  
  232.         bc_flush( &(ff->cac) );
  233.         close( ff->fd );
  234.         remove( ff->fname );
  235.         ff->mode &= ~IS_OPEN;
  236.  
  237.         #ifdef COMPILE_EMM
  238.         emm_unmap_pages( &(ff->cac) );
  239.         #endif
  240.  
  241.         bc_free( &(ff->cac) );
  242.         free( (void *) ff );
  243.  
  244.         return 0;
  245. }
  246.  
  247. /* ---- End of File -------------------------------- */
  248.