home *** CD-ROM | disk | FTP | other *** search
/ PC to Maximum / PC-na-maximum.bin / DriveSpeed / SRC / DRSP / DRSP.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-04  |  7.6 KB  |  319 lines

  1. /*
  2.  *  DRSP - DriveSpeed, version 3.10 (GPL FREEWARE)
  3.  *  Copyleft (l) Stanislav Sokolov, May 1998 and onwards.
  4.  *
  5.  *  This program is subject to GNU General Public License ver. 2 of June 1991
  6.  *  and any later version.
  7.  *
  8.  *  You may use this source with your programs, provided
  9.  *  due credits are given.
  10.  *
  11.  *  Contact the author by e-mail: stanislavs@hotmail.com
  12.  *
  13.  *  Internet:  http://members.tripod.com/~stanislavs/prog/prog.htm
  14.  */
  15.  
  16. #include "D:\TC\MY\DRSP\DRSP.H"
  17.  
  18.  
  19. int HError = 0;
  20. Bool fError = False;
  21.  
  22. //Local global variable used by DRSPCC
  23. Bool FromCC = False;
  24. extern char **environ;
  25.  
  26. int main(int argc, char *argv[]){
  27.     TestData TD;
  28.     float WriteSpd = 0.0, ReadSpd = 0.0;
  29.     unsigned int i;
  30.     TestFile TF[MAX_FBUF];
  31.     char *RetPath = NULL; //Will be allocated in SearchRO()
  32.  
  33.     //Init TF
  34.     for(i = 0; i < MAX_FBUF; i++)
  35.         TF[i].Size = 0;
  36.  
  37.     //Display help if the user enters /?
  38.     if(!(strcmp(argv[1], "/?") && strcmp(argv[1], "-?")))
  39.         Info(True);
  40.     else
  41.         Info(False);
  42.  
  43.  
  44.     //Install a do-nothing Ctrl-Break routine.
  45.     FindLong f;
  46.     f.Whole = (long)Brk;
  47.     asm{
  48.         push DS
  49.         mov  AH, 0x25
  50.         mov  AL, 0x23
  51.         mov  DS, word ptr [f.Part.High]
  52.         mov  DX, word ptr [f.Part.Low]
  53.         int  0x21
  54.         pop  DS
  55.     }
  56.  
  57.  
  58.     //Install a hardware-error handler routine.
  59.     harderr(FatalHandler);
  60.  
  61.     //Parse the program arguements
  62.     TD = ParseArg(argc, argv);
  63.  
  64.     //Get the test parameters, if they are not (correctly) given in the
  65.     //COMMAND-line. Note that the batch-mode is reset to false in this case.
  66.  
  67.     //Work with the drive letter
  68.     if((TD.Drive == '\0') && TD.Batch)
  69.         Abort(0, NULL, "\nNo drive selected!", EX_BAD_DRV);
  70.  
  71.     if((TD.Drive == '\0') && Ask("\nScan for available drives? (Y/N) ") == 'Y')
  72.         ScanDrv();
  73.  
  74.     if((TD.Drive == '\0') || !DriveIsOK(TD.Drive - 64)){
  75.         if(TD.Batch)
  76.             Abort(0, NULL, "\nWrong drive selected!", EX_BAD_DRV);
  77.         TD.Drive = GetDrive();
  78.     }else
  79.         printf("Drive %c: selected.", TD.Drive);
  80.  
  81.     //Test if RO-mode should be used
  82.     TD.RO = SetRO(TD);
  83.  
  84.     //Ajust or get the testsize
  85.     TD.Size = GetTestSize(&TD);
  86.  
  87.     //Prepare Read-Only test.
  88.     if(TD.RO != Off)
  89.         RetPath = SearchRO(&TD, TF);
  90.  
  91.     //Get the number of turns
  92.     if(((TD.Turns < 3) || (TD.Turns > 999)) && (TD.RO != Single)){
  93.         if(TD.Batch)
  94.             Abort(0, NULL, "\nWrong number of turns selected!", EX_BAD_TURN);
  95.         TD.Turns = GetTurns();
  96.     }else if(TD.RO != Single)
  97.         printf("\n%i turns selected.", TD.Turns);
  98.  
  99.     //Perform the test & display results
  100.     if(TD.RO == Off){
  101.         DoTest(TD, &ReadSpd, &WriteSpd);
  102.         Analyze(TD, WriteSpd, ReadSpd, TestFAS(TD.Drive));
  103.     }else{
  104.         if(TD.RO == Multi)
  105.             ReadSpd = DoTest(RetPath, TD);
  106.         else{
  107.             ReadSpd = DoTest(TF, TD.Size);
  108.             TD.Turns = 1; //Set to one to mark a single-pass test
  109.         }
  110.  
  111.         Analyze(TD, ReadSpd);
  112.     }
  113.  
  114.     nfree(RetPath);
  115.     nfree(TD.LogFile);
  116.  
  117.     //Make a "meep" when the program is done.
  118.     sound(45);
  119.     delay(110);
  120.     nosound();
  121.  
  122.     nexit(EX_OK);
  123.     return EX_OK;
  124. }
  125.  
  126.  
  127. TestData ParseArg(int argc, char *argv[]){
  128.     //Example of legal arguments  DRSP c: /t3 /s3.4
  129.     //Means test drive c: with 3.4MB test-file over 3 turns
  130.     //DRSP c: /R /t4 /s9
  131.     //Perform read-only test of drive c: 4 times, while finding a file, which
  132.     //is not larger than 9MB
  133.     //
  134.     //Additional arguments from ver. 3.00 are:
  135.     // /rs - read-only single-pass mode; /rm - read-only multi-pass mode;
  136.     // /b - batch mode.
  137.     //Additional argument from ver. 3.10 is:
  138.     // /l - specifies the log-file name and path to use.
  139.  
  140.     TestData TD;
  141.  
  142.     //Initialize test data.
  143.     memset(&TD, 0, sizeof(TestData));
  144.  
  145.     for(int i = 1; i < argc; i++){
  146.         switch (argv[i][1]){
  147.             case ':':
  148.                 TD.Drive = argv[i][0];
  149.                 if(TD.Drive >= 97) TD.Drive -= 32;
  150.                 break;
  151.  
  152.             case 't':
  153.             case 'T':
  154.                 TD.Turns = atoi(&argv[i][2]);
  155.                 break;
  156.  
  157.             case 's':
  158.             case 'S':
  159.                 TD.TestSize = atof(&argv[i][2]);
  160.                 break;
  161.  
  162.             case 'r':
  163.             case 'R':
  164.                 if((argv[i][2] == 's') || (argv[i][2] == 'S'))
  165.                     TD.RO = Single;
  166.                 else if((argv[i][2] == 'm') || (argv[i][2] == 'M'))
  167.                     TD.RO = Multi;
  168.                 break;
  169.  
  170.             case 'b':
  171.             case 'B':
  172.                 TD.Batch = True;
  173.                 break;
  174.  
  175.             case 'l':
  176.             case 'L':
  177.                 TD.LogFile = strdup(&argv[i][2]);
  178.                 break;
  179.  
  180.             case 'f':     //Undocumented - used by the front-end DRSPCC
  181.             case 'F':
  182.                 FromCC = True;
  183.                 break;
  184.  
  185.         }
  186.  
  187.     }// end for()
  188.  
  189.     return TD;
  190. }
  191.  
  192.  
  193. //General prompt routine
  194. char Ask(const char *Prompt){
  195.     printf("%s", Prompt);
  196.  
  197.     while (!kbhit());
  198.     textcolor(10);
  199.     char Resp = getche();
  200.     textcolor(7);
  201.  
  202.     if((Resp >= 97) && (Resp <= 122)) Resp -= 32;
  203.  
  204.     if(Resp == 27) nexit(EX_ABORT);  //User wants to quit
  205.  
  206.     return Resp;
  207. }
  208.  
  209.  
  210.  
  211. void Abort(int Handle, const char *FName, const char *Msg, int status){
  212.     _setcursortype(_NORMALCURSOR);
  213.     textcolor(12);
  214.     cprintf("\r%s\r", Msg);
  215.     textcolor(7);
  216.     printf("\n\n\n");
  217.     if(Handle != 0) close(Handle);
  218.     if(FName != NULL) unlink(FName);
  219.  
  220.     nexit(status);
  221. }
  222.  
  223.  
  224.  
  225. //General info
  226. void Info(Bool Help){
  227.     printf("\nDriveSpeed, version 3.10 (GPL FREEWARE)\n"
  228.            "Copyleft (l) Stanislav Sokolov, May 1998 and onwards.\n\n"
  229.     );
  230.  
  231.     if(Help){
  232.         printf("DriveSpeed uses the most common sequential write and read operations performed\n"
  233.                "via DOS functions 3fH and 40H. It also tests File Access Speed. The program can\n"
  234.                "test any drive.\n\n"
  235.  
  236.                "The program will check which drives are available, ask for which drive to test,\n"
  237.                "the size of the test file, and how many times it should repeat the test. At the\n"
  238.                "end of the test you will be prompted to store the results in a log-file. Read-\n"
  239.                "only drives can be tested with one of the two read-only modes.\n\n"
  240.  
  241.                "DriveSpeed accepts COMMAND-line parameters:\tDRSP C: /S3.5 /T5,\n"
  242.                "which means: test drive C: with a 3.5MB test-file, repeating the test 5 turns.\n"
  243.                "Invalid pameters will be re-prompted from within the program. For more\n"
  244.                "information see README.TXT\n\n"
  245.  
  246.                "If you find this program useful, send me an (e-)postcard telling so:\n"
  247.  
  248.                "\tStanislav Sokolov,\tE-mail:\n"
  249.                "\tSnorresvei 24,\t\t stanislavs@hotmail.com\n"
  250.                "\t1473 SKÅRER,\t\tInternet:\n"
  251.                "\tNorway\t\t\t http://members.tripod.com/~stanislavs/\n"
  252.         );
  253.  
  254.         nexit(EX_OK);
  255.  
  256.     }
  257.  
  258.     if((_osmajor < 4)/* || ((_osmajor == 4) && (_osminor < 0))*/){
  259.         textcolor(12);
  260.         cprintf("The program will only run under DOS version 4.0 or higher.\n");
  261.         textcolor(7);
  262.         nexit(EX_OLD_DOS);
  263.     }
  264.  
  265.  
  266.     printf("This program will test a conventional speed of a selected drive\n"
  267.            "by performing a series of DOS I/O operations.\n\n"
  268.     );
  269. }
  270.  
  271.  
  272. void ClearCache(void){
  273.     //Crear SMARTDRV's cache (and hopefully Windows xxxx')
  274.     asm{
  275.         mov AX, 0x4A10
  276.         mov BX, 0x0001 //Commit
  277.         int 0x2F
  278.         mov AX, 0x4A10
  279.         mov BX, 0x0002 //Clear
  280.         int 0x2F
  281.     }
  282. }
  283.  
  284.  
  285. //Works according to UNIX specification - NULL pointer is ignored!
  286. void nfree(void *ptr){
  287.     if(ptr == NULL) return;
  288.     free(ptr);
  289. }
  290.  
  291. //A special version of exit() that prints the status to a file that is used
  292. //by the Windows front-end. Windows is seemingly unable to pass the return
  293. //status to the caller, so I had to employ this work-around.
  294. void nexit(int status){
  295.     FILE *Res;
  296.     char resPath[MAX_PATH];
  297.     char *tmp;
  298.  
  299.     if(FromCC){
  300.         //Try to put the res-file to a path in either TEMP, TMP or root.
  301.         tmp = getenv("TEMP");
  302.         if(tmp == NULL) tmp = getenv("TMP");
  303.         if(tmp == NULL) tmp = "C:\\";
  304.  
  305.         strcpy(resPath, tmp);
  306.         if(resPath[strlen(resPath) - 1] != '\\')
  307.             strcat(resPath, "\\");
  308.         strcat(resPath, "@DRSPRES.TMP");
  309.  
  310.         if((Res = fopen(resPath, "w+t")) != NULL){
  311.             fprintf(Res, "%d", status);
  312.             fclose(Res);
  313.         }
  314.     }
  315.  
  316.     _setcursortype(_NORMALCURSOR);
  317.  
  318.     exit(status);
  319. }