home *** CD-ROM | disk | FTP | other *** search
/ PC to Maximum / PC-na-maximum.bin / DriveSpeed / SRC / DRSP / GETSINFO.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-04  |  14.6 KB  |  550 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. #include "D:\TC\UTILS\USER\USER.H"
  18.  
  19.  
  20. void ScanDrv(void){
  21.     char *Path = "A:\\*.*";
  22.     char Label[12] ={'\0'};
  23.     struct ffblk Block;         //struct used in file searching
  24.     char Drive;
  25.     unsigned int ax_, bx_, cx_, dx_, x;
  26.     Bool turn = True;
  27.  
  28.     //Table header
  29.     printf("\n\nThe following drives are available:\n\n"
  30.            "#│   Label   │    Free   │    Total   ││#│   Label   │    Free   │    Total   \n"
  31.            "─┼───────────┼───────────┼────────────┼┼─┼───────────┼───────────┼────────────\n"
  32.     );
  33.  
  34.     //Build a table of available drives.
  35.     for(char i = 1; i < 26; i++){
  36.         if(DriveIsOK(i)){
  37.             //Get drive Size
  38.             asm{
  39.                 mov AH, 0x36
  40.                 mov DL, i
  41.                 int 0x21
  42.                 mov ax_, AX
  43.                 mov bx_, BX
  44.                 mov cx_, CX
  45.                 mov dx_, DX
  46.             }
  47.  
  48.             if(ax_ != 0xFFFF){
  49.                 turn = !turn;
  50.                 Drive = i+64;
  51.  
  52.                 Path[0] = Drive;
  53.                 x = findfirst(Path, &Block, FA_LABEL); //Read volume label
  54.  
  55.                 if(x != 0)
  56.                     strcpy(Label, " (Unknown) \0");
  57.                 else{
  58.                     for(char a = 0, b = 0; a <= 13; a++, b++){
  59.                         if(Block.ff_name[a] == '.') a++;
  60.                         Label[b] = Block.ff_name[a];
  61.                     }
  62.                 }
  63.  
  64.                 printf("%c│%11s│%11li│%12li", Drive, Label, long(ax_)*long(cx_)*long(bx_), long(ax_)*long(cx_)*long(dx_));
  65.  
  66.                 //Fill both sides of the table in turn
  67.                 if(turn)
  68.                     printf("\n");
  69.                 else
  70.                     printf("││");
  71.  
  72.             }
  73.         }
  74.     }
  75. }
  76.  
  77.  
  78.  
  79. char GetDrive(void){
  80.     char Drive;
  81.     Bool Error;
  82.  
  83.     do{
  84.         Error = False;
  85.         Drive = Ask("\n\nType a drive letter for the drive you want to test. (Esc to quit): ") - 64;
  86.  
  87.         //Does a specified drive exist?
  88.         if(!DriveIsOK(Drive)){
  89.             Error = True;
  90.             printf("\nDrive not found! Please retry, or press Esc to abort.");
  91.         }
  92.     }while (Error);
  93.  
  94.     return Drive + 64;
  95. }
  96.  
  97.  
  98. unsigned long GetTestSize(TestData *TD){
  99.     char sSize[7], dl_ = TD->Drive - 64;
  100.     unsigned long DrvSize, iSize;
  101.     unsigned int ax_, bx_, cx_;
  102.     float fSize, MaxSize;
  103.     GetTxt *Txt = new GetTxt;
  104.  
  105.     //Get amount free
  106.     asm{
  107.         mov AH, 0x36
  108.         mov DL, dl_
  109.         int 0x21
  110.         mov ax_, AX
  111.         mov bx_, BX
  112.         mov cx_, CX
  113.     }
  114.  
  115.     DrvSize = long(ax_) * long(cx_) * long(bx_);
  116.  
  117.     //Check if the user passed test size in parameter line.
  118.     if(TD->TestSize == 0.0){
  119.         if(TD->Batch){
  120.             Abort(0, NULL, "\nNo test size selected!", EX_BAD_SIZE);
  121.         }else{
  122.             printf("\n\nPlease enter the amount of MB to test the drive with.\n"
  123.                    "The absolute minimum is 0.2, maximum is 999.99. The recommended minimum\n"
  124.                    "for floppies is 0.5, and for other media is 3. ('Esc' to quit.)"
  125.             );
  126.  
  127.             if(TD->RO != Off) printf("\n\nIn read-only mode the value means the upper boundary for size of a test\n"
  128.                                      "file, which the program will look for.");
  129.  
  130.             //Read the desired test size and convert to bytes
  131.             printf("\n-> ______\b\b\b\b\b\b");
  132.  
  133.             textcolor(10);
  134.             Txt->InText(sSize, 6, wherey(), wherex(), 7);
  135.             textcolor(7);
  136.  
  137.             fSize = atof(sSize);
  138.         }
  139.     }else
  140.         fSize = TD->TestSize;
  141.  
  142.     //Check if it is OK in case of read-write test
  143.     if(TD->RO == Off){
  144.         MaxSize = float(DrvSize - 1024) / (float)1048576;
  145.         if(fSize > 999.99)
  146.             fSize = 999.99;
  147.         else if (fSize > MaxSize)
  148.             fSize = MaxSize;
  149.     }
  150.  
  151.     if(fSize == 0.0) nexit(EX_ABORT);  //User wants to quit
  152.  
  153.     if(fSize < 0.2)
  154.         Abort(0, NULL, "\n\nTest size too small to give a reliable result!", EX_BAD_SIZE);
  155.  
  156.     iSize = (long)(fSize * 1048576L);
  157.     printf("\n%li bytes selected.", iSize);
  158.  
  159.     TD->TestSize = fSize;
  160.     delete Txt;
  161.     return iSize;
  162. }
  163.  
  164.  
  165. unsigned int GetTurns(void){
  166.     char sTurns[4];
  167.     unsigned int Turns;
  168.     GetTxt *Txt = new GetTxt;
  169.  
  170.     printf("\n\nPlease enter the number of turns this test will be performed.\n"
  171.            "The absolute minimum is 3, maximum is 999.  The recommended minimum\n"
  172.            "is 5. ('Esc' to quit.)"
  173.     );
  174.  
  175.     //Read the desired number of turns
  176.     printf("\n-> ___\b\b\b");
  177.  
  178.     textcolor(10);
  179.     Txt->InText(sTurns, 3, wherey(), wherex(), 4);
  180.     textcolor(7);
  181.  
  182.     Turns = atoi(sTurns);
  183.  
  184.     if(Turns == 0) nexit(EX_ABORT);  //User wants to quit
  185.  
  186.     //Check if it is OK and eventually correct
  187.     if(Turns < 3) Turns = 3;
  188.  
  189.     printf("\n%i turns selected.", Turns);
  190.     delete Txt;
  191.     return Turns;
  192.  
  193. }
  194.  
  195.  
  196. Bool DriveIsOK(char Drive){
  197.     char al_, CF;
  198.     unsigned int ax_, flags_;
  199.  
  200.     //Check if a drive is there (This function checks the co-relation between
  201.     //logical and physical drives. See DOS documentation for more info.)
  202.     asm{
  203.         mov AX, 0x440E  //DOS Fn 0x44, SubFn 0x0E
  204.         mov BL, Drive
  205.         int 0x21
  206.         mov ax_ , AX
  207.         mov al_, AL
  208.         pushf           //push Flags on stack
  209.         pop flags_      //read Flags
  210.     }
  211.  
  212.     //If Carry Flag != 1 no error occured;
  213.     CF = flags_ & 0x01;
  214.     //If logical drive is the same as physical drive or a logical drive has
  215.     //only one physical drive, it is safe to work with it.
  216.     //Another thing to check is when both Carry Flag set to 1 and AX register set to 1
  217.     //(indicating DOS error - Illigal function). This situation may occur, when Fn 0x44
  218.     //SubFn 0x0E is used on a RAM-Drive. It is NOT an error, the drive is accepted.
  219.     if( (!CF && ((al_ == Drive) || (al_ == 0))) || (CF && (ax_ == 1)) ){
  220.         //Check size, to see if any removable drive is inserted
  221.         asm{
  222.             mov AH, 0x36
  223.             mov DL, Drive
  224.             int 0x21
  225.             mov ax_, AX
  226.         }
  227.  
  228.         if(ax_ != 0xFFFF)
  229.             return True;
  230.         else
  231.             return False;
  232.     }else
  233.         return False;
  234.  
  235. }
  236.  
  237.  
  238.  
  239. char *FindPath(char *Path){
  240.     //The Path is used in the Analyse routine to write the log-file to the
  241.     //same directory, where the program is stored.
  242.  
  243.     register int i, j;
  244.     extern unsigned int _psp;
  245.  
  246.     //Set the char pointer to the beginning of the environment variable list by
  247.     //finding the relative address at offset 2cH of PSP (Program Segment Prefix)
  248.     //extern char **environ; would not do!
  249.     char far *Env = (char far*)MK_FP(*(int far*)MK_FP(_psp, 0x2C), 0);
  250.  
  251.     //Walk through the env. list until the formal end is reached (Program's
  252.     //start-up path and name are stored 4 bytes beyond the formal env. list.
  253.     //This feature is available from DOS 3.0)
  254.     for(i = 0; !((Env[i] == '\0') && (Env[i + 1] == '\0')); i++);
  255.     i += 4;
  256.  
  257.     //Read the start-up path and name
  258.     for(i = i, j = 0; Env[i] != '\0'; i++, j++)
  259.         Path[j] = Env[i];
  260.  
  261.     //Strip off the start-up name
  262.     for(j = j; ((Path[j] != '\\') && (j >= 0)); j--)
  263.         Path[j] = '\0';
  264.  
  265.     //Extra security check - better not to return any path at all, than an
  266.     //incorrect path.
  267.     if(Path[1] != ':') Path[0] = '\0';
  268.  
  269.     return Path;
  270. }
  271.  
  272.  
  273. //ScanPath designed for a multi-pass functionality. It finds the largest
  274. //file on a drive. The file will not be greater the the maxSize provided.
  275. unsigned long ScanPath(unsigned long maxSize, const char *Path, char **RetPath, unsigned long biggest){
  276.     struct ffblk ffblk;
  277.     Bool done;
  278.  
  279.     //The following variable are declared as static to make things faster.
  280.     static signed int i;
  281.     static unsigned long size;
  282.     static int cur1 = wherey(), Handle;
  283.     static Bool Esc = False;
  284.     static char buf[MAX_PATH];
  285.  
  286.     char *NewPath = (char *)malloc(sizeof(char) * strlen(Path) + 4);
  287.     if(NewPath == NULL) Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
  288.  
  289.     strcpy(NewPath, Path);
  290.     strcat(NewPath, "*.*");
  291.  
  292.     //Get first file in dir
  293.     done = findfirst(NewPath, &ffblk, 0x37); //All files - Volume
  294.  
  295.     while(!done && !Esc){
  296.  
  297.         size = ffblk.ff_fsize;
  298.  
  299.         //Dive into a sub-dir    /Directory
  300.         if((ffblk.ff_attrib & 0x10) && (ffblk.ff_name[0] != '.')){
  301.             NewPath = (char *)realloc(NewPath, strlen(Path) + strlen(ffblk.ff_name) + 2);
  302.             if(NewPath == NULL) Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
  303.  
  304.             strcpy(NewPath, Path);
  305.             strcat(NewPath, ffblk.ff_name);
  306.             strcat(NewPath, "\\");
  307.  
  308.             biggest = ScanPath(maxSize, NewPath, RetPath, biggest);
  309.         }
  310.  
  311.         //Register largest files in a directory if it is accessable.
  312.         if((size > biggest) && (size <= maxSize) && (ffblk.ff_name[0] != '.')){
  313.             sprintf(buf,"%s%s", Path, ffblk.ff_name);
  314.             Handle = open(buf, O_BINARY, S_IREAD);
  315.             if(Handle != -1){
  316.                 close(Handle);
  317.                 biggest = size;
  318.                 *RetPath = (char *)realloc(*RetPath, strlen(Path) + strlen(ffblk.ff_name) + 1);
  319.                 if(RetPath == NULL) Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
  320.  
  321.                 strcpy(*RetPath, buf); //buf is initialized in file access test
  322.  
  323.                 gotoxy(1, cur1);
  324.                 printf("Largest file found so far:\n%s", *RetPath);
  325.                 for(i = 1; i < MAX_PATH - strlen(*RetPath); i++) printf(" ");
  326.                 printf("%ld bytes selected.", biggest);
  327.             }
  328.         }
  329.  
  330.         done = findnext(&ffblk);
  331.  
  332.         //Test if any key is pressed and if it was an Esc. Using BIOS calls
  333.         //is about 5 times faster than kbhit() + getch() combination.
  334.         if(_bios_keybrd(_NKEYBRD_READY)){
  335.             if(_bios_keybrd(_NKEYBRD_READ) == 0x011B) //
  336.                 Esc = True;
  337.         }
  338.     }
  339.  
  340.     nfree(NewPath);
  341.     return biggest;
  342. }
  343.  
  344. //ScanPath designed for a single-pass functionality. It generates a
  345. //collection of the 10 largest files on a drive.
  346. unsigned long ScanPath(unsigned long maxSize, const char *Path, TestFile TF[]){
  347.     struct ffblk ffblk;
  348.     Bool done, changed = False;
  349.     register char i;
  350.  
  351.     //The following variable are declared as static to make things faster.
  352.     static signed int j, tmp;
  353.     static unsigned long size;
  354.     static int cur1 = wherey(), Handle;
  355.     static Bool Esc = False;
  356.     static unsigned long totSize = 0; //Total amount in the array
  357.     static char buf[MAX_PATH];
  358.  
  359.     char *NewPath = (char *)malloc(sizeof(char) * strlen(Path) + 4);
  360.     if(NewPath == NULL)
  361.         Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
  362.  
  363.     strcpy(NewPath, Path);
  364.     strcat(NewPath, "*.*");
  365.  
  366.     //Get first file in dir
  367.     done = findfirst(NewPath, &ffblk, 0x37); //All files - Volume
  368.  
  369.     while(!done && !Esc){
  370.  
  371.         size = ffblk.ff_fsize;
  372.  
  373.         //Dive into a sub-dir    /Directory
  374.         if((ffblk.ff_attrib & 0x10) && (ffblk.ff_name[0] != '.')){
  375.             NewPath = (char *)realloc(NewPath, strlen(Path) + strlen(ffblk.ff_name) + 2);
  376.             if(NewPath == NULL)
  377.                 Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
  378.  
  379.             strcpy(NewPath, Path);
  380.             strcat(NewPath, ffblk.ff_name);
  381.             strcat(NewPath, "\\");
  382.  
  383.             ScanPath(maxSize, NewPath, TF);
  384.         }
  385.  
  386.  
  387.         //If the total amount is not yet reached, try to fit the new
  388.         //file into the array so that the total size increases.
  389.         if((totSize < maxSize) && (size <= maxSize) && (ffblk.ff_name[0] != '.')){
  390.             //Check if the new file will fit at all.
  391.             i = MAX_FBUF - 1;
  392.             if(size > TF[i].Size){
  393.                 //Find the optimal location to replace with the new file.
  394.                 while(i >= 0){
  395.                     if((size > TF[i].Size) && (((totSize - TF[i].Size) + size) <= maxSize)) break;
  396.                     i--;
  397.                 }
  398.  
  399.                 //If i == -1 the the new candidate was too big
  400.                 //Otherwise, copy it in.
  401.                 if(i >= 0){
  402.                     //See if the new file can be read first.
  403.                     sprintf(buf,"%s%s", Path, ffblk.ff_name);
  404.                     Handle = open(buf, O_BINARY, S_IREAD);
  405.                     if(Handle != -1){
  406.                         close(Handle);
  407.  
  408.                         totSize = (totSize - TF[i].Size) + size;
  409.  
  410.                         //From that position shift the items down until the right
  411.                         //placce for the new item is reached (sort).
  412.                         while((i > 0) && (TF[i - 1].Size < size)){
  413.                             TF[i] = TF[i - 1];
  414.                             i--;
  415.                         }
  416.  
  417.                         strcpy(TF[i].Path, buf); //buf is initialized in file access test
  418.                         TF[i].Size = size;
  419.                         changed = True;
  420.                     }
  421.                 }
  422.             }
  423.  
  424.  
  425.             //Make a current status printout
  426.             if(changed){
  427.                 changed = False;
  428.                 gotoxy(1, cur1);
  429.                 for(i = 0; (i < MAX_FBUF) && (TF[i].Size != 0); i++){
  430.                     //Avoid printouts that are longer than the line of 80 chars
  431.                     tmp = strlen(TF[i].Path);
  432.                     if(tmp > 67){
  433.                         for(j = 0; j < 3; j++)
  434.                             buf[j] = TF[i].Path[j];
  435.                         buf[j] ='\0';
  436.  
  437.                         strcat(buf, "...");
  438.                         strcat(buf, (TF[i].Path + (tmp - 61)));
  439.                     }else
  440.                         strcpy(buf, TF[i].Path);
  441.  
  442.                     printf("%10ld:  %s", TF[i].Size, buf);
  443.                     tmp = 67 - strlen(buf);
  444.                     for(j = 0; j < tmp; j++) printf(" ");
  445.                 }
  446.                 printf("==========                \n"
  447.                        "%10ld bytes selected.", totSize);
  448.             }
  449.  
  450.         }// end if(totSize...
  451.  
  452.         done = findnext(&ffblk);
  453.  
  454.         //Test if any key is pressed and if it was an Esc. Using BIOS calls
  455.         //is about 5 times faster than kbhit() + getch() combination.
  456.         if(_bios_keybrd(_NKEYBRD_READY)){
  457.             if(_bios_keybrd(_NKEYBRD_READ) == 0x011B) //
  458.                 Esc = True;
  459.         }
  460.     }
  461.  
  462.     nfree(NewPath);
  463.     return totSize;
  464. }
  465.  
  466.  
  467. //Work with read-only mode
  468. Ro_mode SetRO(TestData TD){
  469.     int Handle;
  470.     Ro_mode RO = TD.RO;
  471.     char buf[] = FILE_NAME;
  472.     buf[0] = TD.Drive;
  473.  
  474.     if(RO == Off){ //Make some tests
  475.         if((Handle = open(buf, O_CREAT | O_TRUNC | O_BINARY, S_IWRITE)) == -1){
  476.             //Can't open test-file for writing - suggest read-only mode
  477.             printf("\n\nUnable to write to drive! ");
  478.             if(TD.Batch){
  479.                 RO = Multi;
  480.             }else{
  481.                 if(Ask("Run in read-only mode? (Y/N) ") == 'Y'){
  482.                     if(Ask("\n  Use a single- or a multipass mode? (S/M) ") == 'S')
  483.                         RO = Single;
  484.                     else
  485.                         RO = Multi;
  486.                 }else{
  487.                     printf("\n");
  488.                     nexit(EX_WRITE_ERR);
  489.                 }
  490.             }
  491.  
  492.         }else{
  493.             //Could write to the drive and the user
  494.             //didn't choose RO-mode from the COMMAND-line:
  495.             //do a RW test.
  496.             if(close(Handle) == -1)    nexit(EX_CLOSE_ERR);
  497.             if(unlink(buf) == -1) nexit(EX_DEL_ERR);
  498.         }
  499.     }else
  500.         printf("\n");
  501.  
  502.     if(RO != Off)
  503.         printf("Read-only %s-pass mode selected.", (RO == Single) ? "single" : "multi");
  504.  
  505.     return RO;
  506.  
  507. }
  508.  
  509.  
  510. //The function that starts the RO file search process
  511. char *SearchRO(TestData *TD, TestFile TF[]){
  512.     int i;
  513.     char *Path = (char *)malloc(MAX_PATH);
  514.     char *RetPath = (char *)malloc(MAX_PATH);
  515.  
  516.     if((Path == NULL) || (Path == NULL))
  517.         Abort(0, NULL, "Out of memory in SearchRO().", EX_NO_MEM);
  518.  
  519.     strcpy(Path, "C:\\");
  520.     Path[0] = TD->Drive;
  521.  
  522.  
  523.     printf("\n\nLooking for files to perform the test on ('Esc' to accept current value) ");
  524.     textcolor(128 + 7);
  525.     cprintf(". . .");
  526.     textcolor(7);
  527.     //Free MAX_BUF lines, where the results of the scan can be printed.
  528.     for(i = 0; i < MAX_FBUF + 3; i++)
  529.         printf("\n");
  530.  
  531.     gotoxy(1, wherey() - (MAX_FBUF + 2));
  532.  
  533.     _setcursortype(_NOCURSOR);
  534.     if(TD->RO == Multi)
  535.         TD->Size = ScanPath(TD->Size, Path, &RetPath, 0);
  536.     else
  537.         TD->Size = ScanPath(TD->Size, Path, TF);
  538.  
  539.     TD->TestSize = (float)(TD->Size) / 1048576.0;
  540.  
  541.     if(TD->TestSize < 0.2){
  542.         fprintf(stderr, "\n\nTest size too small to give a reliable result! Aborting.\n");
  543.         nexit(EX_BAD_SIZE);
  544.     }
  545.     _setcursortype(_NORMALCURSOR);
  546.  
  547.     nfree(Path);
  548.  
  549.     return RetPath;
  550. }