Глава – 10
Восстановление данных с поврежденной дискеты
Восстановление данных с поврежденной дискеты
Диета — один из самых ненадежных источников хранения данных. Если вы пойдете в любую организацию, которая использует компьютерные системы, и спросите ее сотрудников о проблемах, вызванных гибкими дисками, вы очень часто услышите проблему, что у сотрудника организации были какие-то важные данные на его дискете, и теперь дискета не читается компьютером, и сообщения отображаются примерно так
“Не удается прочитать диск”
“Плохой трек 0
“Недопустимый диск или емкость”
“Диск не отформатирован. Вы хотите отформатировать его сейчас?”
Это повседневная проблема для организаций, использующих компьютерные системы и дискеты. Проблема становится критической, когда вы узнаете, что резервная копия не была сделана или недоступна для данных, которые кажутся потерянными на поврежденной дискете.
Самая большая проблема возникает, когда вы делаете резервную копию на дискете для вашей важной информации, спасательных дисков антивирусной программы для защиты от вирусной атаки или загрузочных записей или других резервных копий (может быть несколько возможностей) в дискету, и когда вы хотите повторно использовать резервную копию с дискеты, возникает ошибка чтения.
В таком состоянии вы можете потерять важную информацию и данные или даже в некоторых случаях, когда вы чувствуете нехватку резервных копий и программы восстановления для информации о загрузке вашего компьютера и спасения от вирусной атаки. программы и т. д., вы можете понести большую потерю данных в виде сбоя ОС из-за отсутствия информации, хранящейся на дискете, которая теперь не читается компьютером.
В таких случаях наиболее важным требованием становится восстановление данных с дискеты, которая была признана вашей компьютерной системой неисправной.
Почему дискета не читается
Наиболее распространенной проблемой, из-за которой на дискете появляются такие сообщения об ошибках, является повреждение ее загрузочной записи DOS (DBR) дискеты, которая помогает компьютеру узнать логическую идентификацию дискеты.
DBR – это небольшая программа, хранящаяся на дорожке 0, головке 0 и секторе 1 и содержащая важную информацию о дискете, такую как:
- Количество байтов на сектор
- Сектор на кластер
- Количество FAT
- Максимальное количество корневых каталогов и т. д.
Поскольку на дискете нет системы логических разделов, на дискете нет MBR. Первый сектор дискеты содержит DBR. Это также основное отличие логической структуры жесткого диска от дискеты.
Когда мы читаем информацию о загрузочном секторе дискеты с помощью любой программы редактирования диска, она будет отображать информацию, как показано на следующем рисунке.
На следующем рисунке показана информация о 512 байтах DBR 1,44 МБ, 3½ Дюймовая дискета.
Если эта информация каким-либо образом повреждена или становится нечитаемой, дискета вызывает такие сообщения об ошибках чтения. Это может быть связано с физическим или логическим повреждением первого сектора диска.
К Логическому повреждению относятся случаи, когда изменяется информация первого сектора дискеты, возникает какой-либо логический поврежденный сектор или DBR дискеты поврежден по любой другой причине.
Предполагается, что физическое повреждение имеет место в случае наличия физических сбойных секторов (означает, что сектор 1 физически поврежден) на первом секторе гибкий диск. Проблема становится более серьезной, когда вы обнаружите, что дискета имеет более одного поврежденного сектора на дорожке 0.
Как восстановить
Поскольку мы узнали обе причины коррупции, я надеюсь, что теперь вы в состоянии понять проблему. Не очень сложно восстановить данные от логического повреждения, однако восстановление от физического повреждения требует чуть больше усилий.
Метод – 1
Сохраните загрузочный образ любой свежей дискеты
Если проблема логична, теперь мы понимаем, как мы можем восстановить данные. Что нам нужно сделать, так это просто получить соответствующую загрузочную запись с другой дискеты того же размера и емкости и вставить ее в первый сектор нечитаемой дискеты. Хотя проблема возникла из-за плохой загрузочной записи, теперь она должна работать.
Эта процедура состоит из двух шагов, следуя которым мы восстанавливаем наши данные с нечитаемой дискеты:
- Создание образа DOS Boot Record хорошей дискеты
- Вставка загрузочного образа в первый сектор нечитаемой дискеты
Создание образа DOS Boot Record хорошей дискеты
Чтобы сохранить образ загрузочной записи свежей дискеты, программа должна выполнить следующие три задачи:
- Чтение ровно первых 512 байт хорошей дискеты
- Проверьте успешность операции чтения (самое важное)
- Сохранить эти 512 байт в файле с указанным именем и путем назначения
Сектор дискеты составляет 512 байт, и необходимо скопировать точное изображение сектора. Самый важный и необходимый шаг в случае любого типа операций, применяемых к дискете, - проверить, была ли операция успешной или нет.
Даже с хорошей и свежей дискетой могут возникнуть проблемы с инициализацией. Поэтому в большинстве случаев, когда операция выполняется на гибких дисках, в первую очередь выполняется инициализация гибких дисков в программировании с помощью операции сброса диска (функция 00 H INT 13H).
Если даже после инициализации недавно вставленная дискета или замененная дискета вызывает какую-либо ошибку чтения, рекомендуется запустить программу еще раз, скорее всего, на этот раз она сработает.
Следующая программа предназначена для выполнения указанных задач. Давайте посмотрим, как это происходит:
/* Сохранить загрузочный образ в файл с новой дискеты */
#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");
/// Инициализировать дисковую систему \\\
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;
}
Комментарии к программному кодированию:
В программном кодировании, приведенном ранее, в основном мы шаг за шагом приступаем к выполнению следующих задач:
- dinfo указывает на структуру diskinfo_t, которая содержит информацию о параметрах, необходимых для операции, выполняемой функцией _bios_disk.
- Поскольку мы хотим прочитать первый сектор диска, расположение сектора будет следующим:
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 |
- Откройте файловый поток с заданным пользователем именем файла и путем для хранения информации о загрузочном образе размером 512 байт. Имя файла и путь хранятся в массиве символов fname.
- Инициализировать дисковую систему с помощью прерывания 13H (функция 00h), где regs.h.ah = 0x00 указывает на функцию 00H, а regs.h.dl = 0x00 используется для дискеты. А int86(0x13, ®s, ®s) вызывает службу прерывания MS-DOS INT 13 H.
- _bios_disk(_DISK_READ, &dinfo) считывает указанный сектор дискеты.
- Возвращенный статус сохраняется в результате, который используется для отображения сообщения об успешной операции или для отображения сообщения об ошибке на экране в случае возникновения какой-либо ошибки.
Вставка загрузочного образа в первый сектор нечитаемой дискеты
Для вставки загрузочного образа из файла в первый сектор нечитаемой дискеты нам необходимо выполнить в нашей программе следующие три основные задачи:
- Чтение точных 512 байт информации о загрузочной записи новой дискеты из ранее сохраненного файла.
- Запишите эту информацию в первый сектор дискеты, который в данный момент не читается.
- Проверьте успешное завершение операции записи (самое важное).
Поскольку сектор дискеты имеет размер 512 байт, необходимо вставить в этот сектор точный загрузочный образ. Самый важный и необходимый шаг в случае любого типа операций, применяемых к дискете, - проверить, была ли операция успешной или нет.
Во время операции может возникнуть проблема с инициализацией дискеты, поэтому вы должны инициализировать диск, сбросив дисковую систему (используя функцию 00H из INT 13H).
Если даже после инициализации недавно вставленная дискета или замененная дискета вызывает какую-либо ошибку чтения, рекомендуется запустить программу еще раз, скорее всего, на этот раз она сработает.
Следующая программа предназначена для выполнения указанных задач. Давайте посмотрим, как это происходит:
/* Загрузить загрузочный образ на нечитаемую дискету */
#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");
/// Инициализировать дисковую систему \\\
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;
}
Комментарии к программному кодированию:
В программном кодировании, приведенном ранее, в основном мы шаг за шагом приступаем к выполнению следующих задач:
- dinfo указывает на структуру diskinfo_t, которая содержит информацию о параметрах, необходимых для операции, выполняемой функцией _bios_disk.
- Поскольку мы собираемся записывать информацию в первый сектор диска, то расположение сектора будет следующим:
- Откройте файл, в котором предыдущая программа сохранила информацию о загрузочном образе размером 512 байт на новой дискете. Имя файла и путь хранятся в массиве символов fname.
- Инициализировать дисковую систему с помощью прерывания 13H (функция 00h), где regs.h.ah = 0x00 указывает на функцию 00H, а regs.h.dl = 0x00 используется для дискеты. А int86(0x13, ®s, ®s) вызывает службу прерывания MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) записывает загрузочную информацию из указанного файла в первый (указанный) сектор дискеты.
- Возвращенный статус сохраняется в результате, который используется для отображения сообщения об успешной операции или для отображения сообщения об ошибке на экране в случае возникновения какой-либо ошибки.
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 |
Давайте сделаем это с помощью одной программы
Надеюсь, теперь вы поняли суть такого типа восстановления данных с дискеты. После этого представим единую программу, которая дает такие же результаты, какие мы получили с помощью ранее рассмотренных двух программ.
С недавно обсуждаемыми программами мы решали следующие задачи:
- Сохраните загрузочную информацию с хорошей дискеты в файл
- Вставьте эту информацию в первый сектор нечитаемой дискеты. Файл, который мы использовали для хранения загрузочного образа, работал как промежуточный мост для соединения операций обеих программ. Но если мы определяем эту загрузочную информацию в самом коде нашей программы, нам не нужно создавать файл, а также нам не нужно читать загрузочную информацию дискеты из файла.
В нашей следующей программе мы сообщаем нашей программе, что она должна записать в первый сектор нечитаемой дискеты, и, таким образом, мы можем избежать двух разных программ, выполняющих одну и ту же задачу, и мы можем восстановить нашу данные так же, как и раньше, из новой одиночной программы.
Таким образом, программа становится проще с меньшим количеством кода, и мы можем снизить вероятность появления ошибок чтения, записи или создания файла. В этой программе мы выполняем следующие четыре важные задачи:
Не думайте, что программа сложна для написания и понимания, если вы видите 512-байтовую шестнадцатеричную информацию dbuf[512]. Позже мы обсудим простой способ записи этой информации для кодирования вашей программы.
- Определить информацию о загрузочной записи DOS в шестнадцатеричной системе, которая будет записываться в первый сектор нечитаемой в данный момент дискеты.
- Сбросьте дисковую систему, чтобы инициализировать дискету (INT 13H, функция 00H).
- Запишите загрузочную запись DOS в первый сектор дискеты.
- Проверить успешное завершение операции и ошибку, если она возникла.
Давайте рассмотрим программу:
/* Одна программа для загрузки загрузочного образа по умолчанию на нечитаемую дискету */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* Загрузочный образ для загрузки в дисковод гибких дисков */
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");
/// Инициализировать дисковую систему \\\
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;
}
В этом программном кодировании, в основном, мы приступаем к выполнению следующих задач шаг за шагом:
- Буфер статических символьных данных dbuf[512] предоставляет информацию размером 512 байт в шестнадцатеричной системе, которая должна быть записана в первый сектор нечитаемой дискеты. dbuf[512] сообщает компьютеру во время операции, какая информация должна быть записана в первый сектор дискеты. (см. следующую программу)
- dinfo указывает на структуру diskinfo_t, которая содержит информацию о параметрах, необходимых для операции, выполняемой функцией _bios_disk.
- Поскольку мы собираемся записывать информацию в первый сектор диска, то расположение сектора будет следующим:
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 |
- Инициализируйте дисковую систему с помощью прерывания 13H (функция 00h), где regs.h.ah = 0x00 указывает на функцию 00H, а regs.h.dl = 0x00 используется для дискеты. А int86(0x13, ®s, ®s) вызывает службу прерывания MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) записывает загрузочную информацию из указанного файла в первый (указанный) сектор дискеты.
Возвращенный статус сохраняется в результате, который используется для отображения сообщения об успешной операции или для отображения сообщения об ошибке на экране в случае возникновения какой-либо ошибки.
Сохранение загрузочного образа в шестнадцатеричных символах для использования в нашей предыдущей программе
Будет очень сложно записать все 512 символов загрузочной записи DOS на дискете вручную в шестнадцатеричной системе без каких-либо ошибок в программе, которую мы недавно обсуждали. Даже если мы сможем написать это точно, это будет сложной и трудоемкой задачей. Приложим немного хитрости, чтобы сохранить данные для буфера данных dbuf[512] в файл.
Мы знаем, что в программировании на C шестнадцатеричные символы представлены с помощью 0x, так что если шестнадцатеричный символ A9 H, мы запишем это в нашей программе на C как 0xA9. Наша следующая программа делает то же самое. Он будет хранить данные, которые нам нужно записать в нашей предыдущей программе, как данные буфера данных dbuf[512].
Что вам нужно сделать, так это просто взять свежую и новую дискету, сделать образ ее DBR и скопировать вывод этой программы из указанного целевого файла и вставить эти данные в вашу программу. Сделайте некоторое форматирование, если это необходимо. Давайте посмотрим, как это работает:
/* Программа для создания загрузочного образа дискеты в шестнадцатеричном формате */
#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);
}
/// Инициализировать дисковую систему \\\
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;
}
Комментарии по кодированию программы:
Таким образом, данные сохраняются в указанном файле. Просто скопируйте данные в свою программу и выполните необходимое форматирование. Вы никогда не должны забывать следующие советы во время процедуры:
- Убедитесь, что работа программы прошла успешно и данные, которые были сохранены в целевом файле, являются соответствующими.
- Вы должны проверить операцию на наличие ожидаемых ошибок.
- Вы должны инициализировать дискету программой перед чтением загрузочного сектора. Для этой цели вы можете использовать функцию 00H из INT 13H.
Метод – 2
Что делать, если метод – 1 не работает?
Если метод – 1 не работает, и нечитаемый диск не позволяет программе перезаписать загрузочную информацию в свой первый сектор, вам следует попробовать второй метод. Причиной неудачи первого метода может быть физическое повреждение первого сектора гибкого диска.
В этом втором методе мы временно скопируем все данные с поверхности нечитаемой дискеты в один файл, а затем вставим это изображение прямо на поверхность другого исправного диска.
Процедура включает следующие два важных шага:
- Посекторное копирование всех данных поверхности гибкого носителя в один файл.
- Вставьте данные, ранее сохраненные в файле, на новую свежую дискету в том же виде, в тех же секторах.
Скопируйте все данные медиаповерхности в один файл
Чтобы сохранить все данные о поверхности носителя или дискеты, программа должна выполнить следующие три задачи:
- Правильно инициализируйте диск с помощью функции 00H INT 13H.
- Прочитайте информацию о поверхности по секторам и сохраните ее в одном файле.
- Проверьте успешность операции чтения (самое важное)
Очень часто возникают проблемы с инициализацией дискеты, что приводит к большому количеству сообщений о неудачном чтении. Поэтому перед операцией чтения-записи диск необходимо инициализировать с помощью программирования.
Самым важным и необходимым шагом в случае любого типа операций, применяемых к дискете, является проверка того, была ли операция успешной или нет.
Если даже после инициализации недавно вставленная дискета или замененная дискета вызывает какую-либо ошибку чтения, рекомендуется запустить программу еще раз, скорее всего, на этот раз она сработает.
Следующая программа предназначена для выполнения указанных задач. Давайте посмотрим, как это происходит:
/* Программа для сохранения данных о физической поверхности дискеты в файл */
#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");
/// Инициализировать дисковую систему \\\
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);
}
}
}
}
Комментарии к программному кодированию:
В приведенном ранее программном кодировании в основном мы шаг за шагом приступаем к выполнению следующих задач:
- Массив символов имя_файла[80] хранит заданный пользователем путь и имя файла, в котором мы собираемся временно хранить данные.
- dinfo указывает на структуру diskinfo_t, которая содержит информацию о параметрах, необходимых для операции, выполняемой функцией _bios_disk.
- Инициализировать дисковую систему с помощью прерывания 13H (функция 00h), где regs.h.ah = 0x00 указывает на функцию 00H, а regs.h.dl = 0x00 используется для дискеты. А int86(0x13, ®s, ®s) вызывает службу прерывания MS-DOS INT 13 H.
- Поскольку мы собираемся прочитать всю информацию о поверхности диска, параметры _bios_disk будут следующими:
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) считывает данные с физической поверхности дискеты из сектора, указанного в dinfo.
- Возвращенный статус сохраняется в результате, который используется для отображения сообщения об успешной операции или для отображения сообщения об ошибке на экране в случае возникновения какой-либо ошибки.
Всегда помните, что размер файла, который содержит образ данных дискеты, должен быть ровно 1 474 560 байт, потому что дискета имеет 80 дорожек (от 0 до 79), 2 стороны или головки (головка 0 и головка 1), каждая дорожка имеет 18 секторов, и каждый сектор содержит 512 байт данных, таким образом
Всего байтов = (Количество дорожек) * (Количество головок) *
(Количество секторов на дорожке) * 512
= 80*2*18*512
= 1,474,560 Bytes
Таким образом, если в каком-либо секторе дискеты возникнет какая-либо ошибка чтения, это изменит размер файла с 1 474 560 байт, что сделает всю информацию полностью или частично бесполезной для целевого диска, на который мы идем. для записи образа диска посекторно из этого файла.
Это так, потому что Компьютер считывает информацию о любом файле на поверхности носителя гибкого диска в пределах диапазона секторов, как это было выделено в его единице распределения. Теперь при изменении секторов данных файлов меняется вся информация о файле.
Думаю над решением ошибки чтения секторов
В случае плохой или нечитаемой дискеты на ее поверхности могут быть настолько плохие участки, что мы не сможем прочитать информацию с поверхности диска.
В этом случае информация об этом секторе(ах) будет пропущена, а изображение дискеты будет искажено даже для других секторов, так как размер файла изображения в этом случае отличается от 1 474 560 байт.
Чтобы сохранить размер файла изображения и вставить остальную информацию о точном расположении секторов на целевом диске, мы записываем некоторую другую информацию от имени исходных данных размером 512 байт, и таким образом мы’ остальную информацию можно будет сохранить, однако восстановление в таком случае может быть частичным.
Если вашей системе также не удается прочитать первый сектор исходной дискеты, после вставки образа на целевую дискету вы должны запустить описанную выше программу, чтобы перезаписать загрузочную запись DOS дискеты.
Давайте посмотрим, как мы можем сделать это с помощью программирования:
#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];
/*Информация о 512 байтах для заполнения пространства поврежденного сектора */
/// Я использовал 512 нулей, чтобы заполнить пространство в 512 байт \\\
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");
/// Инициализировать дисковую систему \\\
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);
/* Если сектор не доступен для чтения, dbuf2 занимает 512 байт. */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
Комментарии к программному кодированию:
В коде программы каждый шаг такой же, как и в предыдущей программе, за исключением буфера данных dbuf2[512], который мы используем для обработки ошибки, генерируемой плохим сектором во время операции чтения с диска и сохранить размер файла изображения.
При этом мы заполняем пространство информацией, которую не удалось прочитать из плохого сектора и теперь мы записываем псевдоинформацию размером 512 байт. чтобы мы могли поддерживать точность образа диска.
Вставьте данные из файла на физическую поверхность новой дискеты:
На этом шаге мы вставляем данные, сохраненные в файле предыдущей программой, на физическую поверхность новой дискеты, сектор за сектором, таким же образом, как мы копировали их в файл.
Программа выполняет следующие основные шаги:
- Откройте файл, в котором мы временно сохранили поверхностные данные нечитаемой дискеты.
- Правильно инициализируйте дисковую систему с помощью функции сброса 00H из INT 13H.
- Запишите информацию о секторах свежей дискеты из файла.
- Отображать статус записи одновременно, чтобы найти или избежать возникновения ошибок.
Исходный код программы приведен ниже. Давайте посмотрим, как это работает:
/* Программа для записи данных в сектора поверхности свежей дискеты из файла, созданного предыдущей программой */
#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);
}
/// Инициализировать дисковую систему \\\
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);
}
}
}
}
Комментарии к программному кодированию:
В программном кодировании, приведенном ранее, в основном мы шаг за шагом приступаем к выполнению следующих задач:
- Символьный массив имя_файла[80] содержит путь и имя файла, в котором мы временно сохранили данные поверхности нечитаемой дискеты.
- dinfo указывает на структуру diskinfo_t, которая содержит информацию о параметрах, необходимых для операции, выполняемой функцией _bios_disk.
- Инициализировать дисковую систему с помощью прерывания 13H (функция 00h), где regs.h.ah = 0x00 указывает на функцию 00H, а regs.h.dl = 0x00 используется для дискеты. А int86(0x13, ®s, ®s) вызывает службу прерывания MS-DOS INT 13 H.
- Поскольку мы собираемся записывать информацию непосредственно в сектора поверхности диска, параметры _bios_disk будут следующими:
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) записывает данные в сектора физической поверхности дискеты, указанные в dinfo.
- Возвращенный статус сохраняется в результате, который используется для отображения сообщения об успешной операции или для отображения сообщения об ошибке на экране в случае возникновения какой-либо ошибки.
Если после метода – 2 ваша новая дискета не работает, вы можете применить метод – 1 на новую дискету, которую вы использовали в качестве целевого диска во время Метода – 2.
Не только это, но и количество попаданий и попыток может варьироваться в зависимости от повреждения диска. Но вам не нужно беспокоиться, если даже после этого вы не получите удовлетворительных результатов.
Вы можете попробовать восстановить файл за файлом или попробовать множество других советов, которые вы узнаете в следующем разделе. Здесь мы реализуем идею сбора информации о файлах из корневых каталогов в нашем программировании для восстановления данных.
Думая о логическом восстановлении удаленных или потерянных данных:
Все предыдущие случаи восстановления, которые мы обсуждали в этой главе, заключались в восстановлении данных в тех случаях, когда мы ожидали, что поврежден только DBR, а сектора на дорожке 0, имеющие FAT1, FAT2 и корневые каталоги доступны для чтения.
Но если проблема связана с повреждением FAT или данные были удалены с диска или вы хотите восстановить данные напрямую, прочитав их информацию из корневого каталога нам нужно прочитать такую информацию, как имя файла, начальный кластер, размер файла. , Атрибут и т. д. из его записи корневого каталога.
Как мы уже говорили о корневом каталоге в предыдущих главах, для каждого файла или каталога существует информация размером 32 байта. Эти 32 байта разделены следующим образом:
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 |
Мы восстанавливаем данные, считывая информацию о файле(ах) из корневого каталога, а затем интегрируем файл в путь назначения и восстанавливаем файл. Наша следующая программа выполняет следующие шаги для восстановления данных:
- Прочитайте записи корневого каталога и отобразите их на экране со всей информацией, такой как имя файла/каталога, расширение файла, начальный размер кластера файлов в байтах.
- Прочитайте информацию о файлах и каталогах в подкаталогах и отобразите их при необходимости.
- Подтвердите имя восстанавливаемого файла и продолжите восстановление.
- Рассчитать информацию CHS (цилиндр, головка и сектор) для указанного файла, который необходимо восстановить.
- Объединить данные файла из области данных на диске и сохранить восстановленный файл в указанном целевом файле по указанному пути.
Эту Программу не волнует, читаема ли загрузочная информация дискеты или нет. Поэтому вы можете восстановить даже удаленные данные с поврежденной дискеты. Посмотрим на код программы:
/* Программа для восстановления данных с дискеты путем чтения файловой информации из корневого каталога */
#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
}
/// Формат экрана информационного дисплея \\\
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("--------------------------------------------");
/* Один сектор за раз. Каждая запись File/DIR занимает 32 байта */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// Найдите имя файла/каталога \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// Найдите расширение \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// Начальный кластер \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Рассчитать размер \\\
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
Помните, что имя файла, начинающееся с s (E5H), означает, что файл был удален, и поэтому первый символ имени файла был заменен на s (см. описание корневого каталога в предыдущих главах).
И вывод программы отображается так:
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 !!!
|
Комментарии по кодированию:
Функция Display_Information предназначена для чтения информации о файле и каталоге и из корневого каталога. В структуре мы читаем 32 байта информации для каждого файла или каталога с root[32].
Массивы целых чисел без знака name[8] и ext[3] предназначены для имени файла или каталога для DOS в формате 8.3 (восемь точек, три). Точно так же один байт предназначен для атрибута и два байта для начального кластера. размер длинного целого числа без знака; заключается в хранении файла размером четыре байта.
Функция _bios_disk считывает сектор, заданный структурой finfo, и в результате сохраняется статус операции.
Из каждой информации размером 512 байт, прочитанной функцией _bios_disk, до конца области корневого каталога мы собираем информацию о файлах и каталогах, хранящихся на диске. и отображать их на экране.
Целое число file_no хранит номер файла или каталога в списке, начиная с 0. Обычно размер корневого каталога составляет 14 секторов, а корневой каталог обычно начинается с Cylinder = 0, Head = 0 и Sector = 2. в случае 1.44MB и 3½ дискета.
Если пользователь указывает символ ‘M’ или ‘м’ в качестве входных данных отображается информация о следующем секторе, если пользователь выбрал ‘R’ или ‘р’ вызываются функции восстановления. Код функции recover() приведен ниже:
/* Функция для запуска восстановления указанного файла */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/* Функция для интеграции указанного файла */
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));
/* Подтвердите имя файла, который нужно восстановить */
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);
/// Извините, вы выбрали каталог \\\
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(start,&cylinder,&head,§or);
/* Показать содержимое каталога */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* Рассчитать для информации CHS */
calculate(start,&cylinder,&head,§or);
/* Интегрировать файл */
integrate(size,cylinder,head,sector);
}
}
Комментарии по кодированию:
Функция recover() предназначена для получения пользовательского ввода для запуска восстановления. Номер файла, введенный пользователем для восстановления файла, сохраняется в file_no.
Если введенный номер относится к элементу каталога, Display_Information() показывает содержимое этого каталога, в противном случае на экране отображается имя файла и расширение номера файла номер_файла, подтверждающие, что файл подлежит восстановлению.
Чтобы восстановить указанный файл, внутри функции вызываются функции вычислить() и интегрировать(). Код функции calculate() приведен ниже:
/* Функция для расчета геометрии CHS для восстановления */
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;
}
/// Отображение CHS файла, который нужно восстановить \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
Комментарии по кодированию:
Функция calculate() предназначена для вычисления информации о цилиндре, головке и секторе для восстанавливаемого файла. После расчета на экране отображаются номера цилиндра, головки и сектора.
Ниже приведен код функции интегрировать():
/* Объединить файл и сохранить восстановленный файл по указанному пути и имени файла */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* Функция проверки сектора на наличие ошибок */
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;
/* Введите путь назначения и имя файла, чтобы сохранить восстановленный файл */
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(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 */
}
/* Если все в порядке, интегрируйте и напишите */
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);
}
Комментарии по кодированию:
Функция integrate() является фактическим модулем выполнения восстановления указанного пользователем файла в этой программе восстановления.
Имя файла с целевым путем для сохранения восстановленного файла хранится в указателе символов *Filename_with_path. Если при открытии целевого файла возникает какая-либо ошибка, отображается сообщение об ошибке, и пользователю снова предлагается ввести место назначения.
Функция _bios_disk(_DISK_READ, &dinfo); считывает данные файла из области данных диска посекторно, заданные структурой dinfo и хранящиеся в буфере данных buf . Эти данные размером 512 байт записываются в файл назначения. Это повторяется до тех пор, пока не будет интегрирован весь файл.
Функция status=verify_the_sector (цилиндр,головка,сектор); проверяет сектор для чтения. Если статус = 10, это означает плохой (0xA) сектор. Кодирование функции приведено ниже:
/// Проверьте сектор. (данные здесь не передаются) \\\
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);
}
Комментарии по кодированию:
Функция verify_the_sector() проверяет сектор для чтения функцией _bios_disk() и возвращает статус операции. Функция использует INT 13H и функцию 4H для проверки сектора.
*buf — буфер данных, 0x04 — номер функции, указанный в in.h.ah = 0x04; и вх.ч.вл = 1; инструктирует проверять один сектор за раз. в.х.дл = 0x00; используется для номера дисковода для гибких дисков. A:, c, h и s — это номера цилиндров, головок и секторов.
Функция int86x() используется для вызова INT 13H (функция 4H) с значениями регистра сегмента. Статус операции возвращается целочисленным статусом.
Функция clear_the_line() очищает указанную строку на экране. Кодирование функции выглядит следующим образом:
/* Функция очистки строки на экране для указанного номера строки */
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 " " */
}
}
Комментарии по кодированию:
Эта функция используется для очистки указанной строки на экране. Функция вызывается с номером строки, которую нужно убрать с экрана.
Страница изменена: 16/03/2022