Chapitre – 10
Récupération de données à partir d'une disquette corrompue
Récupération de données à partir d'une disquette corrompue
La disquette est l'une des sources de stockage de données les moins fiables. Si vous allez dans une organisation qui utilise des systèmes informatiques et demandez à ses employés les problèmes générés par les disquettes, vous entendrez très souvent le problème que l'employé de l'organisation avait des données importantes sur sa disquette et maintenant la disquette n'est plus lisible par l'ordinateur et un message est affiché quelque chose comme,
“Impossible de lire le disque”
“Suivre 0 mauvais”
“Disque ou capacité non valide”
“Le disque n'est pas formaté. Voulez-vous le formater maintenant ?
C'est le problème quotidien des organisations qui utilisent des systèmes informatiques et des disquettes. Le problème devient critique lorsque vous apprenez qu'aucune sauvegarde n'a été effectuée ou qu'aucune sauvegarde n'est disponible pour les données qui semblent être perdues sur la disquette corrompue.
Le plus gros enfer du problème est censé survenir lorsque vous effectuez une sauvegarde sur disquette pour vos informations critiques, des disques de secours du programme antivirus pour surmonter l'attaque virale ou des enregistrements de démarrage ou d'autres sauvegardes (il peut y avoir un certain nombre de possibilités) dans une disquette et lorsque vous voulez réutiliser la sauvegarde de la disquette, cela donne une erreur de lecture.
Dans de telles conditions, vous êtes sur le point de perdre vos informations et données importantes ou même dans certains cas, lorsque vous ressentez le manque de sauvegardes et de programme de récupération pour les informations de démarrage de votre ordinateur et le sauvetage des attaques de virus programmes etc., vous pouvez subir une grosse perte de données sous forme de plantage du système d'exploitation en raison du manque d'informations, stockées sur la disquette qui n'est pas lisible par l'ordinateur maintenant.
Dans de tels cas, il devient primordial de récupérer les données de la disquette qui a été déclarée mauvaise par votre système informatique.
Pourquoi la disquette n'est pas lisible
Le problème le plus courant qui fait qu'une disquette affiche ce type de messages d'erreur est la corruption de son enregistrement de démarrage DOS (DBR) de la disquette, ce qui aide l'ordinateur à connaître l'identification logique de la disquette.
Le DBR est un petit programme stocké dans la piste 0, la tête 0 et le secteur 1 et contenant des informations importantes sur la disquette telles que :
- Nombre d'octets par secteur
- Secteur par cluster
- Nombre de FAT
- Nombre maximal de répertoires racine, etc.
Étant donné que Floppy n'a pas de système de partition logique, il n'y a donc pas de MBR disponible sur disquette. Le premier secteur de Floppy contient le DBR. C'est aussi une différence principale pour comparer la structure logique du disque dur avec une disquette.
Lorsque nous lisons les informations du secteur de démarrage d'une disquette à l'aide de n'importe quel programme d'édition de disque, il affichera des informations comme dans la figure ci-dessous.
La figure suivante montre les 512 octets d'informations du DBR d'un disque de 1,44 Mo, 3 ½ Disquette pouces.
Si ces informations sont corrompues de quelque manière que ce soit ou si elles deviennent illisibles, la disquette provoque de tels messages d'erreur de lecture. Cela peut être dû à une corruption physique ou logique du premier secteur du disque.
La corruption logique comprend les cas où les informations du premier secteur de la disquette sont modifiées, il se produit un secteur logique défectueux ou le DBR de la disquette est corrompue pour une autre raison.
La corruption physique est censée avoir lieu en cas de présence de secteurs physiques défectueux (ce qui signifie que le secteur 1 est physiquement endommagé) sur le premier secteur du disquette. Le problème devient plus grave lorsque vous constatez que la disquette a plus d'un secteur défectueux dans la piste 0.
Comment récupérer
Comme nous avons appris les causes de la corruption, j'espère que vous êtes maintenant en mesure de comprendre le problème. Il n'est pas très difficile de récupérer les données de la corruption logique, mais la récupération de la corruption physique nécessite un peu plus d'efforts.
Méthode – 1
Stocker l'image de démarrage de toute nouvelle disquette
Si le problème est logique, nous comprenons maintenant comment récupérer les données. Ce que nous devons faire est simplement d'obtenir l'enregistrement de démarrage approprié à partir d'une autre disquette de même taille et capacité et de le coller dans le premier secteur de la disquette illisible. Bien que le problème ait été créé en raison du mauvais enregistrement de démarrage, cela devrait fonctionner maintenant.
Il y a deux étapes impliquées dans cette procédure en suivant laquelle nous récupérons nos données à partir d'une disquette illisible :
- Faire l'image du Boot Record DOS d'une bonne disquette
- Coller l'image de démarrage dans le premier secteur de la disquette illisible
Faire l'image du Boot Record DOS d'une bonne disquette
Pour stocker l'image de l'enregistrement de démarrage d'une nouvelle disquette, le programme doit effectuer les trois tâches suivantes :
- Lire exactement les 512 premiers octets de la bonne disquette
- Vérifier la réussite de l'opération de lecture (le plus important)
- Stockez ces 512 octets dans le nom de fichier et le chemin de destination spécifiés
Le secteur de la disquette est de 512 octets et il est nécessaire de copier l'image exacte du secteur. C'est l'étape la plus importante et la plus nécessaire dans le cas de tout type d'opérations appliquées sur disquette pour vérifier si l'opération a réussi ou non.
Il peut y avoir un problème d'initialisation même avec la bonne et fraîche disquette. C'est pourquoi, dans la plupart des cas, lorsque l'opération est effectuée sur des disquettes, l'initialisation des disquettes est tout d'abord effectuée dans la programmation avec l'opération de réinitialisation du disque (Fonction 00 H de INT 13H).
Si même après l'initialisation, la disquette récemment insérée ou la disquette modifiée provoque une erreur de lecture, il vous est conseillé d'exécuter à nouveau le programme, il est fort probable que cela fonctionne cette fois.
Le programme suivant consiste à effectuer ces tâches spécifiées. Voyons comment ça se passe :
/* Stocker l'image de démarrage dans un fichier à partir d'une nouvelle disquette */
#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");
/// Initialiser le système de disque \\\
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;
}
Commentaires sur le codage du programme :
Dans le codage du programme donné précédemment, nous procédons essentiellement à l'exécution des tâches suivantes étape par étape :
- dinfo pointe vers la structure diskinfo_t qui contient les informations des paramètres requis par l'opération effectuée par la fonction _bios_disk.
- Puisque nous voulons lire le premier secteur du disque, l'emplacement du secteur sera donc le suivant :
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 |
- Ouvrez un flux de fichiers avec un nom de fichier et un chemin donnés par l'utilisateur pour stocker les informations d'image de démarrage de 512 octets exacts. Le nom et le chemin du fichier sont stockés dans le tableau de caractères fname.
- Initialiser le système de disque à l'aide de l'interruption 13H (fonction 00h) où regs.h.ah = 0x00 pointe vers la fonction 00 H et regs.h.dl = 0x00 est utilisé pour a : disquette. Et int86(0x13, ®s, ®s) invoque le service d'interruption MS-DOS INT 13 H.
- _bios_disk(_DISK_READ, &dinfo) lit le secteur spécifié de la disquette.
- Le statut renvoyé est stocké dans le résultat qui est utilisé pour afficher le message de réussite de l'opération ou pour afficher un message d'erreur à l'écran en cas d'erreur.
Coller l'image de démarrage dans le premier secteur de la disquette illisible
Pour coller l'image de démarrage du fichier dans le premier secteur de la disquette illisible, nous devons effectuer les trois tâches principales suivantes dans notre programme :
- Lire les informations exactes de 512 octets de l'enregistrement de démarrage de la nouvelle disquette à partir du fichier précédemment enregistré.
- Écrivez ces informations dans le premier secteur de la disquette qui est actuellement illisible.
- Vérifier la réussite de l'opération d'écriture (le plus important).
Comme le secteur de la disquette est de 512 octets et qu'il est nécessaire de coller l'image de démarrage exacte sur le secteur. C'est l'étape la plus importante et la plus nécessaire dans le cas de tout type d'opérations appliquées sur disquette pour vérifier si l'opération a réussi ou non.
Il peut y avoir un problème d'initialisation avec la disquette pendant l'opération, vous devez donc initialiser le disque en réinitialisant le système de disque(à l'aide de la fonction 00H de INT 13H).
Si même après l'initialisation, la disquette récemment insérée ou la disquette modifiée provoque une erreur de lecture, il vous est conseillé d'exécuter à nouveau le programme, il est fort probable que cela fonctionne cette fois.
Le programme suivant consiste à effectuer ces tâches spécifiées. Voyons comment ça se passe :
/* Charger l'image de démarrage sur la disquette illisible */
#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");
/// Initialiser le système de disque \\\
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;
}
Commentaires sur le codage du programme :
Dans le codage du programme donné précédemment, nous procédons essentiellement à l'exécution des tâches suivantes étape par étape :
- dinfo pointe vers la structure diskinfo_t qui contient les informations des paramètres requis par l'opération effectuée par la fonction _bios_disk.
- Comme nous allons écrire les informations sur le premier secteur du disque, l'emplacement du secteur sera donc le suivant :
- Ouvrez le fichier dans lequel les informations d'image de démarrage de 512 octets d'une nouvelle disquette ont été stockées par le programme précédent. Le nom et le chemin du fichier sont stockés dans le tableau de caractères fname.
- Initialiser le système de disque à l'aide de l'interruption 13H (fonction 00h) où regs.h.ah = 0x00 pointe vers la fonction 00 H et regs.h.dl = 0x00 est utilisé pour a : disquette. Et int86(0x13, ®s, ®s) invoque le service d'interruption MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) écrit les informations de démarrage du fichier spécifié sur le premier secteur (spécifié) de la disquette.
- Le statut renvoyé est stocké dans le résultat qui est utilisé pour afficher le message de réussite de l'opération ou pour afficher un message d'erreur à l'écran en cas d'erreur.
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 |
Faisons-le avec un seul programme
J'espère que vous avez maintenant compris le concept derrière ce type de récupération de données à partir de la disquette. Après cela, imaginons un seul programme qui donne les mêmes résultats que nous avons obtenus avec l'aide des deux programmes précédemment discutés.
Nous effectuions les tâches suivantes avec les programmes récemment discutés :
- Stocker les informations de démarrage d'une bonne disquette dans un fichier
- Collez ces informations dans le premier secteur de la disquette actuellement illisible. Le fichier que nous utilisions pour stocker l'image de démarrage fonctionnait comme un pont intermédiaire pour connecter les opérations des deux programmes. Mais si nous définissons ces informations de démarrage dans le codage de notre programme lui-même, nous n'avons pas besoin de créer de fichier ni de lire les informations de démarrage de la disquette à partir du fichier.
Dans notre programme suivant, nous disons à notre programme ce qu'il doit écrire dans le premier secteur de la disquette illisible et ainsi nous pouvons éviter que deux programmes différents fassent la même tâche et nous pouvons récupérer notre données de la même manière qu'auparavant à partir du nouveau programme unique.
Le programme devient ainsi simple avec moins de codage et nous sommes en mesure de réduire la probabilité d'apparition d'erreurs de lecture, d'écriture ou de création de fichiers. Nous effectuons les quatre tâches importantes suivantes dans ce programme :
Ne pensez pas que le programme est difficile à écrire et à comprendre en voyant les informations hexadécimales de 512 octets de dbuf[512]. Plus tard, nous discuterons de la manière simple d'écrire ces informations pour votre programme codage.
- Définissez les informations d'enregistrement de démarrage DOS dans le système hexadécimal à écrire dans le premier secteur de la disquette actuellement illisible.
- Réinitialisez le système de disque pour initialiser la disquette (INT 13H, Fonction 00H).
- Écrivez l'enregistrement de démarrage DOS sur le premier secteur de la disquette
- Vérifier la réussite de l'opération et l'erreur, le cas échéant.
Examinons le programme :
/* Un seul programme pour charger l'image de démarrage par défaut sur une disquette illisible */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* Image de démarrage à charger dans le lecteur de disquette */
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");
/// Initialiser le système de disque \\\
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;
}
Dans ce programme de codage, nous procédons essentiellement à l'exécution des tâches suivantes, étape par étape :
- Le tampon de données de caractères statiques dbuf[512] fournit les informations de 512 octets en système hexadécimal, qui doivent être écrites dans le premier secteur de la disquette illisible. dbuf[512] indique à l'ordinateur pendant l'opération quelles informations doivent être écrites dans le premier secteur de la disquette. (Voir le programme suivant)
- dinfo pointe vers la structure diskinfo_t qui contient les informations des paramètres requis par l'opération effectuée par la fonction _bios_disk.
- Comme nous allons écrire les informations sur le premier secteur du disque, l'emplacement du secteur sera donc le suivant :
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 |
- Initialiser le système de disque à l'aide de l'interruption 13H (fonction 00h) où regs.h.ah = 0x00 pointe vers la fonction 00 H et regs.h.dl = 0x00 est utilisé pour a : disquette. Et int86(0x13, ®s, ®s) invoque le service d'interruption MS-DOS INT 13 H.
- _bios_disk(_DISK_WRITE, &dinfo) écrit les informations de démarrage du fichier spécifié sur le premier secteur (spécifié) de la disquette.
Le statut renvoyé est stocké dans le résultat qui est utilisé pour afficher le message de réussite de l'opération ou pour afficher un message d'erreur à l'écran en cas d'erreur.
Stocker l'image de démarrage en caractères hexadécimaux à utiliser dans notre programme précédent
Il sera très difficile d'écrire manuellement les 512 caractères de l'enregistrement de démarrage DOS de la disquette dans le système hexadécimal sans aucune erreur dans le programme dont nous avons récemment parlé. Si nous pouvons l'écrire avec précision, ce sera une tâche difficile et longue à faire. Utilisons un peu d'astuce pour stocker les données du tampon de données dbuf[512] dans un fichier.
Nous savons qu'en programmation C, les caractères hexadécimaux sont représentés par 0x de sorte que si le caractère hexadécimal est A9 H, nous l'écrirons dans notre programme C sous la forme 0xA9. Notre prochain programme fait la même chose. Il stockera les données que nous devons écrire dans notre programme précédent, comme les données du tampon de données dbuf[512].
Ce que vous avez à faire est simplement de prendre une nouvelle disquette pour créer l'image de son DBR et copier la sortie de ce programme à partir du fichier de destination spécifié et coller ces données dans votre programme. Faites un formatage si nécessaire. Voyons comment cela fonctionne :
/* Programme pour créer l'image de démarrage de la disquette en caractères 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);
}
/// Initialiser le système de disque \\\
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;
}
Commentaires sur le codage du programme :
Ainsi, les données sont stockées dans le fichier spécifié. Copiez simplement les données dans votre programme et effectuez le formatage requis. Vous ne devez jamais oublier les conseils suivants tout au long de la procédure :
- Assurez-vous que le fonctionnement du programme a réussi et que les données stockées dans le fichier de destination sont appropriées.
- Vous devez vérifier l'opération tout au long de l'apparition des erreurs attendues.
- Vous devez initialiser la disquette avec le programme avant de lire son secteur de démarrage. Vous pouvez utiliser la fonction 00H de INT 13H à cette fin.
Méthode – 2
Que faire si la méthode &ndash ; 1 ne fonctionne pas ?
Si la méthode – 1 ne fonctionne pas et que le disque illisible ne permet pas au programme de réécrire les informations de démarrage sur son premier secteur, vous devriez essayer cette deuxième méthode. La raison de l'échec de la première méthode peut être la corruption physique du premier secteur de la disquette.
Dans cette deuxième méthode, nous allons copier temporairement toutes les données de la surface de la disquette illisible dans un seul fichier, puis nous collerons cette image directement sur la surface d'un autre bon disque.
La procédure implique les deux étapes importantes suivantes :
- Secteur par secteur Copiez temporairement toutes les données de la surface du support de la disquette dans un seul fichier.
- Coller les données précédemment stockées dans le fichier, sur une nouvelle disquette telle quelle, sur les mêmes secteurs.
Copiez toutes les données de la surface média dans un seul fichier
Pour stocker toutes les données de la surface du support de disquette, le programme doit effectuer les trois tâches suivantes :
- Initialisez correctement le disque à l'aide de la fonction 00H de INT 13H.
- Lisez les informations secteur par secteur de la surface et stockez-les dans un seul fichier.
- Vérifier la réussite de l'opération de lecture (le plus important)
Il est très courant d'avoir un problème d'initialisation avec une disquette qui entraîne de nombreux messages de lecture infructueux. C'est pourquoi le disque doit être initialisé avant l'opération de lecture-écriture à l'aide de la programmation.
C'est l'étape la plus importante et la plus nécessaire en cas de tout type d'opérations appliquées sur disquette pour vérifier si l'opération a réussi ou non.
Si même après l'initialisation, la disquette récemment insérée ou la disquette modifiée provoque une erreur de lecture, il vous est conseillé de relancer le programme, il est fort probable que cela fonctionne cette fois.
Le programme suivant consiste à effectuer ces tâches spécifiées. Voyons comment ça se passe :
/* Programme pour stocker les données de surface physique de la disquette dans un fichier */
#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");
/// Initialiser le système de disque \\\
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);
}
}
}
}
Commentaires sur le codage du programme :
Dans le codage du programme donné précédemment, nous procédons essentiellement à l'exécution des tâches suivantes étape par étape :
- Le tableau de caractères filename[80] stocke le chemin défini par l'utilisateur et le nom du fichier dans lequel nous allons stocker temporairement les données.
- dinfo pointe vers la structure diskinfo_t qui contient les informations des paramètres requis par l'opération effectuée par la fonction _bios_disk.
- Initialiser le système de disque à l'aide de l'interruption 13H (fonction 00h) où regs.h.ah = 0x00 pointe vers la fonction 00 H et regs.h.dl = 0x00 est utilisé pour a : disquette. Et int86(0x13, ®s, ®s) invoque le service d'interruption MS-DOS INT 13 H.
- Comme nous allons lire toutes les informations de la surface du disque, les paramètres de _bios_disk seront les suivants :
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) lit les données de la surface physique de la disquette à partir du secteur spécifié par dinfo.
- Le statut renvoyé est stocké dans le résultat qui est utilisé pour afficher le message de réussite de l'opération ou pour afficher un message d'erreur à l'écran en cas d'erreur.
N'oubliez jamais que la taille du fichier qui contient l'image des données de la disquette doit être exactement de 1 474 560 octets car la disquette a 80 pistes (0 à 79), 2 faces ou têtes (tête 0 et tête 1) , chaque piste comporte 18 secteurs et chaque secteur contient les 512 octets de données, donc
Total bytes = (Number of tracks) * (Number of Heads) *
(Number of Sectors per Track) * 512
= 80*2*18*512
= 1,474,560 Bytes
Ainsi, s'il y a une erreur de lecture dans n'importe quel secteur de la disquette, cela changera la taille du fichier de 1 474 560 octets, ce qui rendra toute l'information complètement ou partiellement inutile pour le disque de destination sur lequel nous allons écrire l'image disque secteur par secteur à partir de ce fichier.
Il en est ainsi parce que l'ordinateur lit les informations de n'importe quel fichier sur la surface du support de la disquette dans la plage de secteurs telle qu'elle a été allouée dans son unité d'allocation. Maintenant, si les secteurs des données des fichiers sont modifiés, les informations complètes du fichier sont modifiées.
Penser à la solution de l'erreur de lecture de secteur(s)
Il est possible qu'une disquette défectueuse ou illisible ait une zone si défectueuse sur sa surface que nous ne puissions pas lire les informations à partir de la surface du disque.
Dans cette condition, les informations de ce(s) secteur(s) seront ignorées et l'image de la disquette sera déformée même pour les autres secteurs car la taille du fichier image dans ce cas diffère de 1 474 560 octets.
Pour conserver la taille du fichier image et pour coller le reste des informations sur les emplacements exacts des secteurs sur le disque de destination, nous écrivons d'autres informations au nom des données d'origine de 512 octets et de cette manière, nous’ ll sera en mesure de sauvegarder le reste des informations, mais la récupération dans ce cas peut être une récupération partielle.
Si votre système ne parvient pas non plus à lire le premier secteur de la disquette source, après avoir collé l'image sur la disquette de destination, vous devez exécuter le programme décrit précédemment, pour réécrire le enregistrement de démarrage DOS de la disquette .
Voyons comment nous pouvons le faire en programmant :
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
/*Information de 512 octets pour remplir l'espace du secteur défectueux */
/// J'ai utilisé 512 zéros pour remplir l'espace de 512 octets \\\
caractère statique 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");
/// Initialiser le système de disque \\\
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 le secteur n'est pas lisible, occupez 512 octets par dbuf2 */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
Commentaires sur le codage du programme :
Dans le codage du programme, chaque étape est identique à celle du programme précédent, à l'exception du tampon de données dbuf2[512], que nous utilisons pour gérer l'erreur générée par un secteur défectueux lors de l'opération de lecture du disque et pour maintenir la taille du fichier image.
En faisant cela, nous remplissons l'espace des informations que nous n'avons pas réussi à lire depuis le secteur défectueux et maintenant nous écrivons les pseudo-informations de 512 octets afin que nous puissions maintenir l'exactitude de l'image disque.
Collez les données du fichier sur la surface physique d'une nouvelle disquette :
Dans cette étape, nous collons les données stockées dans le fichier par le programme précédent, sur la surface physique de la nouvelle disquette, secteur par secteur de la même manière que nous les avons copiées dans le fichier.
Le programme se déroule selon les étapes principales suivantes :
- Ouvrez le fichier dans lequel nous avons stocké temporairement les données de surface de la disquette illisible.
- Initialisez correctement le système de disque par la fonction de réinitialisation 00H de INT 13H.
- Écrivez les informations sur les secteurs de la nouvelle disquette à partir du fichier.
- Afficher l'état d'écriture simultanément pour rechercher ou éviter l'apparition d'erreurs.
Le code source du programme a été donné ci-dessous. Voyons comment cela fonctionne :
/* Programme pour écrire les données sur les secteurs de la surface de la disquette fraîche à partir du fichier, créé par le programme précédent */
#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);
}
/// Initialiser le système de disque \\\
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);
}
}
}
}
Commentaires sur le codage du programme :
Dans le codage du programme donné précédemment, nous procédons essentiellement à l'exécution des tâches suivantes étape par étape :
- Le tableau de caractères filename[80] contient le chemin et le nom du fichier dans lequel nous avons temporairement stocké les données de la surface de la disquette illisible.
- dinfo pointe vers la structure diskinfo_t qui contient les informations des paramètres requis par l'opération effectuée par la fonction _bios_disk.
- Initialiser le système de disque à l'aide de l'interruption 13H (fonction 00h) où regs.h.ah = 0x00 pointe vers la fonction 00 H et regs.h.dl = 0x00 est utilisé pour a : disquette. Et int86(0x13, ®s, ®s) invoque le service d'interruption MS-DOS INT 13 H.
- Comme nous allons écrire les informations directement sur des secteurs de la surface du disque, les paramètres de _bios_disk seront les suivants :
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) écrit les données sur les secteurs de la surface physique de la disquette, spécifiés par dinfo.
- Le statut renvoyé est stocké dans le résultat qui est utilisé pour afficher le message de réussite de l'opération ou pour afficher un message d'erreur à l'écran en cas d'erreur.
Si après la méthode – 2 votre nouvelle disquette ne fonctionne pas, vous pouvez continuer à appliquer la méthode – 1 sur votre nouvelle disquette, que vous avez utilisée comme disque de destination lors de la méthode – 2.
Non seulement cela, mais aussi le nombre de hits et d'essais peuvent varier en fonction de la corruption du disque. Mais vous n'avez pas à vous inquiéter si même après vous n'obtenez pas de résultats satisfaisants.
Vous pouvez essayer la récupération fichier par fichier ou essayer de nombreux autres conseils que vous apprendrez dans la suite. Ici, nous mettrons en œuvre l'idée de collecter les informations de fichier à partir des répertoires racine, dans notre programmation pour récupérer les données.
Penser à la récupération logique des données supprimées ou perdues :
Tous les cas précédents dont nous avons discuté dans ce chapitre pour la récupération consistaient à récupérer les données dans les cas où nous nous attendions à ce que seul le DBR soit corrompu et les secteurs dans la piste 0, ayant FAT1, FAT2 et les répertoires racine sont lisibles.
Mais si le problème est dû à la corruption de la FAT ou si les données ont été supprimées du disque ou si vous souhaitez récupérer les données directement en lisant ses informations du répertoire racine, nous devons lire les informations telles que, nom du fichier, cluster de départ, taille du fichier , Attribut etc. à partir de son entrée de répertoire racine.
Comme nous avons déjà discuté du répertoire racine dans les chapitres précédents, il existe des informations de 32 octets pour chaque fichier ou répertoire. Ces 32 octets sont répartis comme suit :
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 |
Nous récupérons les données en lisant les informations du ou des fichiers à partir du répertoire racine, puis intégrons le fichier au chemin de destination et récupérons le fichier. Notre programme suivant effectue les étapes suivantes pour récupérer les données :
- Lisez les entrées du répertoire racine et affichez-les à l'écran avec toutes les informations telles que le nom du fichier/répertoire, l'extension du fichier, la taille du cluster de départ des fichiers en octets.
- Lisez les informations sur les fichiers et les répertoires dans les sous-répertoires et affichez-les si nécessaire.
- Confirmez le nom du fichier à récupérer et continuez la récupération.
- Calculez les informations CHS (cylindre, tête et secteur) pour le fichier spécifié à récupérer.
- Intégrez les données du fichier à partir de la zone de données du disque et enregistrez le fichier récupéré sous le nom de fichier de destination spécifié dans le chemin spécifié.
Ce programme ne se soucie pas de savoir si les informations de démarrage de la disquette sont lisibles ou non. Par conséquent, vous pouvez également récupérer des données supprimées à partir de la disquette corrompue. Voyons le codage du programme :
/* Programme pour récupérer les données de la disquette en lisant les informations de fichier du répertoire racine */
#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
}
/// Format de l'écran d'affichage des informations \\\
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 secteur à la fois. Chaque entrée de fichier/DIR prend 32 octets */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// Rechercher le nom du fichier/répertoire \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// Rechercher l'extension \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// Cluster de départ \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// Calculer la taille \\\
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
N'oubliez pas que le nom de fichier commençant par s (E5H) indique que le fichier a été supprimé et que le premier caractère du nom de fichier a donc été remplacé par s (voir la description du répertoire racine dans les chapitres précédents).
Et la sortie du programme est affichée comme ceci :
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 !!!
|
Commentaires sur le codage :
La fonction Display_Information consiste à lire les informations sur le fichier et le répertoire et à partir du répertoire racine. Dans la structure, nous lisons les informations de 32 octets pour chaque fichier ou répertoire avec root[32].
Les tableaux d'entiers non signés name[8] et ext[3] correspondent au nom de fichier ou de répertoire pour DOS au format 8.3 (huit points trois). De même, un octet est pour l'attribut et deux octets pour le cluster de départ. taille de l'entier long non signé ; est de stocker la taille du fichier de quatre octets.
La fonction _bios_disk lit le secteur spécifié par la structure finfo et l'état de l'opération est stocké dans result.
De toutes les informations de 512 octets lues par la fonction _bios_disk, jusqu'à la fin de la zone de répertoire racine, nous collectons les informations des fichiers et répertoires stockés sur le disque et affichez-les à l'écran.
L'entier file_no stocke le numéro du fichier ou du répertoire dans la liste, à partir de 0. Généralement la taille du répertoire racine est de 14 secteurs et le répertoire racine commence généralement à partir de Cylindre =0, Tête = 0 et Secteur =2 en cas de 1.44MB et 3½ disquette.
Si l'utilisateur donne le caractère ‘M’ ou ‘m’ en entrée, les informations du secteur suivant sont affichées si le choix de l'utilisateur est ‘R’ ou ‘r’ les fonctions de récupération sont appelées. Le codage de la fonction recover() a été donné ci-dessous :
/* Fonction pour démarrer la récupération du fichier spécifié */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/* Fonction d'intégration du fichier spécifié */
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));
/* Confirmez le nom du fichier à récupérer */
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);
/// Désolé, vous avez sélectionné un répertoire \\\
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')
{
/* Calculer la géométrie */
calculate(start,&cylinder,&head,§or);
/* Afficher le contenu du répertoire */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/* Calculer les informations CHS */
calculate(start,&cylinder,&head,§or);
/* Integrate The File */
integrate(size,cylinder,head,sector);
}
}
Commentaires sur le codage :
La fonction recover() consiste à obtenir l'entrée de l'utilisateur pour démarrer la récupération. Le numéro de fichier saisi par l'utilisateur pour récupérer le fichier est stocké dans file_no.
Si le numéro saisi est pour l'entrée du répertoire, Display_Information() affiche le contenu de ce répertoire, sinon le nom de fichier et l'extension du numéro de fichier file_no s'affichent à l'écran pour confirmer le fichier à récupérer.
Pour récupérer le fichier spécifié, les fonctions calculate() et integrate() sont appelées dans la fonction. Le codage de la fonction calculate() a été donné ci-dessous :
/* Fonction Pour calculer la Géométrie CHS Pour La Récupération */
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;
}
/// Afficher le CHS du fichier à récupérer \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
Commentaires sur le codage :
La fonction calculate() consiste à calculer les informations Cylindre, Tête et Secteur pour le fichier à récupérer. Après le calcul, les numéros de cylindre, de tête et de secteur sont affichés à l'écran.
Le codage de la fonctionintegrate() est donné ci-dessous :
/* Intégrer le fichier et enregistrer le fichier récupéré dans le chemin et le nom de fichier spécifiés */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/* Fonction de vérification du secteur pour les erreurs */
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;
/* Entrez le chemin de destination et le nom du fichier pour enregistrer le fichier récupéré */
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 une erreur s'est produite, afficher le message d'erreur et obtenir à nouveau le chemin d'entrée et le nom du fichier */
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 tout va bien, intégrez et écrivez */
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);
}
Commentaires sur le codage :
La fonction integrate() est le module réel d'exécution de la récupération du fichier spécifié par l'utilisateur, dans ce programme de récupération.
Le nom du fichier avec le chemin de destination pour stocker le fichier récupéré est stocké dans le pointeur de caractère *Filename_with_path. S'il y a une erreur lors de l'ouverture du fichier de destination, un message d'erreur s'affiche et l'utilisateur est à nouveau invité à saisir la destination.
La fonction _bios_disk(_DISK_READ, &dinfo); lit les données du fichier depuis la zone de données du disque secteur par secteur, spécifiée par la structure dinfo et stockée dans le tampon de données buf . Ces données de 512 octets sont écrites dans le fichier destination. Ceci est répété jusqu'à ce que le fichier complet soit intégré.
La fonction status=verify_the_sector (cylindre, tête, secteur) ; vérifie le secteur à lire. Si le statut = 10, cela représente un mauvais secteur (0xA). Le codage de la fonction a été donné ci-dessous :
/// Vérifiez le secteur. (Aucune donnée n'est transférée ici) \\\
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);
}
Commentaires sur le codage :
La fonction verify_the_sector() vérifie le secteur à lire par la fonction _bios_disk() et renvoie le statut de l'opération. La fonction utilise INT 13H et la fonction 4H pour vérifier le secteur.
*buf est le tampon de données, 0x04 est le numéro de fonction spécifié par in.h.ah = 0x04 ; et in.h.al = 1 ; demande de vérifier un secteur à la fois. in.h.dl = 0x00 ; est utilisé pour le numéro de lecteur du lecteur de disquette A :, c, h et s sont les numéros de cylindre, tête et secteur.
La fonction int86x() est utilisée pour invoquer INT 13H (fonction 4H) avec des valeurs de registre de segment. Le statut de l'opération est renvoyé par l'entier status.
La fonction clear_the_line() efface la ligne spécifiée à l'écran. Le codage de la fonction est le suivant :
/* Fonction pour effacer la ligne sur l'écran, pour le numéro de ligne spécifié */
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 " " */
}
}
Commentaires sur le codage :
La fonction est utilisée pour effacer la ligne spécifiée sur l'écran. La fonction est appelée avec le numéro de ligne à effacer de l'écran.
Page modifiée le: 09/03/2022