Previous | Table of Contents | Next

### The Main Processing Loop

With these steps out of the way, CARMAN is ready to begin processing in earnest. The main processing loop is found in the routine called ProcessAllFilesInInputCar(). It sits in a big loop, finding files in the input CAR file, checking to see if they match up with any of the names in the file list, then deciding what to do based on the command.

Before entering the main processing loop, CARMAN checks to see if the command given was to ‘Add’ files to the CAR file. If it was, these files all need to be inserted into the output CAR file before anything else happens. This is done in a routine called AddFileListToArchive(). This routine attempts to add every file name that was specified in the command line to the output CAR file.

    int AddFileListToArchive
    ()
    {
     int i;
     int j;
     int skip;
     char *s;
     FILE *input_text_file;

     for ( i = 0 ; FileList[ i ] != NULL ; i++ ) {
      input_text_file = fopen( FileList[ i ], "rb" );
      if ( input_text_file == NULL )
       FatalError( "Could not open %s to add to CAR file",
                             FileList[ i ] );
    #ifdef MSDOS
        s = strrchr( FileList[ i ], '\\' );
        if ( s == NULL )
         s = strrchr( FileList[ i ], ':' );
    #endif
    #ifndef MSDOS /* Must be UNIX */
        s = strrchr( FileList[ i ], '/');
    #endif
        if ( s != NULL )
         s++;
        else
         s = FileList[ i ];
        skip = 0;
        for ( j = 0; j < i ; j++ )
         if ( strcmp( s, FileList[ j ] ) == 0 ) {
           fprintf( stderr, "Duplicate file name: %s", FileList[ i ] );
           fprintf( stderr, " Skipping this file...\n" );
           skip = 1;
           break;
          }
        if ( s != FileList[ i ] {
         for ( j = 0 ; s [ j ] != '\0' ; j++ )
          FileList[ i ][ j ] = s[ j ];
         FileList[ i ][ j ] = '\0';
        }
        if ( !skip ) {
          strcpy( Header.file_name, FileList[ i ];
          Insert( input_text_file, "Adding" );
        } else
          fclose( input_text_file );
       }
      return( i );
    }

Adding files to the archive has to take care of several things in order to accomplish its goal. First, it has to use the full path name specified on the command line to try to open the file to be added. Once the file is opened, however, the file name needs to be stripped of its path and drive component. CARMAN stores file names only, not leading drive or path definitions. Once the file name has been stripped down, a search is made to be sure that this is not a duplicate file name. Adding two files with the same name to a CARMAN file would be a bad idea. Finally, if everything went well, the Insert() routine is called to compress the file and place it in the output CAR file.

Once any new files have been added, CARMAN enters the main processing loop, where most of the real work takes place. The main processing loop is fairly simple in structure. It simply reads in file header from the input file, then checks to see if the file appears in the FileList, saving the answer. Next, it enters a switch, and then performs processing on the input file based on the command type. Each command makes a different decision on what to do based on whether or not the file name appeared in the file list.

Two commands used in the main processing loop require a small amount of setup. The ‘Test’ and ‘Print’ commands actually act just like the ‘Xtract’ command, except that they direct their output to the null device and stdout, respectively. These output destinations are set up before the loop is entered.

    int ProcessAllFilesInInputCar( command, count )
    int command;
    int count;
    {
     int matched;
     FILE *input_text_file;
     FILE *output_destination;

     if ( command == 'P' )
      output_destination = stdout;
     else if ( command == 'T' )
    #ifdef MSDOS
       output_destination = fopen( "NUL", "wb" );
    #else
       output_destination = fopen( "/dev/null", "wb" );
    #endif
     else
      output_destination = NULL;
    /*
    * This is the loop where it all happens. I read in the header for
    * each file in the input CAR, then see if it matches any of the file
    * and wild card specifications in the FileList created earlier. That
    * information, combined with the command, tells me what I need to
    * know in order to process the file. Note that if the 'Addfiles' command
    * is being executed, the InputCarFile will be NULL, so this loop
    * can be safety skipped.
    */
     while ( InputCarFile != NULL && ReadFileHeader() != 0 ) {
      matched = SearchFileList( Header.file_name );
      switch ( command ) {
       case 'D' :
        if ( matched ) {
         SkipOverFileFromInputCar();
         count++;
        } else
         CopyFileFromInputCar();
        break;
       case 'A' :
        if ( matched )
         SkipOverFileFromInputCar();
        else
         CopyFileFromInputCar();
        break;
       case 'L' :
        if ( matched ) {
         ListCarFileEntry();
         count++;
        }
        SkipOverFileFromInputCar();
        break;
       case 'P' :
       case 'X' :
       case 'T' :
        if ( matched ) {
         Extract( output_destination );
         count++;
        } else
         SkipOverFileFromInputCar();
        break;
       case 'R' :
        if ( matched ) {
         input_text_file = fopen( Header.file_name, "rb" );
         if ( input_text_file == NULL ) {
          fprintf( stderr, "Could not find %s", Header.file_name );
          fprintf( stderr, " for replacement, skipping\n" );
          CopyFileFromInputCar();
         } else {
          SkipOverFileFromInputCar();
          Insert( input_text_file, Replacing" );
          count++;
          fclose( input_text_file );
         }
        } else
         CopyFileFromInputCar();
        break;
       }
     }
     return( count );
    }

Previous | Table of Contents | Next