home *** CD-ROM | disk | FTP | other *** search
- /*==========================================================================
- *
- * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
- *
- * File: ffcreate.c
- * Content: Fast file I/O for large numbers of files.
- * Turns all files in a directory into a single file.
- * This single file contains a directory + all the files.
- *
- * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
- * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
- * WARRANTIES OF MERCHANTBILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- ***************************************************************************/
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <fcntl.h>
- #include <io.h>
- #include <malloc.h>
-
- #ifdef __WATCOMC__
- #define _open open
- #define _close close
- #define _lseek lseek
- #define _read read
- #define _write write
- #define _stricmp stricmp
- #define _S_IREAD S_IREAD
- #define _S_IWRITE S_IWRITE
- #endif
-
- #include "ffent.h"
-
- #define BLOCK_SIZE 16*1024
-
- /*
- * Compare
- *
- * quicksort comparison routine
- */
- int Compare( const LPFILEENTRY p1, const LPFILEENTRY p2 )
- {
- return( _stricmp( (p1)->name,(p2)->name ) );
- }
-
- /*
- * main
- */
- main( int argc, char *argv[] )
- {
- HANDLE dir;
- WIN32_FIND_DATA fd;
- int out;
- int in;
- unsigned long cnt;
- unsigned long tmp;
- LPFILEENTRY pfe;
- int i;
- int bytes;
- int outbytes;
- char *buff;
- char *fname;
- char *dename;
- long pos;
-
- /*
- * get i/o buffer
- */
- buff = malloc( BLOCK_SIZE );
- if( buff == NULL ) {
- printf( "Out of memory!\n" );
- exit( 1 );
- }
-
- /*
- * get fastfile name, open file
- */
- if( argc < 2 ) {
- fname = "\\result.ff";
- } else {
- fname = argv[1];
- }
- printf( "Creating FastFile \"%s\"\n", fname );
- out = _open( fname, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY,
- _S_IREAD | _S_IWRITE );
- if( out < 0 ) {
- printf( "Could not open file \"%s\"", fname );
- exit( 1 );
- }
-
- /*
- * build a header
- */
- cnt = 0;
- printf( "Pass 1: building header\n" );
- dir = FindFirstFile( "*.*", &fd );
- if( dir == NULL ) {
- printf( "Could not open current directory\n" );
- _close( out );
- exit( 1 );
- }
- pfe = NULL;
- while( 1 ) {
- if( !(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
- cnt++;
- pfe = realloc( pfe, (cnt+1) * sizeof( FILEENTRY ) );
- memset( &pfe[cnt-1], 0, sizeof( FILEENTRY )*2 );
- if( pfe == NULL ) {
- printf( "Out of memory!\n" );
- _close( out );
- exit( 1 );
- }
- dename = fd.cAlternateFileName;
- if( dename[0] == 0 ) {
- dename = fd.cFileName;
- }
- printf( "File %d: %s \r", cnt, dename );
- pfe[cnt-1].offset = 0;
- strcpy( pfe[cnt-1].name, dename );
- }
- if( !FindNextFile( dir, &fd ) ) {
- break;
- }
- }
- FindClose( dir );
-
- if( cnt == 0 ) {
- printf( "No files found!\n" );
- exit( 0 );
- }
-
- /*
- * sort the directory
- */
- qsort( pfe, cnt, sizeof( FILEENTRY ), (LPVOID) Compare );
-
- /*
- * write the number of directory entries + the directory
- */
- tmp = cnt+1;
- bytes = _write( out, &tmp, sizeof( tmp ) );
- if( bytes != sizeof( tmp ) ) {
- printf( "Error writing output file\n" );
- _close( out );
- exit( 1 );
- }
- bytes = _write( out, pfe, tmp * sizeof( FILEENTRY ) );
- if( bytes != (int) (tmp * sizeof( FILEENTRY )) ) {
- printf( "Error writing output file\n" );
- _close( out );
- exit( 1 );
- }
-
- /*
- * now read all of the files one by one and add them to the fastfile
- */
- printf( "Pass 2: adding data files \n" );
- for( i=0;i<(int)cnt;i++ ) {
- /*
- * save current file position
- */
- pfe[i].offset = _lseek( out, 0, SEEK_CUR );
- if( pfe[i].offset < 0 ) {
- printf( "\nSeek error on output file\n" );
- _close( out );
- exit( 1 );
- }
-
- /*
- * open next file to add
- */
- in = _open( pfe[i].name, O_RDONLY | O_BINARY, 0 );
- printf( "File %d: \"%s\", offset=%ld \r",
- i+1, pfe[i].name, pfe[i].offset );
- if( in < 0 ) {
- printf( "\nError opening file %s\n", pfe[i].name );
- _close( out );
- exit( 1 );
- }
-
- /*
- * copy the data in the file
- */
- while( 1 ) {
- bytes = _read( in, buff, BLOCK_SIZE );
- if( bytes == 0 ) {
- break;
- }
- if( bytes < 0 ) {
- printf( "\nError reading file %s\n", pfe[i].name );
- _close( in );
- _close( out );
- exit( 1 );
- }
- outbytes = _write( out, buff, bytes );
- if( bytes != outbytes ) {
- printf( "\nError writing output file\n" );
- _close( in );
- _close( out );
- exit( 1 );
- }
- if( bytes < BLOCK_SIZE ) {
- break;
- }
- }
- _close( in );
- }
-
- /*
- * get position of file end
- */
- pfe[i].offset = _lseek( out, 0, SEEK_CUR );
-
- /*
- * seek to the start of the directory (right after the # of entries)
- */
- pos = _lseek( out, sizeof( tmp ), SEEK_SET );
- if( pos != sizeof( tmp ) ) {
- printf( "Seek error on output file\n" );
- _close( out );
- exit( 1 );
- }
-
- /*
- * re-write the directory with the offsets setup
- */
- bytes = _write( out, pfe, tmp * sizeof( FILEENTRY ) );
- if( bytes != (int) (tmp * sizeof( FILEENTRY )) ) {
- printf( "Error writing output file\n" );
- _close( out );
- exit( 1 );
- }
-
- /*
- * all done
- */
- printf( "FastFile \"%s\" created: \n", fname );
- printf( " %ld files\n", tmp );
- printf( " %ld total file size\n", pfe[i].offset );
-
- _close( out );
- return 0;
-
- } /* main */
-