home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / fastfile / ffcreate.c < prev    next >
C/C++ Source or Header  |  1997-07-14  |  6KB  |  250 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation.  All Rights Reserved.
  4.  *
  5.  *  File:       ffcreate.c
  6.  *  Content:    Fast file I/O for large numbers of files.
  7.  *        Turns all files in a directory into a single file.
  8.  *        This single file contains a directory + all the files.
  9.  *
  10.  * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
  11.  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  12.  * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
  13.  *
  14.  ***************************************************************************/
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <ctype.h>
  20. #include <sys\types.h>
  21. #include <sys\stat.h>
  22. #include <fcntl.h>
  23. #include <io.h>
  24. #include <malloc.h>
  25.  
  26. #ifdef __WATCOMC__
  27. #define _open open
  28. #define _close close
  29. #define _lseek lseek
  30. #define _read read
  31. #define _write write
  32. #define _stricmp stricmp
  33. #define _S_IREAD S_IREAD
  34. #define _S_IWRITE S_IWRITE
  35. #endif
  36.  
  37. #include "ffent.h"
  38.  
  39. #define BLOCK_SIZE    16*1024
  40.  
  41. /*
  42.  * Compare
  43.  *
  44.  * quicksort comparison routine
  45.  */
  46. int Compare( const LPFILEENTRY p1, const LPFILEENTRY p2 )
  47. {
  48.     return( _stricmp( (p1)->name,(p2)->name ) );
  49. }
  50.  
  51. /*
  52.  * main
  53.  */
  54. main( int argc, char *argv[] )
  55. {
  56.     HANDLE        dir;
  57.     WIN32_FIND_DATA    fd;
  58.     int            out;
  59.     int            in;
  60.     unsigned long    cnt;
  61.     unsigned long    tmp;
  62.     LPFILEENTRY        pfe;
  63.     int            i;
  64.     int            bytes;
  65.     int            outbytes;
  66.     char        *buff;
  67.     char        *fname;
  68.     char        *dename;
  69.     long        pos;
  70.  
  71.     /*
  72.      * get i/o buffer
  73.      */
  74.     buff = malloc( BLOCK_SIZE );
  75.     if( buff == NULL ) {
  76.     printf( "Out of memory!\n" );
  77.     exit( 1 );
  78.     }
  79.  
  80.     /*
  81.      * get fastfile name, open file
  82.      */
  83.     if( argc < 2 ) {
  84.     fname = "\\result.ff";
  85.     } else {
  86.     fname = argv[1];
  87.     }
  88.     printf( "Creating FastFile \"%s\"\n", fname );
  89.     out = _open( fname, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY,
  90.             _S_IREAD | _S_IWRITE );
  91.     if( out < 0 ) {
  92.     printf( "Could not open file \"%s\"", fname );
  93.     exit( 1 );
  94.     }
  95.  
  96.     /*
  97.      * build a header
  98.      */
  99.     cnt = 0;
  100.     printf( "Pass 1: building header\n" );
  101.     dir = FindFirstFile( "*.*", &fd );
  102.     if( dir == NULL ) {
  103.     printf( "Could not open current directory\n" );
  104.     _close( out );
  105.     exit( 1 );
  106.     }
  107.     pfe = NULL;
  108.     while( 1 ) {
  109.     if( !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  110.         cnt++;
  111.         pfe = realloc( pfe, (cnt+1) * sizeof( FILEENTRY ) );
  112.         memset( &pfe[cnt-1], 0, sizeof( FILEENTRY )*2 );
  113.         if( pfe == NULL ) {
  114.         printf( "Out of memory!\n" );
  115.         _close( out );
  116.         exit( 1 );
  117.         }
  118.         dename = fd.cAlternateFileName;
  119.         if( dename[0] == 0 ) {
  120.         dename = fd.cFileName;
  121.         }
  122.         printf( "File %d: %s                 \r", cnt, dename );
  123.         pfe[cnt-1].offset = 0;
  124.         strcpy( pfe[cnt-1].name, dename );
  125.     }
  126.     if( !FindNextFile( dir, &fd ) ) {
  127.         break;
  128.     }
  129.     }
  130.     FindClose( dir );
  131.  
  132.     if( cnt == 0 ) {
  133.     printf( "No files found!\n" );
  134.     exit( 0 );
  135.     }
  136.  
  137.     /*
  138.      * sort the directory
  139.      */
  140.     qsort( pfe, cnt, sizeof( FILEENTRY ), (LPVOID) Compare );
  141.  
  142.     /*
  143.      * write the number of directory entries + the directory
  144.      */
  145.     tmp = cnt+1;
  146.     bytes = _write( out, &tmp, sizeof( tmp ) );
  147.     if( bytes != sizeof( tmp ) ) {
  148.     printf( "Error writing output file\n" );
  149.     _close( out );
  150.     exit( 1 );
  151.     }
  152.     bytes = _write( out, pfe, tmp * sizeof( FILEENTRY ) );
  153.     if( bytes != (int) (tmp * sizeof( FILEENTRY )) ) {
  154.     printf( "Error writing output file\n" );
  155.     _close( out );
  156.     exit( 1 );
  157.     }
  158.  
  159.     /*
  160.      * now read all of the files one by one and add them to the fastfile
  161.      */
  162.     printf( "Pass 2: adding data files                  \n" );
  163.     for( i=0;i<(int)cnt;i++ ) {
  164.     /*
  165.      * save current file position
  166.      */
  167.     pfe[i].offset = _lseek( out, 0, SEEK_CUR );
  168.     if( pfe[i].offset < 0 ) {
  169.         printf( "\nSeek error on output file\n" );
  170.         _close( out );
  171.         exit( 1 );
  172.     }
  173.  
  174.     /*
  175.      * open next file to add
  176.      */
  177.     in = _open( pfe[i].name, O_RDONLY | O_BINARY, 0 );
  178.     printf( "File %d: \"%s\", offset=%ld                          \r",
  179.                 i+1, pfe[i].name, pfe[i].offset );
  180.     if( in < 0 ) {
  181.         printf( "\nError opening file %s\n", pfe[i].name );
  182.         _close( out );
  183.         exit( 1 );
  184.     }
  185.  
  186.     /*
  187.      * copy the data in the file
  188.      */
  189.     while( 1 ) {
  190.         bytes = _read( in, buff, BLOCK_SIZE );
  191.         if( bytes == 0 ) {
  192.         break;
  193.         }
  194.         if( bytes < 0 ) {
  195.         printf( "\nError reading file %s\n", pfe[i].name );
  196.         _close( in );
  197.         _close( out );
  198.         exit( 1 );
  199.         }
  200.         outbytes = _write( out, buff, bytes );
  201.         if( bytes != outbytes ) {
  202.         printf( "\nError writing output file\n" );
  203.         _close( in );
  204.         _close( out );
  205.         exit( 1 );
  206.         }
  207.         if( bytes < BLOCK_SIZE ) {
  208.         break;
  209.         }
  210.     }
  211.     _close( in );
  212.     }
  213.  
  214.     /*
  215.      * get position of file end
  216.      */
  217.     pfe[i].offset = _lseek( out, 0, SEEK_CUR );
  218.  
  219.     /*
  220.      * seek to the start of the directory (right after the # of entries)
  221.      */
  222.     pos = _lseek( out, sizeof( tmp ), SEEK_SET );
  223.     if( pos != sizeof( tmp ) ) {
  224.     printf( "Seek error on output file\n" );
  225.     _close( out );
  226.     exit( 1 );
  227.     }
  228.  
  229.     /*
  230.      * re-write the directory with the offsets setup
  231.      */
  232.     bytes = _write( out, pfe, tmp * sizeof( FILEENTRY ) );
  233.     if( bytes != (int) (tmp * sizeof( FILEENTRY )) ) {
  234.     printf( "Error writing output file\n" );
  235.     _close( out );
  236.     exit( 1 );
  237.     }
  238.  
  239.     /*
  240.      * all done
  241.      */
  242.     printf( "FastFile \"%s\" created:                   \n", fname );
  243.     printf( "    %ld files\n", tmp );
  244.     printf( "    %ld total file size\n", pfe[i].offset );
  245.  
  246.     _close( out );
  247.     return 0;
  248.  
  249. } /* main */
  250.