Capítulo – 10
Recuperación de datos de disquete corrupto
Recuperación de datos de disquete corrupto
El disquete es una de las fuentes menos confiables para el almacenamiento de datos. Si usted va a cualquier organización que utiliza sistemas informáticos y pregunta a sus empleados sobre los problemas que generan los disquetes, muy comúnmente escuchará el problema de que el empleado de la organización tenía algunos datos importantes en su disquete y ahora el disquete no está. legible por la computadora y se muestra un mensaje algo como,
"No se puede leer el disco"
"Pista 0 mala"
“Unidad o capacidad no válida”
“El disco no está formateado. ¿Desea formatearlo ahora?”
Este es el problema cotidiano de las organizaciones que utilizan sistemas informáticos y disquetes. El problema se vuelve crítico cuando se da cuenta de que no se realizó ninguna copia de seguridad o de que no hubo ninguna copia de seguridad disponible para los datos que parecen haberse perdido en el disquete dañado.
Se supone que el problema más grave surge cuando realiza una copia de seguridad en el disquete de su información crítica, discos de rescate del programa antivirus para superar el ataque de virus o registros de arranque u otras copias de seguridad (puede haber varias posibilidades) en un disquete y cuando desea reutilizar la copia de seguridad del disquete da un error de lectura.
En tal condición, está a punto de perder su información y datos importantes o incluso en algunos casos cuando siente la falta de copias de seguridad y programa de recuperación para la información de arranque de su computadora y rescate de ataques de virus programas etc., puede sufrir una gran pérdida de datos en forma de bloqueo del sistema operativo debido a la falta de información almacenada en el disquete que la computadora no puede leer ahora.
En tales casos, se convierte en el requisito más importante para recuperar los datos del disquete que ha sido declarado defectuoso por su sistema informático.
Por qué no se puede leer el disquete
El problema más común que hace que un disquete muestre este tipo de mensajes de error es la corrupción de su registro de arranque DOS (DBR) del disquete, lo que ayuda a la computadora a conocer la identificación lógica del disquete.
El DBR es un pequeño programa almacenado en la pista 0, encabezado 0 y sector 1 y que contiene información importante sobre el disquete, como:
- Número de bytes por sector
- Sector por clúster
- Número de FAT
- Número máximo de directorios raíz, etc.
Dado que el disquete no tiene un sistema de partición lógica, no hay MBR disponible en el disquete. El Primer Sector de Floppy tiene el DBR. Esta es también una diferencia principal para comparar la estructura lógica del disco duro con un disquete.
Cuando leemos la información del sector de arranque de un disquete con la ayuda de cualquier programa de edición de disco, mostrará información como la que se muestra a continuación.
La siguiente figura muestra la información de 512 Bytes del DBR de un 1.44MB, 3½ Disquete de pulgadas.
Si esta información se corrompe de alguna forma o se vuelve ilegible, el disquete genera dichos mensajes de error de lectura. Puede deberse a una corrupción física o lógica del primer sector del disco.
La corrupción lógica incluye los casos en que se cambia la información del primer sector del disquete, se produce cualquier sector lógico defectuoso o el DBR del disquete está dañado por cualquier otro motivo.
Se supone que la corrupción física tiene lugar en caso de que haya sectores físicos defectuosos (significa que el sector 1 está físicamente dañado) en el primer sector de la disco flexible. El problema se vuelve más serio cuando descubre que el disquete tiene más de un sector defectuoso en la pista 0.
Cómo recuperar
Como hemos aprendido sobre las causas de la corrupción, espero que ahora pueda comprender el problema. No es muy difícil recuperar los datos de la corrupción lógica; sin embargo, la recuperación de la corrupción física requiere un poco más de esfuerzo.
Método – 1
Almacene la imagen de arranque de cualquier disquete nuevo
Si el problema es lógico, ahora entendemos cómo podemos recuperar los datos. Lo que tenemos que hacer es obtener el registro de arranque apropiado de otro disquete del mismo tamaño y capacidad y pegarlo en el primer sector del disquete ilegible. Aunque el problema se creó debido al registro de arranque incorrecto, debería funcionar ahora.
Hay dos pasos involucrados en este procedimiento siguiendo los cuales estamos recuperando nuestros datos de un disquete ilegible:
- Haciendo la imagen de DOS Boot Record de un buen disquete
- Pegar la imagen de inicio en el primer sector del disquete ilegible
Haciendo la imagen de DOS Boot Record de un buen disquete
Para almacenar la imagen del registro de arranque de un disquete nuevo, el programa debe realizar las siguientes tres tareas:
- Leer exactamente los primeros 512 bytes del disquete bueno
- Verifique que la operación de lectura sea exitosa (lo más importante)
- Almacene estos 512 bytes en el nombre de archivo y la ruta de destino especificados
El sector del disquete es de 512 bytes y es necesario copiar la imagen exacta del sector. Es el paso más importante y necesario en caso de cualquier tipo de operaciones aplicadas en un disquete para verificar si la operación fue exitosa o no.
Puede haber algún problema de inicialización incluso con el disquete bueno y nuevo. Es por eso que en la mayoría de los casos cuando la operación se realiza en disquetes, en primer lugar se realiza la inicialización de los disquetes en la programación con la operación de reinicio de disco (Función 00 H de INT 13H).
Si, incluso después de la inicialización, el disquete insertado recientemente o el disquete cambiado causa algún error de lectura, se le recomienda ejecutar el programa nuevamente, lo más probable es que funcione esta vez.
El siguiente programa es para realizar estas tareas especificadas. Veamos cómo procede:
/* Almacene la imagen de inicio en un archivo desde un disquete nuevo */
#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");
/// Inicializar el 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;
}
Comentarios sobre la codificación del programa:
En la codificación del programa dada anteriormente, básicamente estamos procediendo a realizar las siguientes tareas paso a paso:
- dinfo apunta a la estructura diskinfo_t que contiene la información de los parámetros requeridos por la operación realizada por la función _bios_disk.
- Dado que queremos leer el primer sector del disco, la ubicación del sector será la siguiente:
Parámetro |
Qué significa |
dinfo.drive = 0x00 |
Indica la unidad 0 que es disquetera (a:) |
dinfo.head = 0 |
Apunta al número de cabeza 0 |
dinfo.track = 0 |
apunta a rastrear 0 |
dinfo.sector = 1 |
Primer sector del disquete que es sector1 |
dinfo.sector = 1 |
Número de sectores a considerar para la operación de lectura =1 |
dinfo.buffer = dbuf |
Búfer de datos para la operación |
- Abra una secuencia de archivos con el nombre de archivo y la ruta proporcionados por el usuario para almacenar la información de la imagen de arranque de 512 bytes exactos. El nombre del archivo y la ruta se almacenan en la matriz de caracteres fname.
- Inicialice el sistema de disco usando la interrupción 13H (función 00h) donde regs.h.ah = 0x00 apunta a la función 00 H y regs.h.dl = 0x00 se usa para un: disquete. E int86(0x13, ®s, ®s) invoca el servicio de interrupción de MS-DOS INT 13 H.
- _bios_disk(_DISK_READ, &dinfo) lee el sector especificado del disquete.
- El estado devuelto se almacena en el resultado que se usa para mostrar el mensaje de operación exitosa o para mostrar un mensaje de error en la pantalla si ocurre algún error.
Pegar la imagen de inicio en el primer sector del disquete ilegible
Para pegar la imagen de arranque desde el archivo al primer sector del disquete ilegible, debemos realizar las siguientes tres tareas principales en nuestro programa:
- Lea información exacta de 512 bytes del registro de arranque de un disquete nuevo desde un archivo guardado previamente.
- Escriba esta información en el primer sector del disquete que actualmente no se puede leer.
- Verifique que la operación de escritura se haya completado con éxito (lo más importante).
Como el sector del disquete es de 512 bytes y es necesario pegar la imagen de arranque exacta al sector. Es el paso más importante y necesario en caso de cualquier tipo de operaciones aplicadas en un disquete para verificar si la operación fue exitosa o no.
Puede haber algún problema de inicialización con el disquete durante la operación, por lo que debe inicializar el disco restableciendo el sistema del disco(usando la función 00H de INT 13H).
Si, incluso después de la inicialización, el disquete insertado recientemente o el disquete cambiado causa algún error de lectura, se le recomienda ejecutar el programa nuevamente, lo más probable es que funcione esta vez.
El siguiente programa es para realizar estas tareas especificadas. Veamos cómo procede:
/* Cargar imagen de inicio en el disquete ilegible */
#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");
/// Inicializar el 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;
}
Comentarios sobre la codificación del programa:
En la codificación del programa dada anteriormente, básicamente estamos procediendo a realizar las siguientes tareas paso a paso:
- dinfo apunta a la estructura diskinfo_t que contiene la información de los parámetros requeridos por la operación realizada por la función _bios_disk.
- Como vamos a escribir la información en el primer sector del disco, la ubicación del sector será la siguiente:
- Abra el archivo en el que el programa anterior almacenó la información de la imagen de arranque de 512 bytes de un disquete nuevo. El nombre del archivo y la ruta se almacenan en la matriz de caracteres fname.
- Inicialice el sistema de disco usando la interrupción 13H (función 00h) donde regs.h.ah = 0x00 apunta a la función 00 H y regs.h.dl = 0x00 se usa para un: disquete. E int86(0x13, ®s, ®s) invoca el servicio de interrupción de MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) escribe la información de arranque del archivo especificado en el primer sector (especificado) del disquete.
- El estado devuelto se almacena en el resultado que se usa para mostrar el mensaje de operación exitosa o para mostrar un mensaje de error en la pantalla si ocurre algún error.
Parámetro |
Qué significa |
dinfo.drive = 0x00 |
Indica la unidad 0 que es disquetera (a:) |
dinfo.head = 0 |
Apunta al número de cabeza 0 |
dinfo.track = 0 |
apunta a rastrear 0 |
dinfo.sector = 1 |
Primer sector del disquete que es sector 1 |
dinfo.sector = 1 |
Número de sectores a considerar para operación de escritura = 1 |
dinfo.buffer = dbuf |
Búfer de datos para la operación |
Hagámoslo con un solo programa
Espero que ahora haya entendido el concepto detrás de este tipo de recuperación de datos del disquete. Después de esto, imaginemos un solo programa que dé los mismos resultados que obtuvimos con la ayuda de los dos programas discutidos anteriormente.
Estábamos haciendo las siguientes tareas con los programas discutidos recientemente:
- Almacene la información de arranque de un buen disquete en un archivo
- Pegue esta información en el primer sector del disquete actualmente ilegible. El archivo que estábamos usando para almacenar la imagen de arranque funcionaba como un puente intermedio para conectar las operaciones de ambos programas. Pero si definimos esta información de arranque en la codificación de nuestro propio programa, no necesitamos crear un archivo así como no necesitamos leer la información de arranque del disquete del archivo.
En nuestro próximo programa le estamos diciendo a nuestro programa lo que tiene que escribir en el primer sector del disquete ilegible y así podemos evitar que dos programas diferentes hagan la misma tarea y podemos recuperar nuestro datos de la misma manera que antes del nuevo programa único.
Por lo tanto, el programa se vuelve simple con menos codificación y podemos reducir la probabilidad de ocurrencia de errores de lectura, escritura o creación de archivos. Estamos haciendo las siguientes cuatro tareas importantes en este programa:
No crea que el programa es difícil de escribir y comprender al ver la información hexadecimal de 512 bytes de dbuf[512]. Más adelante, discutiremos la manera fácil de escribir esta información para la codificación de su programa.
- Defina la información del registro de arranque de DOS en el sistema hexadecimal para que se escriba en el primer sector del disquete actualmente ilegible.
- Restablezca el sistema de disco para inicializar el disquete (INT 13H, Función 00H).
- Escriba el registro de arranque de DOS en el primer sector del disquete
- Compruebe la finalización exitosa de la operación y el error, si ocurrió.
Examinemos el programa:
/* Programa único para cargar la imagen de inicio predeterminada en un disquete ilegible */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* Imagen de arranque que se cargará en la unidad 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");
/// Inicializar el 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;
}
En la codificación de este programa, básicamente estamos procediendo a realizar las siguientes tareas paso a paso:
- El búfer de datos de caracteres estáticos dbuf[512] proporciona la información de 512 bytes en sistema hexadecimal, que se escribirá en el primer sector del disquete ilegible. dbuf[512] le dice a la computadora durante la operación qué información debe escribirse en el primer sector del disquete. (Ver el próximo programa)
- dinfo apunta a la estructura diskinfo_t que contiene la información de los parámetros requeridos por la operación realizada por la función _bios_disk.
- Como vamos a escribir la información en el primer sector del disco, la ubicación del sector será la siguiente:
Parámetro |
que significa |
dinfo.drive = 0x00 |
Indica la unidad 0 que es disquetera (a:) |
dinfo.head = 0 |
Apunta al número de cabeza0 |
dinfo.track = 0 |
apunta a rastrear0 |
dinfo.sector = 1 |
Primer sector del disquete que es sector1 |
dinfo.sector = 1 |
Número de sectores a considerar para la operación de escritura =1 |
dinfo.buffer = dbuf |
Búfer de datos para la operación |
- Inicialice el sistema de disco usando la interrupción 13H (función 00h) donde regs.h.ah = 0x00 apunta a la función 00 H y regs.h.dl = 0x00 se usa para un: disquete. E int86(0x13, ®s, ®s) invoca el servicio de interrupción de MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) escribe la información de arranque del archivo especificado en el primer sector (especificado) del disquete.
El estado devuelto se almacena en el resultado que se utiliza para mostrar el mensaje de operación exitosa o para mostrar un mensaje de error en la pantalla si ocurre algún error.
Almacenamiento de la imagen de inicio en caracteres HEXADECIMAL para usar en nuestro programa anterior
Será un trabajo muy difícil escribir los 512 caracteres del registro de arranque de DOS del disquete manualmente en un sistema hexadecimal sin ningún error en el programa del que hablamos recientemente. Si podemos escribirlo con precisión, será una tarea difícil y que llevará mucho tiempo hacerlo. Usemos una mente astuta para almacenar los datos para el búfer de datos dbuf[512] en un archivo.
Sabemos que en la programación C los caracteres hexadecimales se representan con 0x, de modo que si el carácter hexadecimal es A9 H, lo escribiremos en nuestro programa C como 0xA9. Nuestro próximo programa está haciendo lo mismo. Almacenará los datos que necesitamos escribir en nuestro programa anterior, como los datos del búfer de datos dbuf[512].
Lo que tiene que hacer es simplemente tomar un disquete nuevo y fresco para hacer la imagen de su DBR y copiar la salida de este programa desde el archivo de destino especificado y pegar estos datos en su programa. Haga algo de formateo si es necesario. Veamos cómo funciona:
/* Programa para hacer la imagen de arranque del disquete en carácter 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);
}
/// Inicializar el 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;
}
Comentarios sobre la codificación del programa:
Por lo tanto, los datos se almacenan en el archivo especificado. Simplemente copie los datos en su programa y realice el formateo requerido. Nunca debe olvidar los siguientes consejos a lo largo del procedimiento:
- Asegúrese de que la operación del programa se haya realizado correctamente y que los datos almacenados en el archivo de destino sean los adecuados.
- Debe verificar la operación en busca de errores esperados.
- Debe inicializar el disquete con el programa antes de leer su sector de arranque. Puede usar la función 00H de INT 13H para este propósito.
Método – 2
Qué hacer si Método – 1 no funciona?
Si el Método – 1 no funciona y el disco ilegible no permite que el programa vuelva a escribir la información de arranque en su primer sector, debe probar este segundo método. La razón detrás de la falla de First Method puede ser la corrupción física del primer sector del disquete.
En este segundo método vamos a copiar todos los datos de la superficie del disquete ilegible en un solo archivo temporalmente y luego pegaremos esta imagen directamente en la superficie del otro disco bueno.
El procedimiento implica los siguientes dos pasos importantes:
- Sector por sector Copie todos los datos de la superficie de los medios de disquete en un solo archivo temporalmente.
- Pegue los datos previamente almacenados en el archivo, en un nuevo disquete tal como está, en los mismos sectores.
Copie todos los datos de la superficie multimedia en un solo archivo
Para almacenar todos los datos de la superficie de los medios de disquete, el programa debe realizar las siguientes tres tareas:
- Inicialice el disco correctamente con la ayuda de la función 00H de INT 13H.
- Lea la información sector por sector de la superficie y guárdela en un solo archivo.
- Verifique que la operación de lectura sea exitosa (lo más importante)
Es muy común tener algún problema de inicialización con un disquete que genera muchos mensajes de lectura fallida. Es por eso que el disco debe inicializarse antes de la operación de lectura y escritura con la ayuda de la programación.
Es el paso más importante y necesario en caso de cualquier tipo de operaciones aplicadas en un disquete para verificar si la operación fue exitosa o no.
Si, incluso después de la inicialización, el disquete insertado recientemente o el disquete cambiado causan algún error de lectura, se recomienda ejecutar el programa nuevamente, lo más probable es que funcione esta vez.
El siguiente programa es para realizar estas tareas específicas. Veamos cómo procede:
/* Programa para almacenar los datos de la superficie física del disquete en un archivo */
#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");
/// Inicializar el 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);
}
}
}
}
Comentarios sobre la codificación del programa:
En la codificación del programa dada anteriormente, básicamente estamos procediendo a realizar las siguientes tareas paso a paso:
- Nombre de archivo de matriz de caracteres[80] almacena la ruta definida por el usuario y el nombre de archivo del archivo en el que vamos a almacenar los datos temporalmente.
- dinfo apunta a la estructura diskinfo_t que contiene la información de los parámetros requeridos por la operación realizada por la función _bios_disk.
- Inicialice el sistema de disco usando la interrupción 13H (función 00h) donde regs.h.ah = 0x00 apunta a la función 00 H y regs.h.dl = 0x00 se usa para un: disquete. E int86(0x13, ®s, ®s) invoca el servicio de interrupción de MS-DOS INT 13 H.
- Como vamos a leer toda la información de la superficie del disco, los parámetros de _bios_disk serán los siguientes:
Parámetro |
que significa |
dinfo.drive = 0x00 |
Indica la unidad 0 que es disquetera (a:) |
dinfo.head = head |
Apunta a la cabeza número 0 y 1 ya que el disquete tiene dos lados (dos cabezas) |
dinfo.track = track |
Apunta a la pista 0 a 79 ya que hay 80 pistas en cada lado del disquete. |
dinfo.sector = sector |
Apunta al sector 1 a 18 ya que hay 18 sectores en cada pista. |
dinfo.sector = 1 |
Número de sectores a considerar para operación de lectura = 1 |
dinfo.buffer = dbuf |
Búfer de datos para la operación |
- _bios_disk(_DISK_READ, &dinfo) lee los datos de la superficie física del disquete del sector especificado por dinfo.
- El estado devuelto se almacena en el resultado que se usa para mostrar el mensaje de operación exitosa o para mostrar un mensaje de error en la pantalla si ocurre algún error.
Recuerde siempre que el tamaño del archivo que contiene la imagen de los datos del disquete debe ser de 1.474.560 bytes exactos porque el disquete tiene 80 pistas (0 a 79), 2 caras o cabezas (cabeza 0 y cabeza 1), cada pista tiene 18 sectores y cada sector contiene los 512 bytes de datos, por lo tanto
Bytes totales = (Número de pistas) * (Número de cabezales) *
(Número de Sectores por Pista) * 512
= 80*2*18*512
= 1.474.560 bytes
Así, si hay algún error de lectura en algún sector del disquete, cambiará el tamaño del archivo de 1.474.560 Bytes, lo que hará que toda la información sea total o parcialmente inservible para el disco de destino al que nos dirigimos. para escribir la imagen de disco sector por sector de este archivo.
Esto es así porque la computadora lee la información de cualquier archivo en la superficie de los medios del disquete dentro del rango del sector tal como ha sido asignado en su unidad de asignación. Ahora bien, si se cambian los sectores de los datos de los archivos, se cambia la información completa del archivo.
Pensando en la solución del error de lectura del sector(es)
Es posible que el disquete dañado o ilegible tenga un área tan dañada en su superficie que no podamos leer la información de la superficie del disco.
En esta condición, la información de este(s) sector(es) se omitirá y la imagen del disquete se distorsionará incluso para los demás sectores, ya que el tamaño del archivo de imagen en este caso difiere de 1 474 560 Bytes.
Para mantener el tamaño del archivo de imagen y pegar el resto de la información en las ubicaciones exactas de los sectores en el disco de destino, escribimos alguna otra información en nombre de los datos originales de 512 bytes y de esta manera, ’ Se podrá guardar el resto de la información, sin embargo, la recuperación en tal caso puede ser la recuperación parcial.
Si su sistema tampoco puede leer el primer sector del disquete de origen, después de pegar la imagen en el disquete de destino, debe ejecutar el programa descrito anteriormente para volver a escribir el Registro de arranque de DOS del disquete. .
Veamos cómo podemos hacerlo 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];
/*Información de 512 Bytes para llenar espacio de Bad Sector */
/// Usé 512 ceros para llenar el espacio de 512 bytes \\\
static char dbuf2[512] =
"00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// Inicializar el 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);
/* Si el sector no es legible, ocupa 512 bytes por dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
Comentarios sobre la codificación del programa:
En la codificación del programa, cada paso es igual que en el programa anterior, excepto el búfer de datos dbuf2[512], que estamos usando para manejar el error generado por el sector defectuoso durante la operación de lectura del disco. > y para mantener el tamaño del archivo de imagen.
Al hacer esto, estamos llenando el espacio de la información, que no pudimos leer del sector defectuoso y ahora estamos escribiendo la pseudo información de 512 bytes para que podamos mantener la precisión de la imagen del disco.
Pegue los datos del archivo en la superficie física de un disquete nuevo:
En este paso, pegamos los datos almacenados en el archivo por el programa anterior, en la superficie física del disquete nuevo, sector por sector de la misma manera que lo copiamos en el archivo.
El programa procede con los siguientes pasos principales:
- Abra el archivo en el que almacenamos los datos de superficie del disquete ilegible temporalmente.
- Inicialice el sistema de disco correctamente mediante la función de reinicio 00H de INT 13H.
- Escriba la información en los sectores del disquete nuevo del archivo.
- Muestre el estado de escritura simultáneamente para encontrar o evitar la ocurrencia de errores.
El código fuente del programa se proporciona a continuación. Examinemos cómo funciona:
/* Programa para escribir los datos en los sectores de la superficie del disquete nuevo del archivo, creado por el 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);
}
/// Inicializar el 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);
}
}
}
}
Comentarios sobre la codificación del programa:
En la codificación del programa dada anteriormente, básicamente estamos procediendo a realizar las siguientes tareas paso a paso:
- Nombre de archivo de matriz de caracteres[80] contiene la ruta y el nombre de archivo del archivo en el que almacenamos los datos de la superficie del disquete ilegible temporalmente.
- dinfo apunta a la estructura diskinfo_t que contiene la información de los parámetros requeridos por la operación realizada por la función _bios_disk.
- Inicialice el sistema de disco usando la interrupción 13H (función 00h) donde regs.h.ah = 0x00 apunta a la función 00 H y regs.h.dl = 0x00 se usa para un: disquete. E int86(0x13, ®s, ®s) invoca el servicio de interrupción de MS-DOS INT 13 H.
- Como vamos a escribir la información directamente en sectores de la superficie del disco, los parámetros de _bios_disk serán los siguientes:
Parámetro |
que significa |
dinfo.drive = 0x00 |
Indica la unidad 0 que es disquetera (a:) |
dinfo.head = head |
Apunta a la cabeza número 0 y 1 ya que el disquete tiene dos lados (dos cabezas) |
dinfo.track = track |
Apunta a la pista 0 a 79 ya que hay 80 pistas en cada lado del disquete. |
dinfo.sector = sector |
Apunta al sector 1 a 18 ya que hay 18 sectores en cada pista. |
dinfo.sector = 1 |
Número de sectores a considerar para la operación de escritura = 1 |
dinfo.buffer = dbuf |
Búfer de datos para la operación |
- _bios_disk(_DISK_WRITE, &dinfo) escribe los datos en los sectores de la superficie física del disquete, especificados por dinfo.
- El estado devuelto se almacena en el resultado que se usa para mostrar el mensaje de operación exitosa o para mostrar un mensaje de error en la pantalla si ocurre algún error.
Si después del Método – 2 su nuevo disquete no funciona, puede aplicar el Método – 1 en su nuevo disquete, que usó como disco de destino durante el Método – 2.
No solo esto, sino que también el número de aciertos y pruebas puede variar dependiendo de la corrupción del disco. Pero no debe preocuparse si incluso después no obtiene resultados satisfactorios.
Puede probar la recuperación archivo por archivo o probar muchos más consejos que aprenderá a continuación. Aquí implementaremos la idea de recopilar la información del archivo de los directorios raíz, en nuestra programación para recuperar los datos.
Pensando en la recuperación lógica de datos borrados o perdidos:
Todos los casos anteriores que discutimos en este capítulo para la recuperación, fueron para recuperar los datos en aquellos casos en los que esperábamos que solo el DBR esté dañado y los sectores en la pista 0, FAT1, FAT2 y los directorios raíz son legibles.
Pero si el problema se debe a la corrupción de FAT o los datos se han eliminado del disco o desea recuperar los datos directamente leyendo su información desde el directorio raíz, necesitamos leer información como Nombre de archivo, clúster de inicio, tamaño del archivo , Atributo etc. desde su entrada en el directorio raíz.
Como ya hemos discutido sobre Directorio raíz en capítulos anteriores, existe una información de 32 bytes para cada archivo o directorio. Estos 32 bytes se dividen de la siguiente manera:
Número de bytes |
Descripción de la información |
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 |
Recuperamos los datos leyendo la información de los archivos del Directorio raíz y luego integramos el archivo en la ruta de destino y recuperamos el archivo. Nuestro siguiente programa realiza los siguientes pasos para recuperar los datos:
- Lea las entradas del directorio raíz y muéstrelas en la pantalla con toda la información, como el nombre del archivo/directorio, la extensión del archivo, el tamaño del clúster inicial de los archivos en bytes.
- Lea la información de archivos y directorios en los subdirectorios y muéstrelos si es necesario.
- Confirme el nombre del archivo a recuperar y continúe con la recuperación.
- Calcule la información de CHS (cilindro, cabeza y sector) para recuperar el archivo especificado.
- Integre los datos del archivo desde el área de datos del disco y guarde el archivo recuperado en el nombre de archivo de destino especificado en la ruta especificada.
A este Programa no le importa si la información de arranque del disquete es legible o no. Por lo tanto, también puede recuperar datos eliminados del disquete dañado. Veamos la codificación del programa:
/* Programa para recuperar los datos del disquete leyendo la información del archivo desde el directorio raíz */
#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 de pantalla de visualización de información \\\
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("--------------------------------------------");
/* Un Sector a la vez. Cada entrada de archivo/DIR ocupa 32 bytes */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// Encuentre el nombre del archivo/directorio \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// Encuentra la extensión \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// Clúster de inicio \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Calcular el tamaño \\\
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
Recuerde que el nombre de archivo que comienza con s (E5H) representa que el archivo se eliminó y, por lo tanto, el primer carácter del nombre de archivo se reemplazó con s (consulte la descripción del directorio raíz en los capítulos anteriores).
Y la salida del programa se muestra así:
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 !!!
|
Comentarios sobre la codificación:
La función Display_Information es para leer la información del archivo y directorio y desde el directorio raíz. En la Estructura estamos leyendo la información de 32 bytes para cada archivo o directorio con root[32].
Las matrices de enteros sin signo nombre[8] y ext[3] son para nombre de archivo o directorio para DOS en formato 8.3 (ocho puntos tres). De manera similar, un byte es para el atributo y dos bytes para el clúster inicial. tamaño int sin signo largo; es almacenar el tamaño del archivo de cuatro bytes.
La función _bios_disk lee el sector especificado por la estructura finfo y el estado de la operación se almacena en result.
Desde toda la información de 512 bytes leída por la función_bios_disk, hasta que finaliza el área del directorio raíz, recopilamos la información de los archivos y directorios almacenados en el disco y mostrarlos en la pantalla.
El entero file_no almacena el número del archivo o directorio en la lista, comenzando desde 0. Generalmente, el tamaño del directorio raíz es de 14 sectores y el directorio raíz generalmente comienza desde Cilindro = 0, Cabeza = 0 y Sector = 2 en caso de 1.44MB y 3½ disquete.
Si el usuario da el carácter ‘M’ o ‘m’ como entrada, se muestra la información del siguiente sector si la elección del usuario es ‘R’ o ‘r’ se llaman las funciones de recuperación. La codificación de la función recover() se muestra a continuación:
/* Función para iniciar la recuperación del archivo especificado */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/* Función para integrar el archivo 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 el nombre del archivo a recuperar */
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);
/// Lo sentimos, seleccionó un directorio \\\
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 Geometría */
calculate(start,&cylinder,&head,§or);
/* Mostrar contenido del directorio */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* Calcular para información CHS */
calculate(start,&cylinder,&head,§or);
/* Integrar el archivo */
integrate(size,cylinder,head,sector);
}
}
Comentarios sobre la codificación:
La función recover() es obtener la entrada del usuario para iniciar la recuperación. El número de archivo proporcionado como entrada por el usuario para recuperar el archivo, se almacena en file_no.
Si el número ingresado es para la entrada del directorio, Display_Information() muestra el contenido de ese directorio; de lo contrario, el nombre del archivo y la extensión del número de archivo file_no se muestran en la pantalla para confirmar el archivo que se va a recuperar.
Para recuperar el archivo especificado, las funciones calculate() e integrate() se llaman dentro de la función. La codificación de la función calcular() se da a continuación:
/* Función para calcular la geometría CHS para la recuperación */
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;
}
/// Mostrar el CHS del archivo que se recuperará \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
Comentarios sobre la codificación:
La función calculate() es para calcular la información de Cilindro, Cabezal y Sector para el archivo a recuperar. Después del cálculo, los números de Cilindro, Culata y Sector se muestran en la pantalla.
La codificación para la función integrar() se proporciona a continuación:
/* Integre el archivo y guarde el archivo recuperado en la ruta y el nombre de archivo especificados */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* Función para verificar el sector en busca de errores */
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;
/* Ingrese la ruta de destino y el nombre del archivo para guardar el archivo 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");
/* Si se produjo un error, muestre el mensaje de error y obtenga la ruta de entrada y el nombre del archivo nuevamente */
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 */
}
/* Si todo está bien, integra y escribe */
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);
}
Comentarios sobre la codificación:
La función integrate() es el módulo real para realizar la recuperación del archivo especificado por el usuario, en este programa de recuperación.
El nombre del archivo con la ruta de destino para almacenar el archivo recuperado se almacena en el puntero de carácter *Filename_with_path. Si hay algún error al abrir el archivo de destino, se muestra un mensaje de error y se le solicita nuevamente al usuario que ingrese el destino.
La función _bios_disk(_DISK_READ, &dinfo); lee los datos del archivo del área de datos del disco sector por sector, especificado por la estructura dinfo y almacenado en el búfer de datos buf . Estos datos de 512 bytes se escriben en el archivo de destino. Esto se repite hasta que se integra el archivo completo.
La función estado=verificar_el_sector (cilindro, cabeza, sector); verifica el sector a leer. Si el estado = 10, representa un sector defectuoso (0xA). La codificación de la función se da a continuación:
/// Verificar el Sector. (No se transfieren datos aquí) \\\
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);
}
Comentarios sobre la codificación:
La función verificar_el_sector(), verifica el sector para ser leído por la función _bios_disk() y devuelve el estado de la operación. La función usa INT 13H y la función 4H para verificar el sector.
*buf es el búfer de datos, 0x04 es el número de función especificado por in.h.ah = 0x04; e in.h.al = 1; instruye para verificar un sector a la vez. en.h.dl = 0x00; se utiliza para el número de unidad para la unidad de disquete A:, c, h y s son números de cilindro, cabezal y sector.
La función int86x() se usa para invocar INT 13H (función 4H) con valores de registro de segmento. El estado de la operación es devuelto por el estado entero.
La función clear_the_line() borra la fila especificada en la pantalla. La codificación de la función es la siguiente:
/* Función para borrar la línea en la pantalla, para el número de fila 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 " " */
}
}
Comentarios sobre la codificación:
La función se utiliza para borrar la fila especificada en la pantalla. La función se llama con el número de fila, que se va a borrar de la pantalla.
Página modificada el: 14/01/2022