Previous | Table of Contents | Next

Note that not all MS-DOS compilers will define the manifest constant MSDOS. If your compiler doesn’t, you may need to edit the source files for CARMAN.C.

    void MassageMSDOSFileName( count, file )
    int count;
    char *file;
    {
     int i;
     char *p;

     FileList[ count ] = malloc( strlen( file ) + 2 );
     if ( FileList[ count ] == NULL )
      FatalError( "Ran out of memory storing file names" );
     strcpy( FileList[ count ], file );
     for ( i = 0 ; FileList[ count ][ i ] != '\0' ; i++ )
      FileList[ count ][ i ] = tolower( FileList[ count ][ i ] );
     if ( strpbrk( FileList[ count ], "*?" ) == NULL ) }
       p = strrchr( FileList[ count ], '\\' );
       if ( p == NULL )
         p = FileList[ count ];
       if ( strrchr( p, '.' ) == NULL )
            strcat( FileList[ count ], "." );
      }
     }

    int ExpandAndMassageMSDOSFileNames( count, wild_name )
    int count;
    char *wild_name;
    {
     int done;
     DIR_STRUCT file_info_block
     char *leading_path;
     char *file_name;

     char *p;

     leading_path = malloc( strlen( wild_name ) + 1 );
     file_name = malloc( strlen(wild_name ) + 13 );
     if ( leading_path == NULL || file_name == NULL )
      FatalError( "Ran out of memory storing file names" );
     strcpy( leading_path, wild_name );
        p = strrchr( leading_path, '\\' );
     if ( p != NULL )
        p[ 1 ] = '\0';
     else {
       p = strrchr( leading_path, ':' );
      if ( p != NULL )
        p[ 1 ] = '\0';
      else
        leading_path[ 0 ] = '\0';
     }
     done = FIND_FIRST( wild_name, &file_info_block, 0);
     while ( !done ) {
      strcpy( file_name, leading_path );
      strcat( file_name, file_info_block, DIR_FILE_NAME );
      MassageMSDOSFileName( count++, file_name );
      done = FINDNEXT( &file_info_block );
      if ( count > 99 )
       FatalError( "Too many file names" );
     }
     free( leading_path );
     free( file_name );
     return( count );
    }

The code shown here for expanding wild cards words with most popular MS-DOS compilers. Conditional complication is used to define the macros in slightly different ways depending on which compiler is being used. Check the complete listing at the end of this chapter for details on how this is accomplished.

#### Opening the Archive Files

The final step before you can begin processing the CAR file is opening the input and output CAR files. This routine is complicated by several possible conditions. In general, a routine that modifies the archive will have both an input and an output CAR file. This includes the ‘Add,’ ‘Replace,’ and ‘Delete’ commands. These commands operate by reading in and processing the CAR file while copying files to the output file.

The remaining processing commands don’t actually modify the input CAR file, so they don’t have to open an OutputFile. In addition, if the command is to ‘Add’ files to the archive, an input file may not exist, in which case a new one has to be created. The OpenArchiveFiles() command manages all these possibilities.

    void OpenArchiveFiles( name, command )
    char *name;
    int command;
    {
     char *s;
     int i;

     strncpy( CarFileName, name, FILENAME_MAX - 1 );
     CarFileName[ FILENAME_MAX - 1 ] = '\0';
     InputCarFile = fopen( CarFileName, "rb" );
     if ( InputCarFile == NULL ) {
    #ifdef MSDOS
        s = strrchr( CarFileName, '\\' );
    #else /* UNIX */
        s = strrchr( CarFileName, '/' );
    #endif
        if ( s == NULL )
         s = CarFileName;
        if ( strrchr( s, '.' ) == NULL )
         if ( strlen( CarFileName ) < ( FILENAME_MAX - 4 ) ) {
          strcat( CarFileName, ".car");
          InputCarFile = fopen( CarFileName, "rb" );
         }
     }
     if ( InputCarFile == NULL && command != 'A' )
      FatalError( "Can't open archive '%s'", CarFileName );
     if ( command == 'A' || command == 'R' || command == 'D' ) {
      strcpy( TempFileName, CarFileName );
      s = strrchr( TempFileName, '.' );
      if ( s == NULL )
       s = TempFileName + strlen( TempFileName );
      for ( i = 0 ; i < 10 ; i++ ) {
       sprintf( s, ".$$%d", i );
       if ( ( OutputCarFile = fopen( TempFileName, "r" ) ) == NULL )
        break;
       fclose( OutputCarFile );
       OutputCarFile = NULL;
       }
       if ( i == 10 )
        FatalError( "Can't open temporary file %s", TempFileName );
       OutputCarFile = fopen( TempFileName, "wb" );
       if ( OutputCarFile == NULL )
        FatalError( "Can't open temporary file %s", TempFileName );
     };
     if ( InputCarFile != NULL )
      setvbuf( InputCarFile, NULL, _IOFBF, 8192 );
     if ( OutputCarFile != NULL )
      setvbuf( OutputCarFile, NULL, _IOFBF, 8192 );
    }

When an output file is created, it will be the file that eventually gets a copy of all the selected files from the input archive. Once all that processing is over, the input file can be deleted and the output file can be renamed to have the correct name. However, while CARMAN is still processing, the output file has to have a different name. In this case, we create a temporary file name based on the name of the CAR file. We do a limited amount of checking to try and create a name that isn’t already in use.

One additional feature that CARMAN develops in this routine is the ability to automatically attempt to add a file extension to the archive name. If the input file name does not include an extension, OpenArchiveFiles() first tries to open it normally. If the file cannot be opened, OpenArchiveFiles() tries again with the “.CAR” extension appended to the file name. This lets the user type a command like “CARMAN L FILES” when the correct command might really be “CARMAN L FILES.CAR”.

Finally, note that both files have big buffers set up using the setvbuf() command. This helps throughput, particularly when performing bulk copies of compressed files from the input archive to the output CAR file.

Previous | Table of Contents | Next