home *** CD-ROM | disk | FTP | other *** search
- /*
- * DRSP - DriveSpeed, version 3.10 (GPL FREEWARE)
- * Copyleft (l) Stanislav Sokolov, May 1998 and onwards.
- *
- * This program is subject to GNU General Public License ver. 2 of June 1991
- * and any later version.
- *
- * You may use this source with your programs, provided
- * due credits are given.
- *
- * Contact the author by e-mail: stanislavs@hotmail.com
- *
- * Internet: http://members.tripod.com/~stanislavs/prog/prog.htm
- */
-
- #include "D:\TC\MY\DRSP\DRSP.H"
- #include "D:\TC\UTILS\USER\USER.H"
-
-
- void ScanDrv(void){
- char *Path = "A:\\*.*";
- char Label[12] ={'\0'};
- struct ffblk Block; //struct used in file searching
- char Drive;
- unsigned int ax_, bx_, cx_, dx_, x;
- Bool turn = True;
-
- //Table header
- printf("\n\nThe following drives are available:\n\n"
- "#│ Label │ Free │ Total ││#│ Label │ Free │ Total \n"
- "─┼───────────┼───────────┼────────────┼┼─┼───────────┼───────────┼────────────\n"
- );
-
- //Build a table of available drives.
- for(char i = 1; i < 26; i++){
- if(DriveIsOK(i)){
- //Get drive Size
- asm{
- mov AH, 0x36
- mov DL, i
- int 0x21
- mov ax_, AX
- mov bx_, BX
- mov cx_, CX
- mov dx_, DX
- }
-
- if(ax_ != 0xFFFF){
- turn = !turn;
- Drive = i+64;
-
- Path[0] = Drive;
- x = findfirst(Path, &Block, FA_LABEL); //Read volume label
-
- if(x != 0)
- strcpy(Label, " (Unknown) \0");
- else{
- for(char a = 0, b = 0; a <= 13; a++, b++){
- if(Block.ff_name[a] == '.') a++;
- Label[b] = Block.ff_name[a];
- }
- }
-
- printf("%c│%11s│%11li│%12li", Drive, Label, long(ax_)*long(cx_)*long(bx_), long(ax_)*long(cx_)*long(dx_));
-
- //Fill both sides of the table in turn
- if(turn)
- printf("\n");
- else
- printf("││");
-
- }
- }
- }
- }
-
-
-
- char GetDrive(void){
- char Drive;
- Bool Error;
-
- do{
- Error = False;
- Drive = Ask("\n\nType a drive letter for the drive you want to test. (Esc to quit): ") - 64;
-
- //Does a specified drive exist?
- if(!DriveIsOK(Drive)){
- Error = True;
- printf("\nDrive not found! Please retry, or press Esc to abort.");
- }
- }while (Error);
-
- return Drive + 64;
- }
-
-
- unsigned long GetTestSize(TestData *TD){
- char sSize[7], dl_ = TD->Drive - 64;
- unsigned long DrvSize, iSize;
- unsigned int ax_, bx_, cx_;
- float fSize, MaxSize;
- GetTxt *Txt = new GetTxt;
-
- //Get amount free
- asm{
- mov AH, 0x36
- mov DL, dl_
- int 0x21
- mov ax_, AX
- mov bx_, BX
- mov cx_, CX
- }
-
- DrvSize = long(ax_) * long(cx_) * long(bx_);
-
- //Check if the user passed test size in parameter line.
- if(TD->TestSize == 0.0){
- if(TD->Batch){
- Abort(0, NULL, "\nNo test size selected!", EX_BAD_SIZE);
- }else{
- printf("\n\nPlease enter the amount of MB to test the drive with.\n"
- "The absolute minimum is 0.2, maximum is 999.99. The recommended minimum\n"
- "for floppies is 0.5, and for other media is 3. ('Esc' to quit.)"
- );
-
- if(TD->RO != Off) printf("\n\nIn read-only mode the value means the upper boundary for size of a test\n"
- "file, which the program will look for.");
-
- //Read the desired test size and convert to bytes
- printf("\n-> ______\b\b\b\b\b\b");
-
- textcolor(10);
- Txt->InText(sSize, 6, wherey(), wherex(), 7);
- textcolor(7);
-
- fSize = atof(sSize);
- }
- }else
- fSize = TD->TestSize;
-
- //Check if it is OK in case of read-write test
- if(TD->RO == Off){
- MaxSize = float(DrvSize - 1024) / (float)1048576;
- if(fSize > 999.99)
- fSize = 999.99;
- else if (fSize > MaxSize)
- fSize = MaxSize;
- }
-
- if(fSize == 0.0) nexit(EX_ABORT); //User wants to quit
-
- if(fSize < 0.2)
- Abort(0, NULL, "\n\nTest size too small to give a reliable result!", EX_BAD_SIZE);
-
- iSize = (long)(fSize * 1048576L);
- printf("\n%li bytes selected.", iSize);
-
- TD->TestSize = fSize;
- delete Txt;
- return iSize;
- }
-
-
- unsigned int GetTurns(void){
- char sTurns[4];
- unsigned int Turns;
- GetTxt *Txt = new GetTxt;
-
- printf("\n\nPlease enter the number of turns this test will be performed.\n"
- "The absolute minimum is 3, maximum is 999. The recommended minimum\n"
- "is 5. ('Esc' to quit.)"
- );
-
- //Read the desired number of turns
- printf("\n-> ___\b\b\b");
-
- textcolor(10);
- Txt->InText(sTurns, 3, wherey(), wherex(), 4);
- textcolor(7);
-
- Turns = atoi(sTurns);
-
- if(Turns == 0) nexit(EX_ABORT); //User wants to quit
-
- //Check if it is OK and eventually correct
- if(Turns < 3) Turns = 3;
-
- printf("\n%i turns selected.", Turns);
- delete Txt;
- return Turns;
-
- }
-
-
- Bool DriveIsOK(char Drive){
- char al_, CF;
- unsigned int ax_, flags_;
-
- //Check if a drive is there (This function checks the co-relation between
- //logical and physical drives. See DOS documentation for more info.)
- asm{
- mov AX, 0x440E //DOS Fn 0x44, SubFn 0x0E
- mov BL, Drive
- int 0x21
- mov ax_ , AX
- mov al_, AL
- pushf //push Flags on stack
- pop flags_ //read Flags
- }
-
- //If Carry Flag != 1 no error occured;
- CF = flags_ & 0x01;
- //If logical drive is the same as physical drive or a logical drive has
- //only one physical drive, it is safe to work with it.
- //Another thing to check is when both Carry Flag set to 1 and AX register set to 1
- //(indicating DOS error - Illigal function). This situation may occur, when Fn 0x44
- //SubFn 0x0E is used on a RAM-Drive. It is NOT an error, the drive is accepted.
- if( (!CF && ((al_ == Drive) || (al_ == 0))) || (CF && (ax_ == 1)) ){
- //Check size, to see if any removable drive is inserted
- asm{
- mov AH, 0x36
- mov DL, Drive
- int 0x21
- mov ax_, AX
- }
-
- if(ax_ != 0xFFFF)
- return True;
- else
- return False;
- }else
- return False;
-
- }
-
-
-
- char *FindPath(char *Path){
- //The Path is used in the Analyse routine to write the log-file to the
- //same directory, where the program is stored.
-
- register int i, j;
- extern unsigned int _psp;
-
- //Set the char pointer to the beginning of the environment variable list by
- //finding the relative address at offset 2cH of PSP (Program Segment Prefix)
- //extern char **environ; would not do!
- char far *Env = (char far*)MK_FP(*(int far*)MK_FP(_psp, 0x2C), 0);
-
- //Walk through the env. list until the formal end is reached (Program's
- //start-up path and name are stored 4 bytes beyond the formal env. list.
- //This feature is available from DOS 3.0)
- for(i = 0; !((Env[i] == '\0') && (Env[i + 1] == '\0')); i++);
- i += 4;
-
- //Read the start-up path and name
- for(i = i, j = 0; Env[i] != '\0'; i++, j++)
- Path[j] = Env[i];
-
- //Strip off the start-up name
- for(j = j; ((Path[j] != '\\') && (j >= 0)); j--)
- Path[j] = '\0';
-
- //Extra security check - better not to return any path at all, than an
- //incorrect path.
- if(Path[1] != ':') Path[0] = '\0';
-
- return Path;
- }
-
-
- //ScanPath designed for a multi-pass functionality. It finds the largest
- //file on a drive. The file will not be greater the the maxSize provided.
- unsigned long ScanPath(unsigned long maxSize, const char *Path, char **RetPath, unsigned long biggest){
- struct ffblk ffblk;
- Bool done;
-
- //The following variable are declared as static to make things faster.
- static signed int i;
- static unsigned long size;
- static int cur1 = wherey(), Handle;
- static Bool Esc = False;
- static char buf[MAX_PATH];
-
- char *NewPath = (char *)malloc(sizeof(char) * strlen(Path) + 4);
- if(NewPath == NULL) Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
-
- strcpy(NewPath, Path);
- strcat(NewPath, "*.*");
-
- //Get first file in dir
- done = findfirst(NewPath, &ffblk, 0x37); //All files - Volume
-
- while(!done && !Esc){
-
- size = ffblk.ff_fsize;
-
- //Dive into a sub-dir /Directory
- if((ffblk.ff_attrib & 0x10) && (ffblk.ff_name[0] != '.')){
- NewPath = (char *)realloc(NewPath, strlen(Path) + strlen(ffblk.ff_name) + 2);
- if(NewPath == NULL) Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
-
- strcpy(NewPath, Path);
- strcat(NewPath, ffblk.ff_name);
- strcat(NewPath, "\\");
-
- biggest = ScanPath(maxSize, NewPath, RetPath, biggest);
- }
-
- //Register largest files in a directory if it is accessable.
- if((size > biggest) && (size <= maxSize) && (ffblk.ff_name[0] != '.')){
- sprintf(buf,"%s%s", Path, ffblk.ff_name);
- Handle = open(buf, O_BINARY, S_IREAD);
- if(Handle != -1){
- close(Handle);
- biggest = size;
- *RetPath = (char *)realloc(*RetPath, strlen(Path) + strlen(ffblk.ff_name) + 1);
- if(RetPath == NULL) Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
-
- strcpy(*RetPath, buf); //buf is initialized in file access test
-
- gotoxy(1, cur1);
- printf("Largest file found so far:\n%s", *RetPath);
- for(i = 1; i < MAX_PATH - strlen(*RetPath); i++) printf(" ");
- printf("%ld bytes selected.", biggest);
- }
- }
-
- done = findnext(&ffblk);
-
- //Test if any key is pressed and if it was an Esc. Using BIOS calls
- //is about 5 times faster than kbhit() + getch() combination.
- if(_bios_keybrd(_NKEYBRD_READY)){
- if(_bios_keybrd(_NKEYBRD_READ) == 0x011B) //
- Esc = True;
- }
- }
-
- nfree(NewPath);
- return biggest;
- }
-
- //ScanPath designed for a single-pass functionality. It generates a
- //collection of the 10 largest files on a drive.
- unsigned long ScanPath(unsigned long maxSize, const char *Path, TestFile TF[]){
- struct ffblk ffblk;
- Bool done, changed = False;
- register char i;
-
- //The following variable are declared as static to make things faster.
- static signed int j, tmp;
- static unsigned long size;
- static int cur1 = wherey(), Handle;
- static Bool Esc = False;
- static unsigned long totSize = 0; //Total amount in the array
- static char buf[MAX_PATH];
-
- char *NewPath = (char *)malloc(sizeof(char) * strlen(Path) + 4);
- if(NewPath == NULL)
- Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
-
- strcpy(NewPath, Path);
- strcat(NewPath, "*.*");
-
- //Get first file in dir
- done = findfirst(NewPath, &ffblk, 0x37); //All files - Volume
-
- while(!done && !Esc){
-
- size = ffblk.ff_fsize;
-
- //Dive into a sub-dir /Directory
- if((ffblk.ff_attrib & 0x10) && (ffblk.ff_name[0] != '.')){
- NewPath = (char *)realloc(NewPath, strlen(Path) + strlen(ffblk.ff_name) + 2);
- if(NewPath == NULL)
- Abort(0, NULL, "Out of memory in ScanPath().", EX_NO_MEM);
-
- strcpy(NewPath, Path);
- strcat(NewPath, ffblk.ff_name);
- strcat(NewPath, "\\");
-
- ScanPath(maxSize, NewPath, TF);
- }
-
-
- //If the total amount is not yet reached, try to fit the new
- //file into the array so that the total size increases.
- if((totSize < maxSize) && (size <= maxSize) && (ffblk.ff_name[0] != '.')){
- //Check if the new file will fit at all.
- i = MAX_FBUF - 1;
- if(size > TF[i].Size){
- //Find the optimal location to replace with the new file.
- while(i >= 0){
- if((size > TF[i].Size) && (((totSize - TF[i].Size) + size) <= maxSize)) break;
- i--;
- }
-
- //If i == -1 the the new candidate was too big
- //Otherwise, copy it in.
- if(i >= 0){
- //See if the new file can be read first.
- sprintf(buf,"%s%s", Path, ffblk.ff_name);
- Handle = open(buf, O_BINARY, S_IREAD);
- if(Handle != -1){
- close(Handle);
-
- totSize = (totSize - TF[i].Size) + size;
-
- //From that position shift the items down until the right
- //placce for the new item is reached (sort).
- while((i > 0) && (TF[i - 1].Size < size)){
- TF[i] = TF[i - 1];
- i--;
- }
-
- strcpy(TF[i].Path, buf); //buf is initialized in file access test
- TF[i].Size = size;
- changed = True;
- }
- }
- }
-
-
- //Make a current status printout
- if(changed){
- changed = False;
- gotoxy(1, cur1);
- for(i = 0; (i < MAX_FBUF) && (TF[i].Size != 0); i++){
- //Avoid printouts that are longer than the line of 80 chars
- tmp = strlen(TF[i].Path);
- if(tmp > 67){
- for(j = 0; j < 3; j++)
- buf[j] = TF[i].Path[j];
- buf[j] ='\0';
-
- strcat(buf, "...");
- strcat(buf, (TF[i].Path + (tmp - 61)));
- }else
- strcpy(buf, TF[i].Path);
-
- printf("%10ld: %s", TF[i].Size, buf);
- tmp = 67 - strlen(buf);
- for(j = 0; j < tmp; j++) printf(" ");
- }
- printf("========== \n"
- "%10ld bytes selected.", totSize);
- }
-
- }// end if(totSize...
-
- done = findnext(&ffblk);
-
- //Test if any key is pressed and if it was an Esc. Using BIOS calls
- //is about 5 times faster than kbhit() + getch() combination.
- if(_bios_keybrd(_NKEYBRD_READY)){
- if(_bios_keybrd(_NKEYBRD_READ) == 0x011B) //
- Esc = True;
- }
- }
-
- nfree(NewPath);
- return totSize;
- }
-
-
- //Work with read-only mode
- Ro_mode SetRO(TestData TD){
- int Handle;
- Ro_mode RO = TD.RO;
- char buf[] = FILE_NAME;
- buf[0] = TD.Drive;
-
- if(RO == Off){ //Make some tests
- if((Handle = open(buf, O_CREAT | O_TRUNC | O_BINARY, S_IWRITE)) == -1){
- //Can't open test-file for writing - suggest read-only mode
- printf("\n\nUnable to write to drive! ");
- if(TD.Batch){
- RO = Multi;
- }else{
- if(Ask("Run in read-only mode? (Y/N) ") == 'Y'){
- if(Ask("\n Use a single- or a multipass mode? (S/M) ") == 'S')
- RO = Single;
- else
- RO = Multi;
- }else{
- printf("\n");
- nexit(EX_WRITE_ERR);
- }
- }
-
- }else{
- //Could write to the drive and the user
- //didn't choose RO-mode from the COMMAND-line:
- //do a RW test.
- if(close(Handle) == -1) nexit(EX_CLOSE_ERR);
- if(unlink(buf) == -1) nexit(EX_DEL_ERR);
- }
- }else
- printf("\n");
-
- if(RO != Off)
- printf("Read-only %s-pass mode selected.", (RO == Single) ? "single" : "multi");
-
- return RO;
-
- }
-
-
- //The function that starts the RO file search process
- char *SearchRO(TestData *TD, TestFile TF[]){
- int i;
- char *Path = (char *)malloc(MAX_PATH);
- char *RetPath = (char *)malloc(MAX_PATH);
-
- if((Path == NULL) || (Path == NULL))
- Abort(0, NULL, "Out of memory in SearchRO().", EX_NO_MEM);
-
- strcpy(Path, "C:\\");
- Path[0] = TD->Drive;
-
-
- printf("\n\nLooking for files to perform the test on ('Esc' to accept current value) ");
- textcolor(128 + 7);
- cprintf(". . .");
- textcolor(7);
- //Free MAX_BUF lines, where the results of the scan can be printed.
- for(i = 0; i < MAX_FBUF + 3; i++)
- printf("\n");
-
- gotoxy(1, wherey() - (MAX_FBUF + 2));
-
- _setcursortype(_NOCURSOR);
- if(TD->RO == Multi)
- TD->Size = ScanPath(TD->Size, Path, &RetPath, 0);
- else
- TD->Size = ScanPath(TD->Size, Path, TF);
-
- TD->TestSize = (float)(TD->Size) / 1048576.0;
-
- if(TD->TestSize < 0.2){
- fprintf(stderr, "\n\nTest size too small to give a reliable result! Aborting.\n");
- nexit(EX_BAD_SIZE);
- }
- _setcursortype(_NORMALCURSOR);
-
- nfree(Path);
-
- return RetPath;
- }