home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Languages / Masm V6.11 / SAMPLES / DEMOS / FILEDEMO.C$ / FILEDEMO
Encoding:
Text File  |  1992-11-12  |  18.3 KB  |  501 lines

  1. /* FILEDEMO.C - Performs various file operations using DOS functions.
  2.  * FILEDEMO demonstrates how to interface C and assembly procedures,
  3.  * which in turn demonstrate various assembly-language instructions,
  4.  * DOS calls, and BIOS interrupts.
  5.  *
  6.  * FILEDEMO.EXE is built from the following files:
  7.  *    FILEDEMO.C - Main program
  8.  *    FILE.ASM   - Assembly procedures for FILEDEMO
  9.  *    COMMON.ASM - Assembly procedures shared by other example programs
  10.  *    DEMO.INC   - Assembly include file with macros and structure declarations
  11.  *    DEMO.H     - C include file with prototypes and structure declarations
  12.  *
  13.  * Procedures:  ClearBox             ChangeDrive          GetDiskSize
  14.  *              GetVidConfig         GetVer               GetCurDir
  15.  *              GetCurDrive          CopyFile             DelFile
  16.  *              MakeDir              RemoveDir            ChangeDir
  17.  *              GetAttribute         SetAttribute         RenameFile
  18.  *              GetFileTime          FindFirst            FindNext
  19.  *              UniqueFile           OpenFile             CloseFile
  20.  *              ReadFile             SetCurPos            StrCompare
  21.  *              StrFindChar          ReadCharAttr
  22.  */
  23.  
  24. #include "demo.h"
  25. #include <string.h>
  26. #include <conio.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <malloc.h>
  30.  
  31. /* Function prototypes */
  32. char *get_spec( int n );
  33. int list_dir( char *spec, int disp_attr );
  34. void press( void );
  35.  
  36. /* Constants */
  37. #define MAXSEARCH 80
  38. #define MAXSPEC   64
  39. #define BUFFSIZE  31 * 1024
  40.  
  41. /* Global variables */
  42. struct FILEINFO file;            /* Structure for FindFirst info */
  43. char source[64];                 /* Buffer for source file/path  */
  44.  
  45. main()
  46. {
  47.     static char text[MAXSEARCH];  /* Pointer to buffer for search text  */
  48.     static char date_time[19];    /* Receive file date and time         */
  49.     int err, mode, handle, len;   /* Codes, file handle, bytes read     */
  50.     int row, col, ch;             /* Cursor coordinates, kb character   */
  51.     int i, j, attr;               /* Index variables, file attribute    */
  52.     int disp_attr;                /* Display attribute                  */
  53.     char *spec, *ptr, *buffer;    /* File spec, char match, read buffer */
  54.     long dsize, disk_use;         /* Disk size and usage                */
  55.     struct DISKSTAT disk;         /* Structure for disk size params     */
  56.  
  57.     static char copy_msg[] =
  58.     {
  59.         "Files can be copied or moved in 2 different modes:\n" \
  60.         "      0  -  overwrite target file if it exists\n" \
  61.         "      1  -  abort if target file exists\n\n" \
  62.         "Mode 1 is supported only with DOS versions 3.0 or higher.\n"
  63.     };
  64.     static char move_msg[] =
  65.     {
  66.         "Quick Move uses DOS function 56h (Rename File) to effectively " \
  67.         "move a file from\none directory to another directory on the " \
  68.         "same drive.  It copies the entry\nfrom the source directory to " \
  69.         "the target directory, but does not physically\ncopy the file.\n\n" \
  70.         "Source and target specifications must be given in full, " \
  71.         "including filenames,\neven if the names are the same."
  72.     };
  73.     static char grep_msg[] =
  74.     {
  75.         "The Find Text option uses the StrFindChar and StrCompare procedures " \
  76.         "to locate\na text string within specified files, like Unix's " \
  77.         "\"grep\" command.  Find Text\nis limited to case-sensitive searches " \
  78.         "within the current directory.\n\nEnter the desired search string " \
  79.         "without quotation marks.  When specifying the\nfilename, use " \
  80.         "wildcard characters to expand the search to a group of files --\n" \
  81.         "for example, \"*.*\" searches all files within the current " \
  82.         "directory, \"*.bat\"\nlimits the search to batch files, and so forth."
  83.     };
  84.     static char attr_msg[] =
  85.     {
  86.         "\t\t\t1    normal      \n" \
  87.         "\t\t\t2    read-only   \n" \
  88.         "\t\t\t3    hidden      \n" \
  89.         "\t\t\t4    system      \n" \
  90.         "\t\t\t     volume      \n" \
  91.         "\t\t\t     subdirectory\n" \
  92.         "\t\t\t5    archive     \n"
  93.     };
  94.  
  95.     GetVidConfig();
  96.     ReadCharAttr( &disp_attr );
  97.     clear_scrn( disp_attr, 0, 24 );
  98.     SetCurPos( 8, 0 );
  99.     puts( "Welcome to the FILEDEMO program.\n\n\nThis program is meant " \
  100.           "to encourage experimentation while demonstrating how to\naccess " \
  101.           "DOS from assembly-language procedures.  As a safety precaution, " \
  102.           "however,\nwe suggest you DO NOT experiment with files that " \
  103.           "cannot easily be replaced." );
  104.     press();
  105.  
  106.     do
  107.     {
  108.         /* Display current drive and directory */
  109.         clear_scrn( disp_attr, 0, 24 );
  110.         SetCurPos( 0, 0 );
  111.         printf( "Current Directory:  %c:\\", (char)(GetCurDrive() + 'A') );
  112.         GetCurDir( source );
  113.         puts( source );
  114.  
  115.         /* Display DOS version */
  116.         SetCurPos( 1, 0 );
  117.         printf( "DOS Version:        %2.1f", ( (float) GetVer() ) / 100 );
  118.  
  119.         /* Display disk statistics for current drive */
  120.         SetCurPos( 0, 58 );
  121.         GetDiskSize( 0, &disk );
  122.         dsize = (long)disk.bytes * disk.sects * disk.total;
  123.         disk_use = (long)(disk.total - disk.avail) * disk.bytes * disk.sects;
  124.         printf( "Disk Size: %6lu K", dsize / 1024 );
  125.         SetCurPos( 1, 58 );
  126.         printf( "Disk Use:  %6lu K", disk_use / 1024 );
  127.  
  128.         /* Display menu and poll for keystroke */
  129.         clear_scrn( disp_attr, 2, 23 );
  130.         SetCurPos( 5, 0 );
  131.         puts( " \t               ***      FILE " \
  132.               "Demonstration Program      ***" );
  133.         SetCurPos( 7, 0 );
  134.         puts( " \tA  List Directory       \t\tH  Get/Set File Attribute" );
  135.         puts( " \tB  Copy File            \t\tI  Get File Date and Time" );
  136.         puts( " \tC  Move File            \t\tJ  Rename File" );
  137.         puts( " \tD  Make Subdirectory    \t\tK  Delete File" );
  138.         puts( " \tE  Remove Subdirectory  \t\tL  Create Unique File" );
  139.         puts( " \tF  Change Default Drive \t\tM  Quick Move" );
  140.         puts( " \tG  Change Directory     \t\tN  Find Text" );
  141.         printf( "\n\n\tSelect an option, or press ESC to quit: " );
  142.         ch = getch();
  143.         switch( (ch = toupper( ch )) )
  144.         {
  145.             /* List first 60 files in specified directory */
  146.             case 'A':
  147.                 err  = list_dir( get_spec( 1 ), disp_attr );
  148.                 if( !err )
  149.                     press();
  150.                 break;
  151.  
  152.             /* Copy or Move File according to requested mode:
  153.              *          0 = overwrite target
  154.              *          1 = abort if target exists
  155.              * If Move requested, delete source file after copy.
  156.              */
  157.             case 'B':
  158.             case 'C':
  159.                 clear_scrn( disp_attr, 2, 17 );
  160.                 SetCurPos( 9, 0 );
  161.                 puts( copy_msg );
  162.                 mode = -1;
  163.                 while( (mode < 0)  ||  (mode > 1) )
  164.                 {
  165.                     SetCurPos( 16, 0 );
  166.                     printf( "Enter copy mode:  " );
  167.                     mode = (int)(getche() - '0');
  168.                 }
  169.                 spec = get_spec( 2 );                   /* Get source     */
  170.                 strcpy( source, spec );                 /* Save in buffer */
  171.                 spec = get_spec( 3 );                   /* Get target     */
  172.                 err  = CopyFile( mode, source, spec );
  173.                 if( (ch == 'C')  &&  !err )
  174.                     err = DelFile( source );
  175.                 break;
  176.  
  177.             /* Make Directory */
  178.             case 'D':
  179.                 err = MakeDir( get_spec( 1 ) );
  180.                 break;
  181.  
  182.             /* Remove Directory */
  183.             case 'E':
  184.                 err = RemoveDir( get_spec( 1 ) );
  185.                 break;
  186.  
  187.             /* Change Default Drive */
  188.             case 'F':
  189.                 SetCurPos( 18, 0 );
  190.                 printf( "Enter new drive letter:  " );
  191.                 ch = getch();
  192.                 ch = toupper( ch );
  193.                 ChangeDrive( ch );
  194.                 err = 0;
  195.                 break;
  196.  
  197.             /* Change Directory */
  198.             case 'G':
  199.                 err = ChangeDir( get_spec( 1 ) );
  200.                 break;
  201.  
  202.             /* Get and Set File Attributes */
  203.             case 'H':
  204.                 strcpy( source, get_spec( 3 ) );
  205.                 if( (err = GetAttribute( source )) != -1 )
  206.                 {
  207.                     attr = err;
  208.                     if( !attr )
  209.                         attr_msg[6] = '*';
  210.                     else
  211.                         attr_msg[6] = ' ';
  212.                     for( j = 1, i = 27; j <= 32; j <<= 1, i+= 21 )
  213.                     {
  214.                         attr_msg[i] = ' ';
  215.                         if( attr & j )
  216.                             attr_msg[i] = '*';
  217.                     }
  218.                     err = 0;
  219.                     clear_scrn( disp_attr, 2, 17 );
  220.                     SetCurPos( 7, 0 );
  221.                     puts( attr_msg );
  222.                     printf( "\n\nToggle attribute bits by selecting 1-5, " \
  223.                             "or any other key to exit:  " );
  224.                     mode = (int)( getch() - '0' );
  225.                     if( (mode > 0)  &&  (mode < 6) )
  226.                     {
  227.                         switch( --mode )
  228.                         {
  229.                             case 0:
  230.                                 attr = 0;
  231.                                 break;
  232.  
  233.                             case 1:
  234.                             case 2:
  235.                             case 3:
  236.                                 attr = attr ^ (1 << (--mode) );
  237.                                 break;
  238.  
  239.                             case 4:
  240.                                 attr = attr ^ 32;
  241.                         }
  242.                         err = SetAttribute( attr, source );
  243.                     }
  244.                 }
  245.                 break;
  246.  
  247.             /* Get File Date and Time */
  248.             case 'I':
  249.                 if( (handle = OpenFile( 0, get_spec( 3 ) )) == -1 )
  250.                     err = 1;
  251.                 else
  252.                     err = 0;
  253.                 if( !err )
  254.                 {
  255.                     if( !(err = GetFileTime( handle, date_time )) )
  256.                     {
  257.                         clear_scrn( disp_attr, 2, 17 );
  258.                         SetCurPos( 12, 10 );
  259.                         printf( "File's date and time stamp:  %s", date_time );
  260.                         CloseFile( handle );
  261.                         press();
  262.                     }
  263.                 }
  264.                 break;
  265.  
  266.             /* Rename File */
  267.             case 'J':
  268.                 strcpy( source, get_spec( 2 ) );
  269.                 err = RenameFile( source, get_spec( 3 ) );
  270.                 break;
  271.  
  272.             /* Delete File */
  273.             case 'K':
  274.                 err = DelFile( get_spec( 3 ) );
  275.                 break;
  276.  
  277.             /* Create File with Unique Name */
  278.             case 'L':
  279.                 strcpy( source, get_spec( 1 ) );
  280.                 handle = UniqueFile( 0, source );   /* Normal file attr = 0 */
  281.                 if( handle >= 0 )
  282.                 {
  283.                     printf( "\n\nDOS creates file %s", source );
  284.                     press();
  285.                     err = 0;
  286.                 }
  287.                 else err = 1;
  288.                 break;
  289.  
  290.             /* Quick Move from one directory to another */
  291.             case 'M':
  292.                 clear_scrn( disp_attr, 2, 17 );
  293.                 SetCurPos( 8, 0 );
  294.                 puts( move_msg );
  295.                 strcpy( source, get_spec( 2 ) );
  296.                 err = RenameFile( source, get_spec( 3 ) );
  297.                 break;
  298.  
  299.             /* Search files for specified text */
  300.             case 'N':
  301.                 clear_scrn( disp_attr, 2, 17 );
  302.                 buffer = (char *) malloc( BUFFSIZE + 1 );
  303.                 if( buffer == NULL )
  304.                 {
  305.                     SetCurPos( 12, 26 );
  306.                     puts( "Insufficient memory for option" );
  307.                     err = 1;
  308.                     break;
  309.                 }
  310.                 SetCurPos( 7, 0 );
  311.                 puts( grep_msg );
  312.                 SetCurPos( 18, 0 );
  313.                 printf( "Enter search text:  " );
  314.                 GetStr( text, MAXSEARCH );
  315.  
  316.                 /* Find first data file. */
  317.                 if( err = FindFirst( 0, get_spec( 3 ), &file ) )
  318.                 {
  319.                     clear_scrn( disp_attr, 2, 17 );
  320.                     SetCurPos( 12, 24 );
  321.                     puts( "No files found matching specification" );
  322.                 }
  323.  
  324.                 /* If file found, initialize screen coordinates and
  325.                  * open file for reading.
  326.                  */
  327.                 else
  328.                 {
  329.                     clear_scrn( disp_attr, 2, 17 );
  330.                     row = 6;
  331.                     col = 0;
  332.                     do
  333.                     {
  334.                         if( (handle = OpenFile( 0, file.filename )) != -1 )
  335.                         {
  336.  
  337.                             /* If file opened successfully, read a block
  338.                              * of BUFFSIZE bytes. If end-of-file encountered
  339.                              * (number of bytes read not equal to BUFFSIZE)
  340.                              * or read error, set error flag to break loop.
  341.                              * Terminate block with a NULL character to 
  342.                              * make it an ASCIIZ string.
  343.                              */
  344.                             err = 0;
  345.                             while( !err )
  346.                             {
  347.                                 len = ReadFile( handle, BUFFSIZE, buffer );
  348.                                 if( (len == 0)  ||  (len != BUFFSIZE) )
  349.                                     ++err;
  350.                                 ptr = buffer;
  351.                                 *( ptr + len ) = 0;
  352.  
  353.                                 /* Search block for first character in text */
  354.                                 while( spec = StrFindChar( text[0], ptr, 0 ) )
  355.                                 {
  356.  
  357.                                     /* If initial character found, compare
  358.                                      * remaining characters in search text.
  359.                                      * If all characters match, display file
  360.                                      * name and break out of loop.
  361.                                      */
  362.                                     ptr = StrCompare( ++spec, &text[1],
  363.                                           (strlen( text ) - 1) );
  364.                                     if( !ptr )
  365.                                     {
  366.                                         SetCurPos( row++, col );
  367.                                         puts( file.filename );
  368.                                         if( row == 16)
  369.                                         {
  370.                                             row  = 6;
  371.                                             col += 20;
  372.                                         }
  373.                                         err  = 1;
  374.                                         break;
  375.                                     }
  376.                                 }
  377.                             }
  378.                             CloseFile( handle );
  379.                         }
  380.                         else
  381.                         {
  382.                             err = 1;
  383.                             break;
  384.                         }
  385.                     } while( !FindNext( &file ) );
  386.  
  387.                     if( (row == 6)  &&  (col == 0) )
  388.                     {
  389.                         SetCurPos( 12, 22 );
  390.                         puts( "Text not found in specified file(s)" );
  391.                     }
  392.                     press();
  393.                     err = 0;
  394.                 }
  395.                 free( buffer );             /* Free allocated block */
  396.                 break;
  397.  
  398.             default:
  399.                 continue;
  400.         }
  401.  
  402.         if( err )
  403.         {
  404.             clear_scrn( disp_attr, 24, 24 );
  405.             SetCurPos( 24, 0 );
  406.             printf( "***  Error  ***\a" );
  407.             press();
  408.         }
  409.  
  410.     } while( ch != ESCAPE );            /* Exit if ESC key pressed    */
  411.  
  412.     clear_scrn( disp_attr, 0, 24 );     /* Clear screen before exit   */
  413.     SetCurPos( 23, 0 );                 /*   and set cursor to bottom */
  414.     return( 0 );
  415. }
  416.  
  417.  
  418. /* get_spec - Prompts for file or path specifications.
  419.  *
  420.  * Params:  n - Prompt number
  421.  *
  422.  * Return:  Pointer to specification
  423.  */
  424.  
  425. char *get_spec( int n )
  426. {
  427.     static char spec[MAXSPEC];
  428.  
  429.     switch( n )
  430.     {
  431.         case 1:
  432.             SetCurPos( 18, 0 );
  433.             printf( "Enter path:  " );
  434.             break;
  435.         case 2:
  436.             SetCurPos( 18, 0 );
  437.             printf( "Enter source file:  " );
  438.             break;
  439.         case 3:
  440.             SetCurPos( 20, 0 );
  441.             printf( "Enter target file:  " );
  442.             break;
  443.     }
  444.     GetStr( spec, MAXSPEC );
  445.     if ( *spec == '\0' && n == 1 )
  446.     {
  447.         strcpy ( spec, "\\" );      /* Use current directory for <return> */
  448.         strcat ( spec, source );
  449.     }
  450.     return spec;
  451. }
  452.  
  453.  
  454. /* list_dir - Lists specified directory by invoking DOS Function 4Eh (Find
  455.  * First Matching Entry), then DOS Function 4Fh (Find Next Matching Entry).
  456.  *
  457.  * Params:  spec - Pointer to path specification
  458.  * 
  459.  * Return:  err  - Error code returned from FindFirst procedure:
  460.  *                 0 = successful         1 = error
  461.  */
  462.  
  463. int list_dir( char *spec, int disp_attr )
  464. {
  465.     int row, col;
  466.     int err, end;
  467.     clear_scrn( disp_attr, 2, 23 );
  468.  
  469.     if ( spec[strlen(spec) - 1] == '\\' )       /*Remove trailing backslash*/
  470.          spec[strlen(spec) - 1] = '\0';
  471.     strcat( spec, "\\*.*" );
  472.     err = FindFirst( 16, spec, &file ); /* Find directories, normal files */
  473.     if( !err )
  474.     {
  475.         for( end = 0, col = 0; (col < 80)  &&  (end == 0); col += 22 )
  476.         {
  477.             for( row = 5; (row < 20)  &&  (end == 0); row++ )
  478.             {
  479.                 SetCurPos( row, col );
  480.                 puts( file.filename );
  481.                 end = FindNext( &file );
  482.             }
  483.         }
  484.     }
  485.     return err;
  486. }
  487.  
  488.  
  489. /* press - Prompt for keyboard signal to continue.
  490.  *
  491.  * Params:  None
  492.  */
  493.  
  494. void press( void )
  495. {
  496.     SetCurPos( 24, 49 );
  497.     printf( ". . . press a key to continue" );
  498.     SetCurPos( 24, 47 );
  499.     getch();
  500. }
  501.