Capítulo – 10
Recuperação de dados de disquete corrompido
Recuperação de dados de disquete corrompido
O disquete é uma das fontes menos confiáveis de armazenamento de dados. Se você for a qualquer organização que utiliza sistemas de computador e perguntar aos seus funcionários sobre os problemas gerados pelos disquetes, muito comumente ouvirá o problema de que o funcionário da organização estava tendo alguns dados importantes em seu disquete e agora o disquete não está legível pelo computador e uma mensagem é exibida como,
“Não é possível ler o disco”
“Faixa 0 ruim”
“Unidade ou capacidade inválida”
“O disco não está formatado. Deseja formatá-lo agora?”
Este é o problema cotidiano das organizações que utilizam sistemas de computador e disquetes. O problema se torna crítico quando você descobre que não foi feito nenhum backup ou backup disponível para os dados que parecem estar perdidos no disquete corrompido.
O maior inferno do problema deve vir quando você faz backup no disquete para suas informações críticas, discos de resgate do programa antivírus para superar o ataque de vírus ou registros de inicialização ou outros backups (pode haver várias possibilidades) em um disquete e quando você deseja reutilizar o backup do disquete, ocorre um erro de leitura.
Em tal condição você está prestes a perder suas informações e dados importantes ou até mesmo em alguns casos quando você sente a falta de backups e programa de recuperação para suas informações de inicialização do computador e resgate de ataque de vírus programas etc., você pode sofrer uma grande perda de dados em forma de falha do sistema operacional devido à falta de informações, armazenadas no disquete que não são legíveis pelo computador agora.
Em tais casos, torna-se o requisito mais importante recuperar os dados do disquete que foi declarado inválido pelo seu sistema de computador.
Por que o disquete não é legível
O problema mais comum que faz com que um disquete mostre esse tipo de mensagem de erro é a corrupção do registro de inicialização do DOS (DBR) do disquete, o que ajuda o computador a saber a identificação lógica do disquete.
O DBR é um pequeno programa armazenado na trilha 0, head 0 e setor 1 e contendo informações importantes sobre o disquete como:
- Número de bytes por setor
- Setor por cluster
- Número de FATs
- Número máximo de diretórios raiz etc.
Como o disquete não possui sistema de partição lógica, não há MBR disponível no disquete. O Primeiro Setor de Disquetes detém o DBR. Esta também é a principal diferença para comparar a estrutura lógica do disco rígido com um disquete.
Quando lemos as informações do setor de inicialização de um disquete com a ajuda de qualquer programa de edição de disco, ele exibirá informações como na figura a seguir.
A figura a seguir mostra as informações de 512 Bytes do DBR de um 1.44MB, 3½ Disquete em polegadas.
Se essas informações estiverem corrompidas ou se tornarem ilegíveis, o disquete causará essas mensagens de erro de leitura. Pode ser devido à corrupção física ou lógica do primeiro setor do disco.
A Corrupção lógica inclui os casos em que as informações do primeiro setor do disquete são alteradas, ocorre algum setor lógico defeituoso ou o DBR do disquete está corrompido devido a qualquer outro motivo.
A corrupção física deve ocorrer no caso de, se houver setores defeituosos físicos (significa que o setor 1 está fisicamente danificado) no primeiro setor do disquete. O problema se torna mais sério quando você descobre que o disquete está tendo mais de um setor defeituoso na faixa 0.
Como recuperar
Como aprendemos as duas causas da corrupção, espero que agora você consiga entender o problema. Não é muito difícil recuperar os dados da corrupção lógica, no entanto, a recuperação da corrupção física precisa de um pouco mais de esforço.
Método – 1
Armazene a imagem de inicialização de qualquer disquete novo
Se o problema for lógico, agora entendemos como podemos recuperar os dados. O que precisamos fazer é apenas obter o registro de inicialização apropriado de outro disquete de mesmo tamanho e capacidade e colá-lo no primeiro setor do disquete ilegível. Embora o problema tenha sido criado devido ao registro de inicialização ruim, ele deve funcionar agora.
Há duas etapas envolvidas neste procedimento, seguindo as quais estamos recuperando nossos dados de um disquete ilegível:
- Fazendo a imagem do DOS Boot Record de um bom disquete
- Colando a imagem de inicialização no primeiro setor do disquete ilegível
Fazendo a imagem do DOS Boot Record de um bom disquete
Para armazenar a imagem do registro de inicialização do disquete novo, o programa deve realizar as três tarefas a seguir:
- Leia exatamente os primeiros 512 bytes do disquete bom
- Verifique se a operação de leitura foi bem-sucedida (mais importante)
- Armazene esses 512 bytes no nome do arquivo e no caminho de destino especificados
O setor do disquete é de 512 bytes e é necessário copiar a imagem exata do setor. É o passo mais importante e necessário no caso de qualquer tipo de operação aplicada no disquete verificar se a operação foi bem sucedida ou não.
Pode haver algum problema de inicialização mesmo com o disquete bom e novo. É por isso que na maioria dos casos em que a operação é realizada em disquetes, primeiramente a inicialização dos disquetes é realizada na programação com a operação de reset do disco (Função 00 H de INT 13H).
Se mesmo após a inicialização o disquete inserido recentemente ou o disquete alterado causar algum erro de leitura, você é aconselhado a executar o programa novamente, provavelmente ele funcionará desta vez.
O programa a seguir é para executar essas tarefas especificadas. Vejamos como procede:
/* Armazene a imagem de inicialização em um arquivo de um novo disquete */
#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");
/// Inicialize o sistema de disco \\\
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;
}
Comentários sobre a codificação do programa:
Na codificação do programa dada anteriormente, basicamente estamos realizando as seguintes tarefas passo a passo:
- dinfo aponta para a estrutura diskinfo_t que contém as informações dos parâmetros requeridos pela operação realizada pela função _bios_disk.
- Como queremos ler o primeiro setor do disco, a localização do setor será a seguinte:
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 |
- Abra um fluxo de arquivo de nome de arquivo e caminho determinado pelo usuário para armazenar as informações da imagem de inicialização de 512 bytes exatos. O nome e o caminho do arquivo são armazenados na matriz de caracteres fname.
- Inicie o sistema de disco usando a interrupção 13H (função 00h) onde regs.h.ah = 0x00 aponta para a função 00 H e regs.h.dl = 0x00 é usado para a: disquete. E int86(0x13, ®s, ®s) invoca o serviço de interrupção do MS-DOS INT 13 H.
- _bios_disk(_DISK_READ, &dinfo) lê o setor especificado do disquete.
- O status retornado é armazenado em resultado que é usado para exibir a mensagem de operação bem-sucedida ou para exibir uma mensagem de erro na tela se ocorrer algum erro.
Colando a imagem de inicialização no primeiro setor do disquete ilegível
Para colar a imagem de inicialização do arquivo no primeiro setor do disquete ilegível, temos que executar as três tarefas principais a seguir em nosso programa:
- Leia as informações exatas de 512 bytes do registro de inicialização do novo disquete do arquivo salvo anteriormente.
- Grave esta informação no primeiro setor do disquete que está ilegível no momento.
- Verifique se a operação de gravação foi concluída com êxito (mais importante).
Como o setor do disquete é de 512 bytes e é necessário colar a imagem de boot exata no setor. É o passo mais importante e necessário no caso de qualquer tipo de operação aplicada no disquete verificar se a operação foi bem sucedida ou não.
Pode haver algum problema de inicialização com o disquete durante a operação, portanto, você deve inicializar o disco reiniciando o sistema de disco(usando a função 00H de INT 13H).
Se mesmo após a inicialização o disquete inserido recentemente ou o disquete alterado causar algum erro de leitura, você é aconselhado a executar o programa novamente, provavelmente ele funcionará desta vez.
O programa a seguir é para executar essas tarefas especificadas. Vejamos como procede:
/* Carregar imagem de inicialização para o disquete ilegível */
#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");
/// Inicialize o sistema de disco \\\
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;
}
Comentários sobre a codificação do programa:
Na codificação do programa dada anteriormente, basicamente estamos realizando as seguintes tarefas passo a passo:
- dinfo aponta para a estrutura diskinfo_t que contém as informações dos parâmetros requeridos pela operação realizada pela função _bios_disk.
- Como vamos escrever as informações no primeiro setor do disco, a localização do setor será a seguinte:
- Abra o arquivo no qual as informações da imagem de inicialização de 512 bytes de um novo disquete foram armazenadas pelo programa anterior. O nome e o caminho do arquivo são armazenados na matriz de caracteres fname.
- Inicie o sistema de disco usando a interrupção 13H (função 00h) onde regs.h.ah = 0x00 aponta para a função 00 H e regs.h.dl = 0x00 é usado para a: disquete. E int86(0x13, ®s, ®s) invoca o serviço de interrupção do MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) grava as informações de inicialização do arquivo especificado no primeiro setor (especificado) do disquete.
- O status retornado é armazenado em resultado que é usado para exibir a mensagem de operação bem-sucedida ou para exibir uma mensagem de erro na tela se ocorrer algum erro.
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 |
Vamos fazer isso com um único programa
Espero que agora você tenha entendido o conceito por trás desse tipo de recuperação de dados do disquete. Depois disso, vamos imaginar um único programa que dê os mesmos resultados que obtivemos com a ajuda de dois programas discutidos anteriormente.
Estávamos realizando as seguintes tarefas com os programas discutidos recentemente:
- Armazene as informações de inicialização de um bom disquete em um arquivo
- Cole esta informação no primeiro setor do disquete atualmente ilegível O arquivo que estávamos usando para armazenar a imagem de boot estava funcionando como ponte intermediária para conectar as operações de ambos os programas. Mas se definirmos essas informações de inicialização em nossa própria codificação de programa, não precisamos criar um arquivo, assim como não precisamos ler as informações de inicialização do disquete a partir do arquivo.
No nosso próximo programa estamos dizendo ao nosso programa sobre o que ele tem que escrever no primeiro setor do disquete ilegível e assim podemos evitar que dois programas diferentes façam a mesma tarefa e podemos recuperar nosso dados da mesma forma que antes no novo programa único.
O programa torna-se assim simples com menos codificação e podemos reduzir a probabilidade de ocorrência de erros de leitura, escrita ou criação de arquivos. Estamos realizando as quatro tarefas importantes a seguir neste programa:
Não pense que o programa é difícil de escrever e entender vendo as informações hexadecimais de 512 bytes de dbuf[512]. Mais tarde, discutiremos a maneira fácil de escrever essas informações para a codificação do seu programa.
- Defina as informações do registro de inicialização do DOS no sistema hexadecimal para serem gravadas no primeiro setor do disquete ilegível no momento.
- Reinicialize o sistema de disco para inicializar o disquete (INT 13H, Função 00H).
- Grave o registro de inicialização do DOS no primeiro setor do disquete
- Verifique a conclusão bem-sucedida da operação e o erro, se ocorrer.
Vamos examinar o programa:
/* Programa único para carregar imagem de inicialização padrão para disquete ilegível */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* Imagem de inicialização a ser carregada na unidade de disquete*/
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");
/// Inicialize o sistema de disco \\\
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;
}
Nesta codificação de programa, basicamente estamos realizando as seguintes tarefas passo a passo:
- O buffer de dados de caracteres estáticos dbuf[512] é fornecido com a informação de 512 bytes em sistema hexadecimal, que deve ser escrito no primeiro setor do disquete ilegível. dbuf[512] informa ao computador durante a operação quais informações devem ser gravadas no primeiro setor do disquete. (Veja o próximo programa)
- dinfo aponta para a estrutura diskinfo_t que contém as informações dos parâmetros requeridos pela operação realizada pela função _bios_disk.
- Como vamos escrever as informações no primeiro setor do disco, a localização do setor será a seguinte:
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 |
- Inicialize o sistema de disco usando a interrupção 13H (função 00h) onde regs.h.ah = 0x00 aponta para a função 00 H e regs.h.dl = 0x00 é usado para a: disquete. E int86(0x13, ®s, ®s) invoca o serviço de interrupção do MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) grava as informações de inicialização do arquivo especificado no primeiro setor (especificado) do disquete.
O status retornado é armazenado em resultado que é usado para exibir a mensagem de operação bem-sucedida ou para exibir uma mensagem de erro na tela se ocorrer algum erro.
Armazenando a imagem de inicialização em caracteres hexadecimais para usar em nosso programa anterior
Será um trabalho muito difícil escrever todos os 512 caracteres do DOS Boot Record do disquete manualmente em sistema hexadecimal sem nenhum erro no programa que discutimos recentemente. Se pudermos escrevê-lo com precisão, será uma tarefa difícil e demorada para fazer isso. Vamos usar uma mente complicada para armazenar os dados do buffer de dados dbuf[512] em um arquivo.
Sabemos que na programação C os caracteres hexadecimais são representados com 0x de tal forma que se o caractere hexadecimal for A9 H, devemos escrever isso em nosso programa C como 0xA9. Nosso próximo programa está fazendo o mesmo. Ele armazenará os dados que precisamos escrever em nosso programa anterior, como os dados do buffer de dados dbuf[512].
O que você precisa fazer é apenas pegar um novo e novo disquete para fazer a imagem de seu DBR e copiar a saída deste programa do arquivo de destino especificado e colar esses dados em seu programa. Faça alguma formatação, se necessário. Vejamos como funciona:
/* Programa para fazer a imagem de boot do disquete em caractere HEX */
#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);
}
/// Inicialize o sistema de disco \\\
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;
}
Comentários sobre a codificação do programa:
Assim, os dados são armazenados no arquivo especificado. Basta copiar os dados para o seu programa e fazer a formatação necessária. Você nunca deve esquecer as seguintes dicas ao longo do procedimento:
- Certifique-se de que a operação do programa foi bem-sucedida e que os dados armazenados no arquivo de destino são os apropriados.
- Você deve verificar a operação até a ocorrência de erros esperados.
- Você deve inicializar o disquete com o programa antes de ler seu setor de inicialização. Você pode usar a função 00H de INT 13H para esta finalidade.
Método – 2
O que fazer se o Método – 1 não funciona?
Se o Método – 1 não funciona e o disco ilegível não está permitindo que o programa reescreva as informações de inicialização em seu primeiro setor, você deve tentar este segundo método. A razão por trás da falha do Primeiro Método pode ser a corrupção física do primeiro setor do disquete.
Neste segundo método vamos copiar todos os dados da superfície do disquete ilegível para um único arquivo temporariamente e depois colaremos esta imagem diretamente na superfície de outro disco bom.
O procedimento envolve as duas etapas importantes a seguir:
- Setor por setor Copie todos os dados da superfície da mídia do disquete para um único arquivo temporariamente.
- Cole os dados armazenados anteriormente no arquivo, em um novo disquete como está, nos mesmos setores.
Copie todos os dados da superfície de mídia para um único arquivo
Para armazenar todos os dados da superfície de mídia do disquete, o programa deve realizar as três tarefas a seguir:
- Inicialize o disco corretamente com a ajuda da função 00H de INT 13H.
- Leia as informações Setor por Setor da superfície e armazene em um único arquivo.
- Verifique se a operação de leitura foi bem-sucedida (mais importante)
É muito comum ter algum problema de inicialização com um disquete que leva a muitas mensagens de leitura malsucedidas. É por isso que o disco deve ser inicializado antes da operação de leitura e gravação com a ajuda da programação.
É a etapa mais importante e necessária no caso de qualquer tipo de operação aplicada no disquete verificar se a operação foi bem-sucedida ou não.
Se mesmo após a inicialização o disquete inserido recentemente ou o disquete alterado causar algum erro de leitura, é aconselhável executar o programa novamente, provavelmente ele funcionará desta vez.
O programa a seguir é para executar essas tarefas especificadas. Vamos ver como ele procede:
/* Programa para armazenar os dados da superfície física do disquete em um arquivo */
#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");
/// Inicialize o sistema de disco \\\
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);
}
}
}
}
Comentários sobre a codificação do programa:
Na codificação do programa dada anteriormente, basicamente estamos realizando as seguintes tarefas passo a passo:
- A matriz de caracteres filename[80] armazena o caminho definido pelo usuário e o nome do arquivo no qual armazenaremos os dados temporariamente.
- dinfo aponta para a estrutura diskinfo_t que contém as informações dos parâmetros requeridos pela operação realizada pela função _bios_disk.
- Inicie o sistema de disco usando a interrupção 13H (função 00h) onde regs.h.ah = 0x00 aponta para a função 00 H e regs.h.dl = 0x00 é usado para a: disquete. E int86(0x13, ®s, ®s) invoca o serviço de interrupção do MS-DOS INT 13 H.
- Como vamos ler todas as informações da superfície do disco, os parâmetros de _bios_disk serão os seguintes:
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) lê os dados da superfície física do disquete do setor especificado por dinfo.
- O status retornado é armazenado em resultado que é usado para exibir a mensagem de operação bem-sucedida ou para exibir uma mensagem de erro na tela se ocorrer algum erro.
Lembre-se sempre que o tamanho do arquivo que contém a imagem dos dados do disquete deve ser exato de 1.474.560 bytes, pois o disquete possui 80 trilhas (0 a 79), 2 lados ou cabeças (cabeça 0 e cabeça 1), cada trilha tem 18 setores nele e cada setor contém os 512 bytes de dados, assim
Total bytes = (Number of tracks) * (Number of Heads) *
(Number of Sectors per Track) * 512
= 80*2*18*512
= 1,474,560 Bytes
Assim, se houver algum erro na leitura em algum setor do disquete, ele alterará o tamanho do arquivo de 1.474.560 Bytes, o que tornará toda a informação total ou parcialmente inútil para o disco de destino em que estamos indo para gravar a imagem de disco setor por setor deste arquivo.
Isso ocorre porque o Computador lê as informações de qualquer arquivo na superfície da mídia do disquete dentro do intervalo do setor conforme foi alocado em sua unidade de alocação. Agora, se os setores dos dados dos arquivos forem alterados, as informações completas do arquivo serão alteradas.
Pensando na solução do erro de leitura do(s) setor(es)
É possível que um disquete ruim ou ilegível tenha uma área tão ruim em sua superfície que não possamos ler as informações da superfície do disco.
Nesta condição a informação deste(s) setor(es) será(ão) ignorada(s) e a imagem do disquete será distorcida mesmo para os demais setores, pois o tamanho do arquivo de imagem neste caso difere de 1.474.560 Bytes.
Para manter o tamanho do arquivo de imagem e colar o restante das informações nas localizações exatas do setor no disco de destino, escrevemos algumas outras informações em nome dos dados originais de 512 bytes e, dessa forma, nós’ Você será capaz de salvar o restante das informações, porém a recuperação nesse caso pode ser a recuperação parcial.
Se o seu sistema também não conseguir ler o primeiro setor do disquete de origem, após colar a imagem no disquete de destino, você deve executar o programa descrito anteriormente, para reescrever o Registro de inicialização do DOS do disquete .
Vamos ver como podemos fazer isso programando:
#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];
/*Informação de 512 Bytes para preencher o espaço de Bad Sector */
/// Usei 512 zeros para preencher o espaço de 512 bytes \\\
caractere estático 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");
/// Inicialize o sistema de disco \\\
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);
/* Se o setor não for legível, ocupe 512 bytes por dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
Comentários sobre a codificação do programa:
Na codificação do programa, cada passo é o mesmo do programa anterior, exceto o buffer de dados dbuf2[512], que estamos usando para lidar com o erro gerado por setor defeituoso durante a operação de leitura de disco e para manter o tamanho do arquivo de imagem.
Ao fazer isso, estamos preenchendo o espaço das informações, que não conseguimos ler do setor defeituoso e agora estamos escrevendo as pseudoinformações de 512 bytes para que possamos manter a precisão da imagem do disco.
Cole os dados do arquivo na superfície física do novo disquete:
Nesta etapa, colamos os dados armazenados no arquivo pelo programa anterior, na superfície física do novo disquete, setor por setor, da mesma forma que copiamos para o arquivo.
O programa prossegue com as seguintes etapas principais:
- Abra o arquivo no qual armazenamos os dados de superfície do disquete ilegível temporariamente.
- Inicie o sistema de disco corretamente pela função de redefinição 00H de INT 13H.
- Escreva as informações sobre os setores do novo disquete do arquivo.
- Exiba o status de gravação simultaneamente para localizar ou evitar a ocorrência de erros.
O código-fonte do programa foi fornecido abaixo. Vamos examinar como funciona:
/* Programa para escrever os dados nos setores da superfície do disquete novo do arquivo, criado pelo programa anterior */
#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);
}
/// Inicialize o sistema de disco \\\
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);
}
}
}
}
Comentários sobre a codificação do programa:
Na codificação do programa dada anteriormente, basicamente estamos realizando as seguintes tarefas passo a passo:
- O array de caracteres filename[80] contém o caminho e o nome do arquivo no qual armazenamos temporariamente os dados da superfície do disquete ilegível.
- dinfo aponta para a estrutura diskinfo_t que contém as informações dos parâmetros requeridos pela operação realizada pela função _bios_disk.
- Inicie o sistema de disco usando a interrupção 13H (função 00h) onde regs.h.ah = 0x00 aponta para a função 00 H e regs.h.dl = 0x00 é usado para a: disquete. E int86(0x13, ®s, ®s) invoca o serviço de interrupção do MS-DOS INT 13 H.
- Como vamos escrever as informações diretamente nos setores da superfície do disco, os parâmetros de _bios_disk serão os seguintes:
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) grava os dados nos setores da superfície física do disquete, especificado por dinfo.
- O status retornado é armazenado em resultado que é usado para exibir a mensagem de operação bem-sucedida ou para exibir uma mensagem de erro na tela se ocorrer algum erro.
Se após o Método – 2 seu novo disquete não funcionar, você pode aplicar o Método – 1 em seu novo disquete, que você usou como disco de destino durante o Método – 2.
Não apenas isso, mas também o número de ocorrências e tentativas podem variar dependendo da corrupção do disco. Mas você não precisa se preocupar se mesmo depois de não obter os resultados satisfatórios.
Você pode tentar recuperar arquivo por arquivo ou tentar muitas outras dicas que você aprenderá a seguir. Aqui vamos implementar a ideia de coletar as informações dos arquivos dos Diretórios Raiz, em nossa programação para recuperar os dados.
Pensando em recuperação lógica para dados excluídos ou perdidos:
Todos os casos anteriores que discutimos neste capítulo para recuperação foram para recuperar os dados nos casos em que esperávamos que apenas o DBR estivesse corrompido e os setores na faixa 0, tendo FAT1, FAT2 e diretórios raiz são legíveis.
Mas se o problema for devido à corrupção do FAT ou os dados foram excluídos do disco ou você deseja recuperar os dados diretamente lendo suas informações do diretório raiz, precisamos ler as informações como Nome do arquivo, cluster inicial, tamanho do arquivo , Atributo etc. de sua entrada de diretório raiz.
Como já discutimos sobre o Diretório Raiz em capítulos anteriores, há a informação de 32 Bytes para cada arquivo ou diretório. Esses 32 Bytes são divididos da seguinte forma:
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 |
Nós recuperamos os dados lendo as informações do(s) arquivo(s) do Diretório raiz e, em seguida, integramos o arquivo ao caminho de destino e recuperamos o arquivo. Nosso próximo programa executa as seguintes etapas para recuperar os dados:
- Leia as entradas do diretório raiz e exiba-as na tela com todas as informações, como nome do arquivo/diretório, extensão do arquivo, tamanho do cluster inicial dos arquivos em bytes.
- Leia as informações sobre arquivos e diretórios nos subdiretórios e exiba-os, se necessário.
- Confirme o nome do arquivo a ser recuperado e continue a recuperação.
- Calcule as informações de CHS (Cilindro, Cabeça e Setor) para o arquivo especificado a ser recuperado.
- Integre os dados do arquivo da área de dados do disco e salve o arquivo recuperado no nome do arquivo de destino especificado no caminho especificado.
Este Programa não se importa se as informações de inicialização do disquete são legíveis ou não. Portanto, você também pode recuperar dados excluídos do disquete corrompido. Vejamos a codificação do programa:
/* Programa para recuperar os dados do disquete lendo as informações do arquivo do diretório raiz */
#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
}
/// Formato da tela de exibição de informações\\\
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("--------------------------------------------");
/* Um setor de cada vez. Cada entrada de arquivo/dir leva 32 bytes */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// Encontre o nome do arquivo/dir \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// Encontre a extensão \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// Agrupamento inicial \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Calcule o tamanho \\\
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
Lembre-se de que o nome do arquivo que começa com s (E5H) representa que o arquivo foi excluído e, portanto, o primeiro caractere do nome do arquivo foi substituído por s (consulte a descrição do diretório raiz nos capítulos anteriores).
E a saída do programa é exibida assim:
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 !!!
|
Comentários sobre a codificação:
A função Display_Information é ler as informações do arquivo e do diretório e do diretório raiz. Na Estrutura estamos lendo as informações de 32 bytes para cada arquivo ou diretório com root[32].
Os arrays de inteiros não assinados name[8] e ext[3] são para nome de arquivo ou diretório para DOS no formato 8.3 (oito pontos e três). Da mesma forma, um byte é para atributo e dois bytes para iniciar o cluster. tamanho inteiro sem sinal longo; é armazenar o tamanho do arquivo de quatro bytes.
A função _bios_disk lê o setor, especificado pela estrutura finfo e o status da operação é armazenado em result.
A partir de todas as informações de 512 bytes lidas pela função _bios_disk, até o término da área do diretório raiz, coletamos as informações dos arquivos e diretórios armazenados no disco e exibi-los na tela.
O inteiro file_no armazena o número do arquivo ou diretório na lista, começando em 0. Geralmente o tamanho do diretório raiz é de 14 setores e o diretório raiz geralmente começa em Cylinder =0, Head = 0 e Sector =2 no caso de 1.44MB e 3½ disquete.
Se o usuário der o caractere ‘M’ ou ‘m’ como entrada, a informação do próximo setor é exibida se a escolha do usuário for ‘R’ ou ‘r’ as funções de recuperação são chamadas. A codificação da função recover() foi fornecida abaixo:
/* Função para iniciar a recuperação do arquivo especificado */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/* Função para integrar o arquivo especificado */
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));
/* Confirme o nome do arquivo a ser recuperado */
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);
/// Desculpe, você selecionou um diretório \\\
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')
{
/* Calcular geometria */
calculate(start,&cylinder,&head,§or);
/* Exibir conteúdo do diretório */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* Calcular para informações CHS */
calculate(start,&cylinder,&head,§or);
/* Integrar o arquivo */
integrate(size,cylinder,head,sector);
}
}
Comentários sobre a codificação:
A função recover() é obter a entrada do usuário para iniciar a recuperação. O número do arquivo dado como entrada pelo usuário para recuperar o arquivo, é armazenado em arquivo_no.
Se o número inserido for para a entrada do diretório, Display_Information() mostra o conteúdo desse diretório, senão O nome do arquivo e a extensão do número do arquivo file_no são exibidos na tela para confirmar o arquivo a ser recuperado.
Para recuperar o arquivo especificado, as funções calculate() e integrate() são chamadas dentro da função. A codificação da função calculate() foi dada abaixo:
/* Função para calcular a geometria CHS para a recuperação */
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;
}
/// Exibir o CHS do arquivo a ser recuperado \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
Comentários sobre a codificação:
A função calculate() é para calcular as informações do cilindro, cabeçote e setor para o arquivo a ser recuperado. Após o cálculo, os números do Cilindro, Cabeça e Setor são exibidos na tela.
A codificação para a função integr() foi dada abaixo:
/* Integre o arquivo e salve o arquivo recuperado no caminho e no nome do arquivo especificados */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* Função para verificar o setor quanto a erros */
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;
/* Digite o caminho de destino e o nome do arquivo para salvar o arquivo recuperado */
gotoxy(2,24);
cprintf("Enter Path and Filename to recover the file: ");
fflush(stdin);
gets(Filename_with_path);
fp=fopen(Filename_with_path,"wb");
/* Se ocorrer um erro, exiba a mensagem de erro e obtenha o caminho de entrada e o nome do arquivo novamente */
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 */
}
/* Se tudo estiver bem, Integre e escreva */
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);
}
Comentários sobre a codificação:
A função integrate() é o módulo real de realizar a recuperação do arquivo especificado pelo usuário, neste programa de recuperação.
O nome do arquivo com o caminho de destino para armazenar o arquivo recuperado é armazenado no ponteiro de caractere *Filename_with_path. Se houver algum erro na abertura do arquivo de destino, uma mensagem de erro será exibida e o usuário será solicitado novamente a inserir o destino.
A função _bios_disk(_DISK_READ, &dinfo); lê os dados do arquivo da área de dados do disco setor por setor, especificado pela estrutura dinfo e armazenado no buffer de dados buf . Esses dados de 512 bytes são gravados no arquivo de destino. Isso é repetido até que o arquivo completo seja integrado.
A função status=verify_the_sector (cilindro, cabeçote, setor); verifica o setor a ser lido. Se o status = 10, representa um setor ruim (0xA). A codificação da função foi dada abaixo:
/// Verifique o setor. (Nenhum dado é transferido aqui) \\\
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);
}
Comentários sobre a codificação:
A função Verify_the_sector(), verifica o setor a ser lido pela função _bios_disk() e retorna o status da operação. A função usa INT 13H e função 4H para verificar o setor.
*buf é o buffer de dados, 0x04 é o número da função especificada por in.h.ah = 0x04; e in.h.al = 1; instrui a verificar um setor de cada vez. in.h.dl = 0x00; é usado para o número da unidade de disquete A:, c,h e s são números de Cilindro, Cabeça e Setor.
A função int86x() é usada para invocar INT 13H (função 4H) com valores de registro de segmento. O status da operação é retornado pelo status inteiro.
A função clear_the_line() limpa a linha especificada na tela. A codificação da função é a seguinte:
/* Função para limpar a linha na tela, para o número de linha especificado */
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 " " */
}
}
Comentários sobre a codificação:
A função é usada para limpar a linha especificada na tela. A função é chamada com o número da linha, que deve ser apagada da tela.
Página modificada em: 14/01/2022