Chapter – 10
Data Recovery From Corrupted Floppy
Data Recovery From Corrupted Floppy
The Floppy is one of the most unreliable sources for data storage. If you go to any organization which uses computer systems and ask to its employees about the problems generated by floppy disks, you will very commonly hear the problem that the employee of the organization was having some important data in his floppy and now the floppy is not readable by the computer and a messages is displayed something like,
“Can not read the disk”
“Track 0 Bad”
“Invalid Drive or Capacity”
“The disk is not formatted. Do you want to format it now?”
This is the everyday problem for the organizations which uses computer systems and floppy. The problem becomes critical when you come to know that there was no backup made or backup available for the data which seems to be lost in the corrupted floppy disk.
The biggest hell of the problem is supposed to come when you make backup in the floppy for your critical information, rescue disks of Antivirus program to overcome the virus attack or boot records or other backups (there may be number of possibilities) in a floppy and when you want to reuse the backup from the floppy it gives a reading error.
In such condition you are about to lose your important information and data or even in some cases when you feel the lack of backups and recovery program for you computer boot information and Virus attack rescue programs etc., you may suffer a big loss of data in form of OS crash occurred due to the lack of information, stored in the floppy that is not readable by the computer now.
In such cases it becomes most important requirement to recover the data from the floppy that has been declared bad by your computer system.
Why the floppy is not readable
The most common problem that causes a floppy to show such type of error messages is the corruption of its DOS boot record (DBR) of floppy, which helps the computer to know the logical identification of the floppy.
The DBR is a small program stored in track 0, head 0 and sector 1 and containing important information about the floppy such as:
- Number of bytes per sector
- Sector per cluster
- Number of FATs
- Maximum number of root directories etc.
Since Floppy has no logical partition system therefore there is no MBR available in floppy. The First Sector of Floppy holds the DBR. This is also a main difference to compare logical structure of hard disk with a floppy.
When we read the boot sector information of a floppy with the help of any disk editing program, it will display information like as in the figure given next.
The following figure shows the 512 Bytes information of the DBR of a 1.44MB, 3½ Inch floppy.
If this information is corrupted any how or it becomes unreadable, the floppy disk causes such reading error messages. It may be due to physical or logical corruption of the first sector of the disk.
The Logical corruption includes the cases when the information of the first sector of the floppy is changed, there occurs any logical bad sector or the DBR of the floppy is corrupted due to any other reason.
The Physical corruption is supposed to take place in case of, if there are physical bad sectors (means the sector 1 is physically damaged) on the first sector of the floppy disk. The problem becomes more serious when you find that floppy is having more than one bad sector in track 0.
How to recover
As we have learnt both the causes of corruption I hope now you are able to understand the problem. It is not a very difficult thing to recover the data from logical corruption however the recovery from the physical corruption needs slightly more efforts to do.
Method – 1
Store the boot image of any fresh floppy
If the problem is logical, now we understand that how can we recover the data. What we need to do is just to get the appropriate Boot record from another floppy of same size and capacity and to paste it to the first sector of the unreadable floppy. Though the problem was created due to the bad boot record, it should work now.
There are two steps involved in this procedure by following which we are recovering our data from an unreadable floppy:
- Making the image of DOS Boot Record of a good floppy
- Pasting the boot image to the first sector of unreadable floppy
Making the image of DOS Boot Record of a good floppy
To store the image of boot record of fresh floppy, the program must do the following three tasks:
- Read exactly first 512 bytes of the good floppy
- Check for the successful read operation (Most important)
- Store these 512 bytes to the specified filename and destination path
The sector of floppy is 512 bytes and it is necessary to copy the exact image of the sector. It is most important and necessary step in case of any type of operations applied on floppy to check whether the operation was successful or not.
There may be any initialization problem even with the good and fresh floppy disk. That is why in most of the cases when the operation is performed on floppy disks, first of all initialization of floppy disks is performed in the programming with the reset disk operation (Function 00 H of INT 13H).
If Even after initialization the recently inserted floppy disk or changed floppy disk causes any reading error you are advised to run the program again, most probably it may work this time.
The following program is to perform these specified tasks. Let us see how it proceeds:
/* Store The Boot Image to a file from a Fresh Floppy Disk */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store Boot Image");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
while(count<512)
{
fprintf(fp,"%c",dbuf[count] & 0xff );
count++;
}
fclose(fp);
gotoxy(10,14);cprintf("Disk read from Floppy disk drive
: successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n", result);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
Comments on Program coding:
In the program coding given earlier, basically we are proceeding to perform the following tasks step by step:
- dinfo points to the diskinfo_t structure that contains the information of parameters required by the operation performed by the _bios_disk function.
- Since we want to read first sector of the disk therefore the location of the sector will be as follows:
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- Open a file stream of user given file name and path to store the boot image information of exact 512 bytes. The file name and path is stored in the character array fname.
- Initialize the disk system using the interrupt 13H (function 00h) where regs.h.ah = 0x00 points to the function 00 H and regs.h.dl = 0x00 is used for a: floppy. And int86(0x13, ®s, ®s) invokes MS-DOS interrupt service INT 13 H.
- _bios_disk(_DISK_READ, &dinfo) reads the specified sector of the floppy disk.
- The status returned is stored in result that is used to display the message for successful operation or to display an error message on the screen if any error occurs.
Pasting the boot image to the first sector of unreadable floppy
For pasting the boot image from the file to the first sector of the unreadable floppy we have to perform the following three main tasks in our program:
- Read exact 512 bytes information of boot record of fresh floppy from previously saved file.
- Write this information to the first sector of the floppy which is currently unreadable.
- Check for the successful completion of write operation (Most Important).
As the sector of floppy is 512 bytes and it is necessary to paste the exact boot image to the sector. It is most important and necessary step in case of any type of operations applied on floppy to check whether the operation was successful or not.
There may be any initialization problem with the floppy disk during the operation therefore you must initialize the disk by resetting the disk system(using function 00H of INT 13H).
If Even after initialization the recently inserted floppy disk or changed floppy disk causes any reading error you are advised to run the program again, most probably it may work this time.
The following program is to perform these specified tasks. Let us see how it proceeds:
/* Load Boot Image to the unreadable Floppy */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
char dbuf[512];
FILE *fp;
clrscr();
gotoxy(5,3);cprintf("Enter The File Name And Path, In Which Boot image of Floppy Is Stored");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"rb");
if((fp=fopen(fname,"rb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be Opened");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to Recover Floppy disk drive :\n");
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
while(count<512)
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
fclose(fp);
gotoxy(10,14);cprintf("Successful!!! I Hope Floppy May
Work Now.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
Comments on Program coding:
In the program coding given earlier, basically we are proceeding to perform the following tasks step by step:
- dinfo points to the diskinfo_t structure that contains the information of parameters required by the operation performed by the _bios_disk function.
- As we are going to write the information on the first sector of the disk therefore the location of the sector will be as follows:
- Open the file in which the boot image information of 512 bytes of a fresh floppy was stored by the previous program. The file name and path is stored in the character array fname.
- Initialize the disk system using the interrupt 13H (function 00h) where regs.h.ah = 0x00 points to the function 00 H and regs.h.dl = 0x00 is used for a: floppy. And int86(0x13, ®s, ®s) invokes MS-DOS interrupt service INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) writes the boot information from the specified file to the first (specified) sector of the floppy disk.
- The status returned is stored in result that is used to display the message for successful operation or to display an error message on the screen if any error occurs.
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
Let us do it with single program
I hope, now you have understood the concept behind such type of data recovery from the floppy disk. After this let us imagine a single program which gives the same results that we got with the help of previously discussed two programs.
We were doing the following tasks with the recently discussed programs:
- Store the Boot information from a good floppy disk to a file
- Paste this information to the first sector of the currently unreadable floppy The file which we were using to store the boot image was working as intermediate bridge to connect the operations of both the program. But if we define this boot information in our program coding itself, we need not to create a file as well as we need not to read the boot information of the floppy from the file.
In our next program we are telling our program about what it has to write in the first sector of the unreadable floppy disk and thus we are able to avoid two different programs to do the same task and we can recover our data in the same way as before from the new single program.
The program thus becomes simple with less coding and we are able to reduce the probability of occurrence of file read, write or creation errors. We are doing the following four important tasks in this program:
Don’t think the program difficult to write and understand by seeing the 512 bytes hexadecimal information of dbuf[512]. Later, We’ll discuss the easy way to write this information for your program coding.
- Define the DOS boot record information in hexadecimal system to be written in the first sector of currently unreadable floppy.
- Reset the disk system to initialize the floppy disk (INT 13H, Function 00H).
- Write the DOS Boot Record to the first sector of floppy
- Check for the successful completion of operation and error, if occurred.
Let us examine the program:
/* Single Program to load Default Boot Image To Unreadable Floppy Disk */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* Boot Image to Be Loaded in the Floppy Disk Drive */
static char dbuf[512]=
{
0xEB,0x3E,0x90,0x2B,0x29,0x6E, 0x70,0x32,0x49,0x48,0x43,0x0,0x2 ,0x1 ,0x1 ,0x0,
0x2,0xE0,0x0,0x40,0xB,0xF0,0x9,0x0,0x12, 0x0 ,0x2 ,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x29, 0x24,0x3B,0xDB, 0x16,0x4E, 0x4F, 0x20, 0x4E,0x41,0x4D,0x45,
0x20, 0x20, 0x20,0x20,0x46,0x41, 0x54,0x31, 0x32,0x20,0x20, 0x20,0xF1,0x7D, 0xFA,
0x33, 0xC9,0x8E,0xD1, 0xBC,0xFC,0x7B, 0x16,0x7 ,0xBD,0x78,0x0 ,0xC5,0x76,0x0,
0x1E,0x56,0x16,0x55, 0xBF,0x22,0x5 ,0x89,0x7E,0x0 ,0x89,0x4E,0x2 ,0xB1,0xB,0xFC,
0xF3,0xA4,0x6 ,0x1F,0xBD,0x0,0x7C ,0xC6,0x45,0xFE,0xF,0x8B, 0x46,0x18,0x88,0x45,
0xF9,0xFB,0x38,0x66, 0x24,0x7C,0x4,0xCD,0x13, 0x72,0x3C,0x8A,
0x46,0x10,0x98,0xF7,
0x66,0x16,0x3, 0x46,0x1C,0x13,0x56, 0x1E,0x3 ,0x46,0xE,0x13,
0xD1,0x50,0x52,0x89,
0x46,0xFC,0x89, 0x56,0xFE,0xB8,0x20,0x0, 0x8B,0x76,0x11,0xF7,
0xE6,0x8B,0x5E,0xB ,
0x3 ,0xC3,0x48,0xF7,0xF3,0x1,0x46,0xFC, 0x11,0x4E,0xFE,0x5A,
0x58,0xBB,0x0 ,0x7 ,
0x8B,0xFB,0xB1,0x1, 0xE8,0x94,0x0 ,0x72,0x47,0x38,0x2D,0x74, 0x19,0xB1,0xB,0x56,
0x8B,0x76,0x3E, 0xF3,0xA6,0x5E,0x74,0x4A,0x4E, 0x74,0xB,0x3 , 0xF9,0x83, 0xC7, 0x15,
0x3B, 0xFB,0x72,0xE5,0xEB,0xD7,0x2B, 0xC9,0xB8,0xD8, 0x7D, 0x87, 0x46, 0x3E,0x3C,
0xD8,0x75,0x99, 0xBE,0x80,0x7D,0xAC, 0x98,0x3,0xF0,0xAC,0x84 ,0xC0,0x74,0x17,0x3C,
0xFF,0x74,0x9 ,0xB4,0xE ,0xBB,0x7 ,0x0,0xCD,0x10,0xEB, 0xEE,0xBE,0x83,0x7D, 0xEB,
0xE5, 0xBE, 0x81,0x7D, 0xEB,0xE0, 0x33,0xC0,0xCD,0x16,0x5E,0x1F,0x8F,0x4 ,0x8F,0x44,
0x2,0xCD, 0x19,0xBE,0x82,0x7D,0x8B,0x7D,0xF, 0x83,0xFF,0x2,0 x72,0xC8, 0x8B,0xC7,0x48,
0x48,0x8A,0x4E,0xD,0xF7,0xE1,0x3 ,0x46,0xFC, 0x13,0x56,0xFE,0xBB,0x0 ,0x7 ,0x53,0xB1,0x4 ,
0xE8,0x16,0x0, 0x5B,0x72,0xC8, 0x81,0x3F,0x4D,0x5A, 0x75,0xA7,0x81,0xBF, 0x0,0x2 ,0x42,0x4A,
0x75,0x9F,0xEA,0x0 ,0x2 ,0x70,0x0,0x50,0x52, 0x51, 0x91, 0x92, 0x33, 0xD2,0xF7,0x76,0x18,0x91,
0xF7,0x76, 0x18,0x42, 0x87, 0xCA, 0xF7, 0x76,0x1A,0x8A,0xF2,0x8A,0x56, 0x24,0x8A,0xE8,
0xD0, 0xCC,0xD0,0xCC,0xA, 0xCC,0xB8,0x1,0x2, 0xCD,0x13,0x59,0x5A, 0x58, 0x72,0x9,0x40,
0x75,0x1,0x42,0x3, 0x5E,0xB,0xE2,0xCC,0xC3,0x3 ,0x18 ,0x1 ,0x27,0xD ,0xA,0x49, 0x6E,
0x76,0x61,0x6C,0x69,0x64,0x20, 0x73, 0x79, 0x73, 0x74, 0x65,0x6D,0x20,0x64,0x69,0x73,
0x6B,0xFF,0xD ,0xA,0x44,0x69, 0x73,0x6B,0x20, 0x49,0x2F, 0x4F,0x20, 0x65,0x72, 0x72,0x6F,
0x72,0xFF,0xD ,0xA,0x52, 0x65,0x70,0x6C,0x61,0x63, 0x65,0x20,
0x74,0x68, 0x65, 0x20,
0x64, 0x69,0x73, 0x6B,0x2C,0x20,0x61, 0x6E,0x64,0x20,0x74, 0x68, 0x65, 0x6E, 0x20,0x70,
0x72,0x65, 0x73,0x73, 0x20,0x61, 0x6E,0x79,0x20,0x6B,0x65,0x79,0xD,0xA, 0x0,0x49,0x4F,
0x20,0x20,0x20,0x20, 0x20,0x20,0x53,0x59,0x53,0x4D, 0x53, 0x44, 0x4F, 0x53,0x20,0x20,
0x20,0x53, 0x59,0x53, 0x80,0x1,0x0 ,0x57,0x49, 0x4E,0x42, 0x4F,0x4F,0x54,0x20,0x53, 0x59
,0x53,0x0,0x0,0x55,0xAA};
clrscr();
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk Write Status :successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-
protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13 extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
In this program coding, basically we are proceeding to perform the following these tasks step by step:
- Static character data buffer dbuf[512] is provided the information of 512 bytes in hexadecimal system, which is to be written in the first sector of unreadable floppy. dbuf[512] tells the computer during the operation that what information is to be written in the first sector of floppy. (See the Next Program)
- dinfo points to the diskinfo_t structure that contains the information of parameters required by the operation performed by the _bios_disk function.
- As we are going to write the information on the first sector of the disk therefore the location of the sector will be as follows:
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- Initialize the disk system using the interrupt 13H (function 00h) where regs.h.ah = 0x00 points to the function 00 H and regs.h.dl = 0x00 is used for a: floppy. And int86(0x13, ®s, ®s) invokes MS-DOS interrupt service INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) writes the boot information from the specified file to the first (specified) sector of the floppy disk.
The status returned is stored in result that is used to display the message for successful operation or to display an error message on the screen if any error occurs.
Storing the boot Image in HEXADECIMAL Characters to use in our previous Program
It will be a very difficult job to write all 512 the characters of floppy’s DOS Boot Record manually in hexadecimal system without any error in the program we recently discussed. If we can write it accurately even than it will be a difficult and time taking task to do this. Let us use some tricky mind to store the data for data buffer dbuf[512] in a file.
We know that in C programming the hexadecimal characters are represented with 0x such that if hexadecimal character is A9 H, we shall write this in our C program as 0xA9. Our next program is doing the same. It will store the data that we need to write in our previous program, as the data of data buffer dbuf[512].
What you have to do is just to take a fresh and new floppy to make the image of its DBR and copy the output of this program from the destination file specified and paste this data in your program. Do some formatting if required. Let us see how it works:
/* Program to make the boot Image of the Floppy Disk In HEX Character */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result,i;
int count=0;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store The Boot Image in HEX System");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
gotoxy(10,9); cprintf("Attempting to read from Floppy
disk drive :\n");
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk read from Floppy disk drive :
successful.\n");
while(count<512)
{
fprintf(fp,"0x%X, ",dbuf[count] & 0xff );
count++;
}
fclose(fp);
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
}
return 0;
}
Comments on coding of the program:
Thus the data is stored in the specified file. Just copy the data to your program and do some required formatting. You should never forget the following tips through out the procedure:
- Make it sure that the operation of the program was successful and the data which has been stored in the destination file is the appropriate.
- You should check the operation through out for occurrence of expected errors.
- You must initialize the Floppy disk in, with the program before reading its boot sector. You may use function 00H of INT 13H for this purpose.
Method – 2
What to do if Method – 1 doesn’t work?
If the Method – 1 does not work and the unreadable disk is not allowing the program to re-write the boot information on its first sector you should try this second method. The reason behind the failure of First Method may be the physical corruption of first sector of the floppy disk.
In this second method we are going to copy all the data of the surface of the unreadable Floppy to a single file temporarily and then we shall paste this image directly on the surface of the another good disk.
The procedure involves the following two important steps:
- Sector-by-Sector Copy all the data of the surface of floppy’s media to a single file temporarily.
- Paste the data previously stored in file, to a new fresh floppy as it is, on the same sectors.
Copy all the data of media surface to a single file
To store all the data of the surface of media of floppy, the program must do the following three tasks:
- Initialize the disk properly with the help of function 00H of INT 13H.
- Read the Sector-by-Sector information of the surface and store to a single file.
- Check for the successful read operation (Most important)
It is very common to have any initialization problem with a floppy disk which leads many unsuccessful read messages. That is why the disk must be initialized before the read write operation with the help of programming.
It is most important and necessary step in case of any type of operations applied on floppy to check whether the operation was successful or not.
If Even after initialization the recently inserted floppy disk or changed floppy disk causes any reading error you are advised to run the program again, most probably it may work this time.
The following program is to perform these specified tasks. Let us see how it proceeds:
/* Program to store the data of physical surface of the floppy disk to a file */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File,
Press any Key To EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result,head,track,sector);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track,head,sector);
}
}
}
}
Comments on Program coding:
In the program coding given earlier, basically we are proceeding to perform the following tasks step by step:
- Character array filename[80] stores the user defined path and file name of the file in which we are going to store the data temporarily.
- dinfo points to the diskinfo_t structure that contains the information of parameters required by the operation performed by the _bios_disk function.
- Initialize the disk system using the interrupt 13H (function 00h) where regs.h.ah = 0x00 points to the function 00 H and regs.h.dl = 0x00 is used for a: floppy. And int86(0x13, ®s, ®s) invokes MS-DOS interrupt service INT 13 H.
- As we are going to read all the information of the surface of disk, The parameters of _bios_disk will be as follows:
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_READ, &dinfo) reads the data from the physical surface of floppy disk from the sector specified by dinfo.
- The status returned is stored in result that is used to display the message for successful operation or to display an error message on the screen if any error occurs.
Always remember that the size of the file that holds the image of the floppy disk’s data must be exact 1,474,560 bytes because the floppy has 80 tracks (0 to 79), 2 sides or heads (head 0 and head 1), each track has 18 sectors on it and each sector holds the 512 bytes of data, thus
Total bytes = (Number of tracks) * (Number of Heads) *
(Number of Sectors per Track) * 512
= 80*2*18*512
= 1,474,560 Bytes
Thus, if there is any error in reading at any sector of the floppy disk, it will change the size of the file from 1,474,560 Bytes, which will make the entire information completely or partially of no use for the destination disk on which we are going to write the disk image sector by sector from this file.
This is so because the Computer reads the information of any file on the surface of the media of the floppy disk within the sector range as it has been allocated in its allocation unit. Now if the sectors of the data of the files are changed, the complete file information is changed.
Thinking for the solution of sector(s) reading error
It is possible with the bad or unreadable floppy that it may have such bad area on its surface that we may not be able to read the information from the surface of the disk.
In this condition the information of this sector(s) will we skipped and the image of the floppy will be distorted even for the other sectors as the size of the image file in this case differs from 1,474,560 Bytes.
To maintain the size of the image file and to paste the rest of the information on the exact sector locations on the destination disk, we write some other information on behalf of the original data of 512 bytes and in this way, we’ll be capable to save the rest of the information however the recovery in such case may be the partial recovery.
If your system also fails to read the first sector of the source floppy, after pasting the image to the destination floppy you should run the program described before, to rewrite the DOS Boot Record of the floppy.
Let us see how we can do it by programming:
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
/*Information of 512 Bytes to fill space of Bad Sector */
/// I used 512 zeros to fill the space of 512 bytes \\\
static char dbuf2[512] =
"00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result, head, track, sector);
/* If Sector is not Readable, occupy 512 bytes by dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
Comments on Program coding:
In the coding of the program, every step is same as in previous program except the data buffer dbuf2[512], which we are using to handle the error generated by bad sector during the Disk reading operation and to maintain the size of the image file.
By doing this, we are filling the space of the information, which we failed to read from the bad sector and now we are writing the pseudo information of 512 bytes so that we may maintain the accuracy of disk image.
Paste the Data from the file to the physical surface of fresh floppy:
In this step, we paste the data stored in the file by the previous program, to the physical surface of the fresh floppy, sector by sector in the same way by which we copied it to the file.
The program proceeds with the following main steps:
- Open the file in which we stored the surface data of the unreadable floppy temporarily.
- Initialize the disk system properly by the resetting function 00H of INT 13H.
- Write the information on the sectors of the fresh floppy from the file.
- Display the write status simultaneously to find or avoid the occurrence of errors.
The program source code has been given below. Let us examine how it works:
/* Program to write the data on the sectors of the surface of fresh floppy from the file, created by the previous program */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
int count =0;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *fp;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((fp=fopen(filename,"rb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(1);
}
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
count =0;
while(count<512 )
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector;/* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result= _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
printf("Successful write on Track = %d, Head = %d,
Sector = %d.\n", track, head, sector);
else
printf("Cannot read drive A, status = 0x%02x\n",
result);
}
}
}
}
Comments on Program coding:
In the program coding given earlier, basically we are proceeding to perform the following tasks step by step:
- Character array filename[80] holds the path and file name of the file in which we stored the data of the surface of unreadable floppy temporarily.
- dinfo points to the diskinfo_t structure that contains the information of parameters required by the operation performed by the _bios_disk function.
- Initialize the disk system using the interrupt 13H (function 00h) where regs.h.ah = 0x00 points to the function 00 H and regs.h.dl = 0x00 is used for a: floppy. And int86(0x13, ®s, ®s) invokes MS-DOS interrupt service INT 13 H.
- As we are going to write the information directly to sectors of the surface of disk, The parameters of _bios_disk will be as follows:
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_WRITE, &dinfo) writes the data on the sectors of the physical surface of floppy disk, specified by dinfo.
- The status returned is stored in result that is used to display the message for successful operation or to display an error message on the screen if any error occurs.
If after the Method – 2 your new floppy does not work, you may further apply Method – 1 on your new floppy, which you used as destination disk during the Method – 2.
Not only this but also the number of hits and trials may vary depending upon the corruption of the disk. But you need not to worry if even after you are not getting the satisfactory results.
You can try file by file recovery or can try many more tips which you will learn in the next. Here we shall implement the idea of collecting the file information from Root Directories, in our programming to recover the data.
Thinking for Logical Recovery for Deleted or lost Data:
All the previous cases we discussed in this chapter for recovery, were to recover the data in such cases where we were expecting that only the DBR is corrupted and the sectors in track 0, having FAT1, FAT2 and Root directories are readable.
But if the problem is due to the corruption of FAT or the data has been deleted from the disk or you want to recover the data directly by reading its information from the Root directory, we need to read the information such as, Filename, starting cluster, size of the file, Attribute etc. from its Root directory entry.
As we have already discussed about Root Directory in earlier chapters that there is the information of 32 Bytes for each file or directory. These 32 Bytes are divided as follows:
Number of Bytes |
Information Description |
8 Bytes |
Filename |
3 Bytes |
Extension |
1 Byte |
Attribute |
10 Bytes |
Reserved |
2 Bytes |
Time, Created or Last Updated |
2 Bytes |
Date, Created or Last Updated |
2 Bytes |
Starting Cluster |
4 Bytes |
File Size |
We recover the data by reading the information of the file(s) from the Root Directory and then integrate the file to the destination path and recover the file. Our next program performs the following steps to recover the data:
- Read the Root Directory entries and Display them on the screen with all information such as File/Directory name, Extension of the File, Starting cluster size of the files in Bytes.
- Read the Files and Directories information in the Subdirectories and display them if required.
- Confirm the File name to be recovered and continue recovery.
- Calculate the CHS (Cylinder, Head, and Sector) info for the Specified file to be recovered.
- Integrate the data of the file from the data area of the disk and save the recovered file to the specified destination file name in specified path.
This Program does not care if the boot information of the floppy is readable or not. Therefore you can recover even deleted data from the corrupted floppy disk too. Let us see the coding of the program:
/* Program to recover the data from the Floppy disk by Reading file information from the Root Directory */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void main()
{
void Display_Information(unsigned int,unsigned int,
unsigned int);
unsigned int track=0,head=1,sector=2;
Display_Information(track,head,sector);
} /*End of main */
void Display_Information(unsigned int track,
unsigned int head,
unsigned int sector)
{
void recover(unsigned int *,unsigned int);
char buf[512]; // Buffer of 512 Bytes
char ch;
struct diskinfo_t finfo; //Structure, Used by _bios_disk
unsigned int result,i,j, count=0; /* Unsigned Integers
Defined */
unsigned int file_no; /* Unsigned Integer
for File Number */
struct
{
unsigned int name[8],ext[3]; /* File Name for DOS in 8.3
(Eight Dot Three) Format */
unsigned int attribute; // File/Directory Attribute
unsigned int start; // Starting Cluster of the File
long unsigned int size; // Size of the File in Bytes
}root[32]; /* 32 Bytes Information of
File/Directory in Root
Directory */
clrscr();
do
{
file_no=0;
finfo.drive = 0x00; /* drive number for A: */
finfo.head = head; /* disk head number */
finfo.track = track; /* track number */
finfo.sector= sector; /* sector number */
finfo.nsectors=1; /* sector count */
finfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &finfo); /* Read the
Sector */
if( (result & 0xff00) != 0) /* If Read Error, Display
Error Message and Exit*/
{
printf("Read error");
getch();
exit(0); // Go Back to DOS
}
/// Information Display Screen Format \\\
clrscr();
gotoxy(9,1);
cprintf("DISPLAY CYLN: %u, HEAD: %u, SECTOR: %u",
track, head, sector);
gotoxy(9,2);
cprintf("FNO NAME EXT ATTRIBUTE START SIZE");
gotoxy(7,3);
cprintf("--------------------------------------------");
/* One Sector At a time. Every File/DIR entry Takes 32 Byte */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// Find The File/Dir Name \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// Find the Extension \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// Starting Cluster \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Calculate the Size \\\
root[file_no].size =(long unsigned int)(0xff &
buf[31+i])*16*16*16*16*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[30+i])*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[29+i])*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[28+i]);
if((root[file_no].start == 0) ||
(root[file_no].attribute == 15))
continue;
else
{
gotoxy(8,i/32+4);
cprintf("%2u",file_no); /* Display File
Number */
for(j=0;j<8;j++)
{
gotoxy(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Display File
Name */
}
for(j=0;j<3;j++)
{
gotoxy(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Display
Extension */
}
gotoxy(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* Display
Attribute */
if(root[file_no].attribute==16)
{
gotoxy(33,i/32+4);
cprintf("<DIR>"); /* Display if Directory Attribute */
}
else
{
gotoxy(33,i/32+4);
cprintf("<FILE>"); /* The Entry is of a file */
}
gotoxy(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Display
Starting Cluster */
gotoxy(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* size of the
File */
}
file_no++;
}
gotoxy(10,
cprintf("Press 'M' : To see list of more files &quo
gotoxy(10,
cprintf("Press 'R' :To recover a file from the above
list&quo
ch=getc
Remember that the file name starting with s (E5H) represents that the file has been deleted and therefore the first character of the filename has been replaced with s (See the root directory description in the earlier chapters ).
And the output of the program is displayed like this:
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
--------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Press 'M' : To see list of more files
Press 'R' :To recover a file from the above list R
|
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
----------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Enter FNO. of the file you want to recover 1
You want to recover _2_INFO .C
Cylinder = 1, Head = 0, Sector = 1 Integrating........
Enter Path and Filename to recover the file: c:\windows\desktop\H2_INFO.C
Recovery Done !!!
|
Comments on coding:
The function Display_Information is to read the file and directory information and from the root directory. In the Structure we are reading the 32 bytes information for every file or directory with root[32].
The unsigned integer arrays name[8] and ext[3] are for File or Directory name for DOS in 8.3 (Eight Dot Three) Format. Similarly one byte is for attribute and two bytes for starting cluster. long unsigned int size; is to store the size of the file of four bytes.
The _bios_disk function reads the sector, specified by the structure finfo and the status of the operation is stored in result.
From the every information of 512 bytes read by the _bios_disk function, till the root directory area ends, we collect the information of the files and directories stored in the disk and display them on the screen.
The integer file_no is stores the number of the file or directory in the list, starting from 0. Generally the size of root directory is of 14 sectors and root directory generally starts from Cylinder =0, Head = 0 and Sector =2 in case of 1.44MB and 3½ floppy disk.
If user gives the character ‘M’ or ‘m’ as input, the information of next sector is displayed if the choice by user is ‘R’ or ‘r’ the recovery functions are called. The coding of the function recover() has been given below:
/* Function To Start Recovery for The Specified File */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/* Function to Integrate The Specified File */
void integrate(long unsigned int,unsigned int,
unsigned int,unsigned int);
unsigned int file_no,i;
char ch;
unsigned int *loc;
unsigned int cylinder,head,sector;
unsigned int start;
long unsigned int size;
clear_the_line(21); /* Clear The Row Number 21 */
clear_the_line(22); /* Clear The Row Number 22 */
clear_the_line(23); /* Clear The Row Number 23 */
clear_the_line(24); /* Clear The Row Number 24 */
gotoxy(10,21);
cprintf("Enter FNO. of the file you want to recover");
scanf("%u",&file_no); /* Get the File No. to be
Recovered */
loc=(root+(len*file_no/2));
/* Confirm the file Name to be recovered */
gotoxy(10,22);
cprintf("You want to recover");
for(i=0;i<8;i++)
{
gotoxy(30+i,22);
cprintf("%c",*(loc+i)); /* File name */
}
gotoxy(38,22);
cprintf(".");
for(i=0;i<3;i++)
{
gotoxy(39+i,22);
cprintf("%c",*(loc+8+i)); /* File Extension */
}
start=*(loc+12);
/// Sorry, You Selected a Directory \\\
if(*(loc+11)==16)
{
gotoxy(5,23);
cprintf("Is A directory. Do you want to see the
contents of this directory Y/N");
ch=getch();
if(ch==27)
main();
if(ch=='y' || ch=='Y')
{
/* Calculate Geomatry */
calculate(start,&cylinder,&head,§or);
/* Display Directory Contents */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* Calculate for CHS info */
calculate(start,&cylinder,&head,§or);
/* Integrate The File */
integrate(size,cylinder,head,sector);
}
}
Comments on coding:
The function recover() is to get the user input to start the recovery. The file number given as input by the user to recover the file, is stored in file_no.
If the entered number is for the Directory entry, Display_Information() shows the contents of that directory, else The file name and extension of file number file_no is displayed on the screen to confirm the file to be recovered.
To recover the specified file, the functions calculate() and integrate() are called within the function. The coding of the function calculate() has been given below:
/* Function To calculate the CHS Geomatry For The Recovery */
void calculate(unsigned int start,unsigned int *cylinder,
unsigned int *head,unsigned int *sector)
{
unsigned int temp;
*cylinder=0;
*head=1;
*sector=14;
if(start<5)
*sector=14+start;
else
{
temp= (start-4)/18;
if(temp>0)
{
if(temp%2==0)
*head=0;
else
*head=1;
*cylinder+=1+temp/2;
}
else
{
*head=0;
*cylinder=1;
}
*sector=(start-4)%18;
}
/// Display The CHS of The File to Be Recovered \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
Comments on coding:
The function calculate() is to calculate the Cylinder, Head and Sector information for the file to be recovered. After calculation the Cylinder, Head and Sector numbers are displayed on the screen.
The coding for the function integrate() has been given below:
/* Integrate File and Save the Recovered File To the Specified Path and File name */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* Function to Verify The Sector for Errors */
int verify_the_sector(unsigned int, unsigned int,
unsigned int);
int status;
char buf[512],*Filename_with_path;
struct diskinfo_t dinfo;
unsigned int result;
FILE *fp;
unsigned int left,i;
unsigned int sec;
/* Enter The Destination Path and File Name to Save the Recovered file */
gotoxy(2,24);
cprintf("Enter Path and Filename to recover the file: ");
fflush(stdin);
gets(Filename_with_path);
fp=fopen(Filename_with_path,"wb");
/* If Error Occured Display Error Message and get input Path and File Name Again */
if(fp==NULL)
{
gotoxy(5,25);
cprintf("Error in opening the file");
getch();
clear_the_line(24);
gotoxy(0,25);
cprintf(" ");
integrate(size,cylinder,head,sector); /* Enter the
Destination Again */
}
/* If Everything is all right, Integrate and write */
gotoxy(50,23);
cprintf("Integrating........");
left= size%512;
sec = size/512;
sec++;
while(sec>0)
{
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = cylinder; /* track number */
dinfo.sector= sector; /* sector number */
dinfo.nsectors=1; /* sector count */
dinfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
/* If there is Error While Reading any Sector */
if( (result & 0xff00) != 0)
{
gotoxy(5,25);
cprintf("read error Cylinder %u, Head %u, Sector %u",
cylinder, head, sector);
}
else
{
if(sec==1)
{
for(i=0;i<left;i++)
fputc(buf[i],fp); /* Write The Integrated
Information to the File */
}
else
{
fwrite(buf,512,1,fp);
}
Comments on coding:
The function integrate() is the actual module of performing the recovery of the user specified file, in this recovery program.
The file name with the destination path to store the recovered file is stored in the character pointer *Filename_with_path. If there is any error in opening the destination file, error message is displayed and user is prompt again to enter the destination.
The function _bios_disk(_DISK_READ, &dinfo); reads the data of the file from the data area of the disk sector by sector, specified by the structure dinfo and stored in the data buffer buf. This data of 512 bytes is written to the destination file. This is repeated until the complete file is integrated.
The function status=verify_the_sector (cylinder,head,sector); verifies the sector to be read. If the status = 10, it represents a bad (0xA) sector. The coding of the function has been given below:
/// Verify the Sector. (No Data is Transferred here) \\\
int verify_the_sector(unsigned int c,unsigned int h,unsigned int s)
{
int status;
char *buf;
union REGS in, out;
struct SREGS sg;
in.h.ah = 0x04; /* Function Number */
in.h.al = 1; /* Number of Sectors to Verify*/
in.h.dl = 0x00; /* Drive Number for A: */
in.h.ch = c; /* Cylinder Number */
in.h.dh = h; /* Head Number */
in.h.cl = s; /* Sector Number */
in.x.bx = FP_OFF(buf);/* Offset */
sg.es = FP_SEG(buf); /* Segment */
int86x(0x13,&in,&out,&sg); /* Call the Function 4H
of INT 13H */
if(out.x.cflag)
{
status=out.h.ah;
}
return(status);
}
Comments on Coding:
The function verify_the_sector(), verifies sector to be read by the _bios_disk() function and returns the status of the operation. The function uses INT 13H and function 4H to verify the sector.
*buf is the data buffer, 0x04 is the function number specified by in.h.ah = 0x04; and in.h.al = 1; instructs to verify the one sector at a time. in.h.dl = 0x00; is used for the drive number for floppy drive A:, c,h, and s are Cylinder, Head and Sector numbers.
The function int86x() is used to invoke INT 13H (function 4H) with segment register values. The status of the operation is returned by the integer status.
The function clear_the_line() clears the specified row on the screen. The coding of the function is as follows:
/* Function to clear the Line on the Screen, for Specified Row Number */
void clear_the_line(unsigned int row)
{
unsigned int column;
/* There are 80 Columns in a Row (Line) */
for(column=1;column<=80;column++)
{
gotoxy(column,row);
cprintf(" "); /* Clear With " " */
}
}
Comments on coding:
The function is used to clear the specified row on the screen. The function is called with the number of row, which is to be cleared from the screen.
Page Modified on: 14/01/2022