章 – 10
破損したフロッピーからのデータ回復
破損したフロッピーからのデータ回復
フロッピーは、データストレージの最も信頼性の低いソースの1つです。コンピュータシステムを使用している組織に行って、フロッピーディスクによって発生する問題について従業員に尋ねると、組織の従業員がフロッピーに重要なデータを持っていたが、フロッピーはそうではないという問題をよく耳にします。コンピュータで読み取り可能で、メッセージは次のように表示されます。
“ディスクを読み取れません”
“トラック0悪い”
“ドライブまたは容量が無効です”
“ディスクはフォーマットされていません。今すぐフォーマットしますか?”
これは、コンピュータシステムとフロッピーを使用する組織にとって日常的な問題です。破損したフロッピーディスクで失われたと思われるデータのバックアップが作成されていないこと、またはバックアップが利用できないことがわかった場合、問題は重大になります。
問題の最大の地獄は、重要な情報のためにフロッピーにバックアップを作成するとき、ウイルス攻撃を克服するためにアンチウイルスプログラムのディスクをレスキューするとき、またはフロッピーでレコードまたは他のバックアップ(多くの可能性があるかもしれません)を起動するときに来ると思われます。フロッピーからバックアップを再利用したい場合、読み取りエラーが発生します。
このような状況では、重要な情報やデータが失われようとしている場合や、場合によってはバックアップが不足していると感じた場合でも、 回復プログラム あなたのためにコンピュータの起動情報と ウイルス攻撃レスキュープログラム など、現在コンピュータで読み取れないフロッピーに保存されている情報が不足しているために発生したOSクラッシュの形でデータが大幅に失われる可能性があります。
そのような場合、それは最も重要な要件になります データを回復する コンピュータシステムによって不良と宣言されたフロッピーから。
フロッピーが読めない理由
フロッピーにそのようなタイプのエラーメッセージを表示させる最も一般的な問題は、フロッピーのDOSブートレコード(DBR)の破損です。これは、コンピュータがフロッピーの論理的な識別を知るのに役立ちます。
DBR は、トラック0、ヘッド0、セクター1に格納されている小さなプログラムで、次のようなフロッピーに関する重要な情報が含まれています。
- セクターあたりのバイト数
- クラスターごとのセクター
- FATの数
- ルートディレクトリなどの最大数。
フロッピーには論理パーティションシステムがないため、フロッピーで使用できるMBRはありません。フロッピーの最初のセクターはDBRを保持します。これは、ハードディスクの論理構造をフロッピーと比較する場合の主な違いでもあります。
ディスク編集プログラムを使用してフロッピーのブートセクタ情報を読み取ると、次の図のような情報が表示されます。
次の図は、1.44MBのDBRの512バイト情報を示しています。 3½ インチフロッピー。
この情報が何らかの方法で破損したり、読み取れなくなったりすると、フロッピーディスクによってそのような読み取りエラーメッセージが表示されます。ディスクの最初のセクターの物理的または論理的な破損が原因である可能性があります。
論理的破損には、フロッピーの最初のセクターの情報が変更された場合、論理的不良セクターまたは DBR が発生した場合が含まれます。その他の理由でフロッピーが破損しています。
フロッピーディスクの最初のセクターに物理的な不良セクター(セクター1が物理的に損傷していることを意味します)がある場合、物理的な破損が発生することになっています。フロッピーのトラック0に複数の不良セクタがあることがわかった場合、問題はさらに深刻になります。
回復する方法
破損の両方の原因を学習したので、問題を理解できるようになったことを願っています。 論理的な破損からデータを回復することはそれほど難しいことではありませんが、物理的な破損からの回復にはもう少し努力が必要です。
方法 – 1
新鮮なフロッピーのブートイメージを保存します
問題が論理的である場合、どうすればよいかがわかります。 データを回復する. 同じサイズと容量の別のフロッピーから適切なブートレコードを取得し、それを読み取り不可能なフロッピーの最初のセクターに貼り付けるだけです。問題はのために作成されましたが 不正なブートレコード, 今は動作するはずです。
この手順には2つのステップがあり、それに従って、読み取り不可能なフロッピーからデータを回復します。
- 良いフロッピーのDOSブートレコードのイメージを作成する
- 読み取り不可能なフロッピーの最初のセクターにブートイメージを貼り付ける
良いフロッピーのDOSブートレコードのイメージを作成する
フレッシュフロッピーのブートレコードのイメージを保存するには、プログラムは次の3つのタスクを実行する必要があります。
- 適切なフロッピーの最初の512バイトを正確に読み取ります
- 読み取り操作が成功したかどうかを確認します(最も重要)
- これらの512バイトを指定されたファイル名と宛先パスに保存します
フロッピーのセクターは512バイトであり、セクターの正確なイメージをコピーする必要があります。フロッピーに何らかの種類の操作を適用する場合は、操作が成功したかどうかを確認することが最も重要で必要な手順です。
フロッピーディスクが正常で新しい場合でも、初期化の問題が発生する可能性があります。そのため、フロッピーディスクで操作を行う場合のほとんどは、まずフロッピーディスクの初期化をプログラミングで行います。 ディスク操作のリセット (INT13Hの機能00H)。
初期化した後でも、最近挿入したフロッピーディスクまたは変更したフロッピーディスクで読み取りエラーが発生した場合は、プログラムを再実行することをお勧めします。おそらく今回は動作する可能性があります。
次のプログラムは、これらの指定されたタスクを実行するためのものです。それがどのように進行するか見てみましょう:
/* ブートイメージを新しいフロッピーディスクからファイルに保存します */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
static char dbuf[512];
FILE *fp;
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
clrscr();
gotoxy(10,3);cprintf("Enter The File Name And Path To
Store Boot Image");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"wb");
if((fp=fopen(fname,"wb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be created");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// ディスクシステムを初期化する \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
while(count<512)
{
fprintf(fp,"%c",dbuf[count] & 0xff );
count++;
}
fclose(fp);
gotoxy(10,14);cprintf("Disk read from Floppy disk drive
: successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n", result);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
プログラムコーディングに関するコメント:
前述のプログラムコーディングでは、基本的に次のタスクを段階的に実行します。
- dinfoは、_bios_disk関数によって実行される操作に必要なパラメーターの情報を含むdiskinfo_t構造体を指します。
- ディスクの最初のセクターを読み取りたいので、セクターの場所は次のようになります。
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- ユーザーが指定したファイル名とパスのファイルストリームを開き、正確に512バイトのブートイメージ情報を保存します。ファイル名とパスは文字配列fnameに格納されます。
- 割り込み13H(関数00h)を使用してディスクシステムを初期化します。ここで、regs.h.ah = 0x00は関数00Hを指し、regs.h.dl = 0x00はフロッピーに使用されます。そしてint86(0x13、 ®s, ®s) MS-DOS割り込みサービスINT13Hを呼び出します。
- _bios_disk(_DISK_READ、 &dinfo) フロッピーディスクの指定されたセクターを読み取ります。
- 返されたステータスは結果に保存され、正常に動作するためのメッセージを表示したり、エラーが発生した場合に画面にエラーメッセージを表示したりするために使用されます。
読み取り不可能なフロッピーの最初のセクターにブートイメージを貼り付ける
ファイルから読み取り不可能なフロッピーの最初のセクターにブートイメージを貼り付けるには、プログラムで次の3つの主要なタスクを実行する必要があります。
- 以前に保存したファイルから新しいフロッピーのブートレコードの正確な512バイトの情報を読み取ります。
- この情報を、現在読み取れないフロッピーの最初のセクターに書き込みます。
- 書き込み操作が正常に完了したことを確認します(最も重要)。
フロッピーのセクターは512バイトであるため、正確なブートイメージをセクターに貼り付ける必要があります。フロッピーに何らかの種類の操作を適用する場合は、操作が成功したかどうかを確認することが最も重要で必要な手順です。
操作中にフロッピーディスクに初期化の問題がある可能性があるため、ディスクシステムをリセットして(INT 13Hの関数00Hを使用して)ディスクを初期化する必要があります。
初期化した後でも、最近挿入したフロッピーディスクまたは変更したフロッピーディスクで読み取りエラーが発生した場合は、プログラムを再実行することをお勧めします。おそらく今回は動作する可能性があります。
次のプログラムは、これらの指定されたタスクを実行するためのものです。それがどのように進行するか見てみましょう:
/* 読み取り不可能なフロッピーにブートイメージをロードします */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs;
int result;
int count=0, i;
char fname[80];
char dbuf[512];
FILE *fp;
clrscr();
gotoxy(5,3);cprintf("Enter The File Name And Path, In Which Boot image of Floppy Is Stored");
gotoxy(5,5);
gets(fname);
fp=fopen(fname,"rb");
if((fp=fopen(fname,"rb"))==NULL)
{
highvideo();
gotoxy(10,10);cprintf("File Could Not Be Opened");
getch();
exit(0);
}
gotoxy(10,9);
cprintf("Attempting to Recover Floppy disk drive :\n");
/// ディスクシステムを初期化する \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
while(count<512)
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
fclose(fp);
gotoxy(10,14);cprintf("Successful!!! I Hope Floppy May
Work Now.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13H extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
プログラムコーディングに関するコメント:
前述のプログラムコーディングでは、基本的に次のタスクを段階的に実行します。
- dinfoは、_bios_disk関数によって実行される操作に必要なパラメーターの情報を含むdiskinfo_t構造体を指します。
- ディスクの最初のセクターに情報を書き込むため、セクターの場所は次のようになります。
- 前のプログラムで512バイトの新しいフロッピーのブートイメージ情報が保存されているファイルを開きます。ファイル名とパスは文字配列fnameに保存されます。
- 割り込み13H(関数00h)を使用してディスクシステムを初期化します。ここで、regs.h.ah = 0x00は関数00Hを指し、regs.h.dl = 0x00はフロッピーに使用されます。そしてint86(0x13、 ®s, ®s) MS-DOS割り込みサービスINT13Hを呼び出します。
- _bios_disk(_DISK_WRITE、 &dinfo) 指定されたファイルからフロッピーディスクの最初の(指定された)セクターにブート情報を書き込みます。
- 返されたステータスは結果に保存され、正常に動作するためのメッセージを表示したり、エラーが発生した場合に画面にエラーメッセージを表示したりするために使用されます。
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
単一のプログラムでやってみましょう
このようなタイプのフロッピーディスクからのデータ回復の背後にある概念を理解できたと思います。この後、前に説明した2つのプログラムの助けを借りて得たのと同じ結果をもたらす単一のプログラムを想像してみましょう。
最近議論されたプログラムを使用して、次のタスクを実行していました。
- 起動情報を適切なフロッピーディスクからファイルに保存します
- この情報を現在読み取れないフロッピーの最初のセクターに貼り付けます。ブートイメージの保存に使用していたファイルは、両方のプログラムの操作を接続するための中間ブリッジとして機能していました。ただし、プログラムコーディング自体でこのブート情報を定義する場合は、ファイルを作成する必要はなく、ファイルからフロッピーのブート情報を読み取る必要もありません。
次のプログラムでは、読み取り不可能なフロッピーディスクの最初のセクターに何を書き込む必要があるかをプログラムに伝えます。したがって、2つの異なるプログラムが同じタスクを実行することを回避でき、データを回復できます新しい単一プログラムから以前と同じように。
このように、プログラムはコーディングが少なくてシンプルになり、ファイルの読み取り、書き込み、または作成エラーの発生の可能性を減らすことができます。このプログラムでは、次の4つの重要なタスクを実行しています。
の512バイトの16進情報を見て、プログラムを作成して理解するのが難しいとは思わないでください。 dbuf[512]. 後で、プログラムコーディングのためにこの情報を書く簡単な方法について説明します。
- 現在読み取り不可能なフロッピーの最初のセクターに書き込まれる16進システムのDOSブートレコード情報を定義します。
- ディスクシステムをリセットしてフロッピーディスクを初期化します(INT 13H、機能00H)。
- DOSブートレコードをフロッピーの最初のセクターに書き込みます
- 操作が正常に完了し、エラーが発生した場合はエラーが発生したかどうかを確認します。
プログラムを調べてみましょう。
/* 読み取り不可能なフロッピーディスクにデフォルトのブートイメージをロードする単一のプログラム */
#include <bios.h>
#include <stdio.h>
int main(void)
{
struct diskinfo_t dinfo;
union REGS regs:
int result, i;
/* フロッピーディスクドライブにロードされるブートイメージ*/
static char dbuf[512]=
{
0xEB,0x3E,0x90,0x2B,0x29,0x6E, 0x70,0x32,0x49,0x48,0x43,0x0,0x2 ,0x1 ,0x1 ,0x0,
0x2,0xE0,0x0,0x40,0xB,0xF0,0x9,0x0,0x12, 0x0 ,0x2 ,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x29, 0x24,0x3B,0xDB, 0x16,0x4E, 0x4F, 0x20, 0x4E,0x41,0x4D,0x45,
0x20, 0x20, 0x20,0x20,0x46,0x41, 0x54,0x31, 0x32,0x20,0x20, 0x20,0xF1,0x7D, 0xFA,
0x33, 0xC9,0x8E,0xD1, 0xBC,0xFC,0x7B, 0x16,0x7 ,0xBD,0x78,0x0 ,0xC5,0x76,0x0,
0x1E,0x56,0x16,0x55, 0xBF,0x22,0x5 ,0x89,0x7E,0x0 ,0x89,0x4E,0x2 ,0xB1,0xB,0xFC,
0xF3,0xA4,0x6 ,0x1F,0xBD,0x0,0x7C ,0xC6,0x45,0xFE,0xF,0x8B, 0x46,0x18,0x88,0x45,
0xF9,0xFB,0x38,0x66, 0x24,0x7C,0x4,0xCD,0x13, 0x72,0x3C,0x8A,
0x46,0x10,0x98,0xF7,
0x66,0x16,0x3, 0x46,0x1C,0x13,0x56, 0x1E,0x3 ,0x46,0xE,0x13,
0xD1,0x50,0x52,0x89,
0x46,0xFC,0x89, 0x56,0xFE,0xB8,0x20,0x0, 0x8B,0x76,0x11,0xF7,
0xE6,0x8B,0x5E,0xB ,
0x3 ,0xC3,0x48,0xF7,0xF3,0x1,0x46,0xFC, 0x11,0x4E,0xFE,0x5A,
0x58,0xBB,0x0 ,0x7 ,
0x8B,0xFB,0xB1,0x1, 0xE8,0x94,0x0 ,0x72,0x47,0x38,0x2D,0x74, 0x19,0xB1,0xB,0x56,
0x8B,0x76,0x3E, 0xF3,0xA6,0x5E,0x74,0x4A,0x4E, 0x74,0xB,0x3 , 0xF9,0x83, 0xC7, 0x15,
0x3B, 0xFB,0x72,0xE5,0xEB,0xD7,0x2B, 0xC9,0xB8,0xD8, 0x7D, 0x87, 0x46, 0x3E,0x3C,
0xD8,0x75,0x99, 0xBE,0x80,0x7D,0xAC, 0x98,0x3,0xF0,0xAC,0x84 ,0xC0,0x74,0x17,0x3C,
0xFF,0x74,0x9 ,0xB4,0xE ,0xBB,0x7 ,0x0,0xCD,0x10,0xEB, 0xEE,0xBE,0x83,0x7D, 0xEB,
0xE5, 0xBE, 0x81,0x7D, 0xEB,0xE0, 0x33,0xC0,0xCD,0x16,0x5E,0x1F,0x8F,0x4 ,0x8F,0x44,
0x2,0xCD, 0x19,0xBE,0x82,0x7D,0x8B,0x7D,0xF, 0x83,0xFF,0x2,0 x72,0xC8, 0x8B,0xC7,0x48,
0x48,0x8A,0x4E,0xD,0xF7,0xE1,0x3 ,0x46,0xFC, 0x13,0x56,0xFE,0xBB,0x0 ,0x7 ,0x53,0xB1,0x4 ,
0xE8,0x16,0x0, 0x5B,0x72,0xC8, 0x81,0x3F,0x4D,0x5A, 0x75,0xA7,0x81,0xBF, 0x0,0x2 ,0x42,0x4A,
0x75,0x9F,0xEA,0x0 ,0x2 ,0x70,0x0,0x50,0x52, 0x51, 0x91, 0x92, 0x33, 0xD2,0xF7,0x76,0x18,0x91,
0xF7,0x76, 0x18,0x42, 0x87, 0xCA, 0xF7, 0x76,0x1A,0x8A,0xF2,0x8A,0x56, 0x24,0x8A,0xE8,
0xD0, 0xCC,0xD0,0xCC,0xA, 0xCC,0xB8,0x1,0x2, 0xCD,0x13,0x59,0x5A, 0x58, 0x72,0x9,0x40,
0x75,0x1,0x42,0x3, 0x5E,0xB,0xE2,0xCC,0xC3,0x3 ,0x18 ,0x1 ,0x27,0xD ,0xA,0x49, 0x6E,
0x76,0x61,0x6C,0x69,0x64,0x20, 0x73, 0x79, 0x73, 0x74, 0x65,0x6D,0x20,0x64,0x69,0x73,
0x6B,0xFF,0xD ,0xA,0x44,0x69, 0x73,0x6B,0x20, 0x49,0x2F, 0x4F,0x20, 0x65,0x72, 0x72,0x6F,
0x72,0xFF,0xD ,0xA,0x52, 0x65,0x70,0x6C,0x61,0x63, 0x65,0x20,
0x74,0x68, 0x65, 0x20,
0x64, 0x69,0x73, 0x6B,0x2C,0x20,0x61, 0x6E,0x64,0x20,0x74, 0x68, 0x65, 0x6E, 0x20,0x70,
0x72,0x65, 0x73,0x73, 0x20,0x61, 0x6E,0x79,0x20,0x6B,0x65,0x79,0xD,0xA, 0x0,0x49,0x4F,
0x20,0x20,0x20,0x20, 0x20,0x20,0x53,0x59,0x53,0x4D, 0x53, 0x44, 0x4F, 0x53,0x20,0x20,
0x20,0x53, 0x59,0x53, 0x80,0x1,0x0 ,0x57,0x49, 0x4E,0x42, 0x4F,0x4F,0x54,0x20,0x53, 0x59
,0x53,0x0,0x0,0x55,0xAA};
clrscr();
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = 0; /* disk head number */
dinfo.track = 0; /* track number */
dinfo.sector = 1; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
gotoxy(10,9);
cprintf("Attempting to read from Floppy disk drive :\n");
/// Initialize the Disk System \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
result = _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
{
gotoxy(10,14);
cprintf("Disk Write Status :successful.\n");
}
else
{
gotoxy(10,14);
cprintf("Cannot read drive A, status = 0x%02x\n",
result);
gotoxy(10,16);
switch(result)
{
case 0x00:
cprintf("\n\n STATUS: No Error!!");
break;
case 0x01:
cprintf("\n\n STATUS: Bad command");
break;
case 0x02:
cprintf("\n\n STATUS: Address mark not found");
break;
case 0x03:
cprintf("\n\n STATUS: Attempt to write to write-
protected disk");
break;
case 0x04:
cprintf("\n\n STATUS: Sector not found");
break;
case 0x06:
cprintf("\n\n STATUS: Disk changed since last operation");
break;
case 0x08:
cprintf("\n\n STATUS: Direct memory access (DMA) overrun");
break;
case 0x09:
cprintf("\n\n STATUS: Attempt to perform DMA across 64K boundary");
break;
case 0x0C:
cprintf("\n\n STATUS: Media type not found");
break;
case 0x10:
cprintf("\n\n STATUS: Bad CRC/ECC on disk read");
break;
case 0x20:
cprintf("\n\n STATUS: Controller has failed");
break;
case 0x31:
cprintf("\n\n STATUS: No media in drive (IBM/MS INT 13H extensions)");
break;
case 0x32:
cprintf("\n\n STATUS: Incorrect drive type stored in CMOS (Compaq)");
break;
case 0x40:
cprintf("\n\n STATUS: Seek operation failed");
break;
case 0x80:
cprintf("\n\n STATUS: Attachment failed to respond(Disk Timed-out)");
break;
case 0xB0:
cprintf("\n\n STATUS: Volume not locked in drive (INT 13H extensions)");
break;
case 0xB1:
cprintf("\n\n STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("\n\n STATUS: Volume not removable (INT 13H extensions)");
break;
case 0xB3:
cprintf("\n\n STATUS: Volume in use (INT 13 extensions)");
break;
case 0xB4:
cprintf("\n\n STATUS: Lock count exceeded (INT 13H extensions)");
break;
case 0xB5:
cprintf("\n\n STATUS: Valid eject request failed (INT 13H extensions)");
break;
default: cprintf("\n\n STATUS: UNKNOWN Status CODE For Floppy Errors");
}
}
return 0;
}
このプログラムコーディングでは、基本的に次のタスクを段階的に実行します。
- 静的文字データバッファdbuf [512]は、16進システムで512バイトの情報を提供します。これは、読み取り不可能なフロッピーの最初のセクターに書き込まれます。 dbuf [512]は、操作中に、フロッピーの最初のセクターに書き込まれる情報をコンピューターに通知します。 (次のプログラムを参照)
- dinfoは、_bios_disk関数によって実行される操作に必要なパラメーターの情報を含むdiskinfo_t構造体を指します。
- ディスクの最初のセクターに情報を書き込むため、セクターの場所は次のようになります。
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = 0 |
It points to head number 0 |
dinfo.track = 0 |
It points to track 0 |
dinfo.sector = 1 |
First sector of the floppy that is sector 1 |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- 割り込み13H(関数00h)を使用してディスクシステムを初期化します。ここで、regs.h.ah = 0x00は関数00Hを指し、regs.h.dl = 0x00はフロッピーに使用されます。そしてint86(0x13、 ®s, ®s) MS-DOS割り込みサービスINT13Hを呼び出します。
- _bios_disk(_DISK_WRITE、 &dinfo) 指定されたファイルからフロッピーディスクの最初の(指定された)セクターにブート情報を書き込みます。
返されたステータスは結果に保存され、正常に動作するためのメッセージを表示したり、エラーが発生した場合に画面にエラーメッセージを表示したりするために使用されます。
以前のプログラムで使用する16進文字でのブートイメージの保存
フロッピーの512文字すべてを書くのは非常に難しい仕事になります’s 最近説明したプログラムでエラーが発生することなく、16進法で手動でDOSブートレコードを作成します。それを正確に書くことができれば、それを行うのは困難で時間のかかる作業になります。トリッキーな心を使って、データバッファdbuf [512]のデータをファイルに保存しましょう。
Cプログラミングでは、16進文字は0xで表されるため、16進文字がA9 Hの場合、Cプログラムではこれを0xA9と記述します。次のプログラムも同じことをしています。以前のプログラムで書き込む必要のあるデータを、データバッファdbuf [512]のデータとして保存します。
必要なのは、新しいフロッピーを取り出してDBRのイメージを作成し、指定された宛先ファイルからこのプログラムの出力をコピーして、このデータをプログラムに貼り付けることです。必要に応じてフォーマットを行います。それがどのように機能するか見てみましょう:
/ * フロッピーディスクのブートイメージを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);
}
/// ディスクシステムを初期化します \\\
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;
}
プログラムのコーディングに関するコメント:
したがって、データは指定されたファイルに保存されます。データをプログラムにコピーして、必要なフォーマットを行うだけです。手順全体を通して、次のヒントを決して忘れないでください。
- プログラムの操作が成功し、宛先ファイルに保存されているデータが適切であることを確認してください。
- 予想されるエラーの発生がないか、操作全体を確認する必要があります。
- ブートセクタを読み取る前に、プログラムを使用してフロッピーディスクを初期化する必要があります。この目的のために、INT13Hの機能00Hを使用することができます。
方法 – 2
メソッドの場合の対処方法 – 1 動作しませんか?
メソッドの場合 – 1が機能せず、読み取り不可能なディスクがプログラムに最初のセクターのブート情報の再書き込みを許可していないため、この2番目の方法を試す必要があります。最初の方法の失敗の背後にある理由は、 物理的な破損 フロッピーディスクの最初のセクターの。
この2番目の方法では、読み取り不可能なフロッピーの表面のすべてのデータを一時的に1つのファイルにコピーしてから、この画像を別の正常なディスクの表面に直接貼り付けます。
この手順には、次の2つの重要な手順が含まれます。
- セクターごとフロッピーの表面のすべてのデータをコピーします’s メディアを一時的に単一のファイルに。
- 以前にファイルに保存されたデータを、同じセクターの新しい新しいフロッピーにそのまま貼り付けます。
メディア表面のすべてのデータを1つのファイルにコピーします
フロッピーのメディアの表面のすべてのデータを保存するには、プログラムは次の3つのタスクを実行する必要があります。
- INT 13Hの機能00Hを使用して、ディスクを適切に初期化します。
- サーフェスのセクターごとの情報を読み取り、単一のファイルに保存します。
- 読み取り操作が成功したかどうかを確認します(最も重要)
フロッピーディスクで初期化の問題が発生し、多くの読み取りメッセージが失敗することがよくあります。そのため、プログラミングを使用して、読み取り/書き込み操作の前にディスクを初期化する必要があります。
フロッピーに何らかの種類の操作を適用する場合は、操作が成功したかどうかを確認することが最も重要で必要な手順です。
初期化した後でも、最近挿入したフロッピーディスクまたは変更したフロッピーディスクで読み取りエラーが発生した場合は、プログラムを再実行することをお勧めします。おそらく今回は動作する可能性があります。
次のプログラムは、これらの指定されたタスクを実行するためのものです。それがどのように進行するか見てみましょう:
/ * フロッピーディスクの物理的表面のデータをファイルに保存するプログラム */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File,
Press any Key To EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// ディスクシステムを初期化します \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result,head,track,sector);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track,head,sector);
}
}
}
}
プログラムコーディングに関するコメント:
前述のプログラムコーディングでは、基本的に次のタスクを段階的に実行します。
- Character array filename [80]は、データを一時的に保存するファイルのユーザー定義のパスとファイル名を保存します。
- dinfoは、_bios_disk関数によって実行される操作に必要なパラメーターの情報を含むdiskinfo_t構造体を指します。
- 割り込み13H(関数00h)を使用してディスクシステムを初期化します。ここで、regs.h.ah = 0x00は関数00Hを指し、regs.h.dl = 0x00はフロッピーに使用されます。そしてint86(0x13、 ®s, ®s) MS-DOS割り込みサービスINT13Hを呼び出します。
- ディスクの表面のすべての情報を読み取るため、_bios_diskのパラメーターは次のようになります。
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for read operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_READ, &dinfo) 物理的な表面からデータを読み取ります dinfoで指定されたセクターからのフロッピーディスクの。
- 返されたステータスは結果に保存され、正常に動作するためのメッセージを表示したり、エラーが発生した場合に画面にエラーメッセージを表示したりするために使用されます。
フロッピーの画像を保持するファイルのサイズを常に覚えておいてください フロッピーには80トラック(0〜79)、2つのサイドまたはヘッド(ヘッド0とヘッド1)があり、各トラックには18セクターがあり、各セクターには512バイトのデータが含まれているため、ディスクのデータは正確に1,474,560バイトである必要があります。
Total bytes = (Number of tracks) * (Number of Heads) *
(Number of Sectors per Track) * 512
= 80*2*18*512
= 1,474,560 Bytes
したがって、フロッピーディスクのいずれかのセクターで読み取り中にエラーが発生すると、ファイルのサイズが1,474,560バイトから変更され、情報全体が完全にまたは部分的に、使用先のディスクで使用できなくなります。このファイルからセクターごとにディスクイメージを書き込みます。
これは、コンピュータがフロッピーディスクのメディアの表面にあるファイルの情報を、アロケーションユニットに割り当てられているセクター範囲内で読み取るためです。これで、ファイルのデータのセクターが変更されると、完全なファイル情報が変更されます。
セクターの読み取りエラーの解決策を考える
フロッピーが不良または読み取り不能の場合、フロッピーの表面に不良領域があり、ディスクの表面から情報を読み取れない可能性があります。
この状態では、このセクターの情報はスキップされ、この場合の画像ファイルのサイズが1,474,560バイトと異なるため、他のセクターでもフロッピーの画像が歪んでしまいます。
画像ファイルのサイズを維持し、残りの情報を宛先ディスクの正確なセクター位置に貼り付けるために、512バイトの元のデータに代わって他の情報を書き込みます。このようにして、 残りの情報を保存することはできますが、そのような場合の回復は部分的な回復である可能性があります。
システムがソースフロッピーの最初のセクターも読み取れない場合は、イメージを宛先フロッピーに貼り付けた後、前述のプログラムを実行して、フロッピーの DOSブートレコードを書き換える必要があります。
プログラミングによってそれを行う方法を見てみましょう。
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
/ * 不良セクタのスペースを埋めるための512バイトの情報 */
/// 512バイトのスペースを埋めるために512個のゼロを使用しました \\\
static char dbuf2 [512] =
"00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000" "00000000000000000000000000000000";
FILE *tt;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((tt=fopen(filename,"wb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(0);
}
printf("\n Initializing Floppy Disk System...\n");
/// ディスクシステムを初期化します \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
else
{
printf("Cannot read drive A, status =
0x%02x\t%d\t%d\t%d\n", result, head, track, sector);
/ * セクターが読み取り可能でない場合、dbuf2によって512バイトを占有します */
fwrite(dbuf2,512,1,tt);
}
printf("Reading Track= %d Head= %d Sector= %d\n",
track, head, sector);
}
}
}
}
プログラムコーディングに関するコメント:
プログラムのコーディングでは、ディスク読み取り操作中に不良セクタによって生成されたエラーを処理するために使用しているデータバッファdbuf2 [512]を除いて、すべてのステップは前のプログラムと同じです。画像ファイルのサイズを維持します。
これにより、不良セクタから読み取れなかった情報のスペースを埋め、512バイトの疑似情報を書き込んでいます。ディスクイメージの精度を維持するためです。
データをファイルから新しいフロッピーの物理的な表面に貼り付けます:
このステップでは、前のプログラムによってファイルに保存されたデータを、ファイルにコピーしたのと同じ方法で、セクターごとに新しいフロッピーの物理的な表面に貼り付けます。
プログラムは、次の主要な手順に進みます。
- 読み取り不可能なフロッピーの表面データを一時的に保存したファイルを開きます。
- INT 13Hのリセット機能00Hを使用して、ディスクシステムを適切に初期化します。
- ファイルから新しいフロッピーのセクターに関する情報を書き込みます。
- 書き込みステータスを同時に表示して、エラーの発生を検出または回避します。
プログラムのソースコードを以下に示します。それがどのように機能するかを調べてみましょう:
/ * 前のプログラムで作成された、ファイルから新しいフロッピーの表面のセクターにデータを書き込むプログラム */
#include <bios.h>
#include <stdio.h>
void main(void)
{
int head,track;
union REGS regs;
int result,i,sector;
int count =0;
char filename[80];
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *fp;
clrscr();
printf("\n Enter The Name of file with Path to store The
Data Temporarily\n");
gets(filename);
if((fp=fopen(filename,"rb"))==NULL)
{
printf("Could Not Create The File, Press any Key To
EXIT");
getch();
exit(1);
}
/// ディスクシステムを初期化します \\\
for(i=0; i<3; i++)
{
regs.h.ah = 0x00; /* Reset Disk System */
regs.h.dl = 0x00; /* Floppy Disk a: */
int86(0x13, ®s, ®s);
}
for(track=0;track<=79;track++)
{
for(head=0;head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
count =0;
while(count<512 )
{
fscanf(fp,"%c",&dbuf[count]);
count++;
}
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector;/* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
result= _bios_disk(_DISK_WRITE, &dinfo);
if ((result & 0xff00) == 0)
printf("Successful write on Track = %d, Head = %d,
Sector = %d.\n", track, head, sector);
else
printf("Cannot read drive A, status = 0x%02x\n",
result);
}
}
}
}
プログラムコーディングに関するコメント:
前述のプログラムコーディングでは、基本的に次のタスクを段階的に実行します。
- Character array filename [80]は、読み取り不可能なフロッピーの表面のデータを一時的に保存したファイルのパスとファイル名を保持します。
- dinfoは、_bios_disk関数によって実行される操作に必要なパラメーターの情報を含むdiskinfo_t構造体を指します。
- 割り込み13H(関数00h)を使用してディスクシステムを初期化します。ここで、regs.h.ah = 0x00は関数00Hを指し、regs.h.dl = 0x00はフロッピーに使用されます。そしてint86(0x13、 ®s, ®s) MS-DOS割り込みサービスINT13Hを呼び出します。
- ディスクの表面のセクターに直接情報を書き込むので、 _bios_disk のパラメーターは次のようになります。
Parameter |
What it means |
dinfo.drive = 0x00 |
It indicates the drive 0 that is floppy disk drive (a:) |
dinfo.head = head |
It points to head number 0 and 1 as floppy has two sides(two heads) |
dinfo.track = track |
It points to track 0 to 79 as there are 80 tracks on each side of floppy. |
dinfo.sector = sector |
It points to sector 1 to 18 as there are 18 sectors in each track. |
dinfo.sector = 1 |
Number of sectors to consider for write operation = 1 |
dinfo.buffer = dbuf |
Data buffer for the operation |
- _bios_disk(_DISK_WRITE, &dinfo)dinfoで指定されたフロッピーディスクの物理面のセクターにデータを書き込みます。
- 返されたステータスは結果に保存され、正常に動作するためのメッセージを表示したり、エラーが発生した場合に画面にエラーメッセージを表示したりするために使用されます。
メソッドの後の場合 – 2 新しいフロッピーが機能しない場合は、さらに方法を適用できます – 1 メソッド中に宛先ディスクとして使用した新しいフロッピー – 2.
これだけでなく、ヒット数と試行回数もディスクの破損によって異なる場合があります。しかし、満足のいく結果が得られなくても心配する必要はありません。
ファイルごとのリカバリを試すことも、次に学習する多くのヒントを試すこともできます。ここでは、データを回復するためのプログラミングで、ルートディレクトリからファイル情報を収集するというアイデアを実装します。
削除または失われたデータの論理的回復について考える:
この章でリカバリについて説明したこれまでのすべてのケースは、 DBRが破損しているとセクターのみが破損していると予想される場合にデータをリカバリすることでした。トラック0では、FAT1、FAT2、およびルートディレクトリが読み取り可能です。
ただし、問題の原因がFATの破損であるか、データがディスクから削除されている場合、または情報を読み取ってデータを直接回復したい場合ルートディレクトリから、ファイル名、開始クラスタ、ファイルのサイズなどの情報を読み取る必要があります、ルートディレクトリエントリからの属性など。
前の章でルートディレクトリについてすでに説明したように、ファイルまたはディレクトリごとに32バイトの情報があります。これらの32バイトは次のように分割されます。
Number of Bytes |
Information Description |
8 Bytes |
Filename |
3 Bytes |
Extension |
1 Byte |
Attribute |
10 Bytes |
Reserved |
2 Bytes |
Time, Created or Last Updated |
2 Bytes |
Date, Created or Last Updated |
2 Bytes |
Starting Cluster |
4 Bytes |
File Size |
ルートディレクトリからファイルの情報を読み取ってデータを復元し、ファイルを宛先パスに統合してファイルを復元します。次のプログラムは、データを回復するために次の手順を実行します。
- ルートディレクトリエントリを読み取り、ファイル/ディレクトリ名、ファイルの拡張子、ファイルの開始クラスタサイズ(バイト単位)などのすべての情報を画面に表示します。
- サブディレクトリのファイルとディレクトリの情報を読んで、必要に応じて表示します。
- 回復するファイル名を確認し、回復を続行します。
- 復元する指定ファイルのCHS(シリンダー、ヘッド、セクター)情報を計算します。
- ディスクのデータ領域からファイルのデータを統合し、復元されたファイルを指定されたパスの指定された宛先ファイル名に保存します。
このプログラムは、フロッピーのブート情報が読み取り可能かどうかを気にしません。したがって、破損したフロッピーディスクから削除されたデータも復元することができます。プログラムのコーディングを見てみましょう。
/* ルートディレクトリからファイル情報を読み取ることにより、フロッピーディスクからデータを回復するプログラム */
#include<stdio.h>
#include<bios.h>
#include<dos.h>
void main()
{
void Display_Information(unsigned int,unsigned int,
unsigned int);
unsigned int track=0,head=1,sector=2;
Display_Information(track,head,sector);
} /*End of main */
void Display_Information(unsigned int track,
unsigned int head,
unsigned int sector)
{
void recover(unsigned int *,unsigned int);
char buf[512]; // Buffer of 512 Bytes
char ch;
struct diskinfo_t finfo; //Structure, Used by _bios_disk
unsigned int result,i,j, count=0; /* Unsigned Integers
Defined */
unsigned int file_no; /* Unsigned Integer
for File Number */
struct
{
unsigned int name[8],ext[3]; /* File Name for DOS in 8.3
(Eight Dot Three) Format */
unsigned int attribute; // File/Directory Attribute
unsigned int start; // Starting Cluster of the File
long unsigned int size; // Size of the File in Bytes
}root[32]; /* 32 Bytes Information of
File/Directory in Root
Directory */
clrscr();
do
{
file_no=0;
finfo.drive = 0x00; /* drive number for A: */
finfo.head = head; /* disk head number */
finfo.track = track; /* track number */
finfo.sector= sector; /* sector number */
finfo.nsectors=1; /* sector count */
finfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &finfo); /* Read the
Sector */
if( (result & 0xff00) != 0) /* If Read Error, Display
Error Message and Exit*/
{
printf("Read error");
getch();
exit(0); // Go Back to DOS
}
/// 情報表示画面フォーマット \\\
clrscr();
gotoxy(9,1);
cprintf("DISPLAY CYLN: %u, HEAD: %u, SECTOR: %u",
track, head, sector);
gotoxy(9,2);
cprintf("FNO NAME EXT ATTRIBUTE START SIZE");
gotoxy(7,3);
cprintf("--------------------------------------------");
/* 一度に1つのセクター。すべてのファイル/ DIRエントリは32バイトかかります */
for(i=0;i<512;i+=32)
{
for(j=0;j<8;j++)
{
/// ファイル/ディレクトリ名を検索 \\\
root[file_no].name[j]=buf[j+i];
}
for(j=8;j<11;j++)
{
/// 拡張機能を探す \\\
root[file_no].ext[j-8]=buf[i+j];
}
j=11;
root[file_no].attribute=buf[i+j]; /// Attribute
/// クラスターの開始 \\\
root[file_no].start=(0xff & buf[27+i])*16*16 + (0xff & buf[26+i]);
/// サイズを計算する \\\
root[file_no].size =(long unsigned int)(0xff &
buf[31+i])*16*16*16*16*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[30+i])*16*16*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[29+i])*16*16;
root[file_no].size+=(long unsigned int)(0xff &
buf[28+i]);
if((root[file_no].start == 0) ||
(root[file_no].attribute == 15))
continue;
else
{
gotoxy(8,i/32+4);
cprintf("%2u",file_no); /* Display File
Number */
for(j=0;j<8;j++)
{
gotoxy(14+j,i/32+4);
cprintf("%c",root[file_no].name[j]); /* Display File
Name */
}
for(j=0;j<3;j++)
{
gotoxy(26+j,i/32+4);
cprintf("%c",root[file_no].ext[j]); /* Display
Extension */
}
gotoxy(30,i/32+4);
cprintf("%u",root[file_no].attribute); /* Display
Attribute */
if(root[file_no].attribute==16)
{
gotoxy(33,i/32+4);
cprintf("<DIR>"); /* Display if Directory Attribute */
}
else
{
gotoxy(33,i/32+4);
cprintf("<FILE>"); /* The Entry is of a file */
}
gotoxy(44,i/32+4);
cprintf("%-5u", root[file_no].start); /* Display
Starting Cluster */
gotoxy(58,i/32+4);
cprintf("%-10lu", root[file_no].size); /* size of the
File */
}
file_no++;
}
gotoxy(10,
cprintf("Press 'M' : To see list of more files &quo
gotoxy(10,
cprintf("Press 'R' :To recover a file from the above
list&quo
ch=getc
s(E5H)で始まるファイル名は、ファイルが削除されたため、ファイル名の最初の文字がsに置き換えられたことを示していることに注意してください(前の章のルートディレクトリの説明を参照してください)。.
そして、プログラムの出力は次のように表示されます。
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
--------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Press 'M' : To see list of more files
Press 'R' :To recover a file from the above list R
|
DISPLAY CYLN: 0, HEAD: 1, SECTOR: 2
FNO NAME EXT ATTRIBUTE START SIZE
----------------------------------------------------------------------------
0 WE 32 <FILE> 15 1800
1 s2_INFO C 32 <FILE> 5 4700
2 THELP CFG 32 <FILE> 2 22
3 THELP COM 32 <FILE> 3 11072
4 TIMEIT CPP 32 <FILE> 39 1186
5 TOUCH COM 32 <FILE> 42 5124
6 TRY1 CPP 32 <FILE> 53 1581
7 TURBOC CFG 32 <FILE> 57 30
8 AA CPP 32 <FILE> 58 260
9 ABC CPP 32 <FILE> 59 1036
10 ASSIGN1 CPP 32 <FILE> 62 4257
11 CH24_2 CPP 32 <FILE> 71 834
12 sBSDISK1 C 32 <FILE> 73 911
13 sH24_25 C 32 <FILE> 75 594
14 sBSDISK C 32 <FILE> 77 840
Enter FNO. of the file you want to recover 1
You want to recover _2_INFO .C
Cylinder = 1, Head = 0, Sector = 1 Integrating........
Enter Path and Filename to recover the file: c:\windows\desktop\H2_INFO.C
Recovery Done !!!
|
コーディングに関するコメント:
Display_Information の機能は、ルートディレクトリからファイルとディレクトリの情報を読み取ることです。構造体では、root [32]を持つすべてのファイルまたはディレクトリの32バイトの情報を読み取っています。
符号なし整数配列name [8]およびext [3]は、8.3(Eight Dot Three)形式のDOSのファイル名またはディレクトリ名です。同様に、1バイトは属性用で、2バイトはクラスターの開始用です。 long unsignedintサイズ。 4バイトのファイルのサイズを保存することです。
_bios_disk 関数は、構造体finfoで指定されたセクターを読み取り、操作のステータスが結果に保存されます。
_bios_disk関数によって読み取られた512バイトのすべての情報から、ルートディレクトリ領域が終了するまで、ディスクに保存されているファイルとディレクトリの情報を収集します。それらを画面に表示します。
整数file_noは、0から始まるリスト内のファイルまたはディレクトリの番号を格納します。通常、ルートディレクトリのサイズは14セクターであり、ルートディレクトリは通常Cylinder = 0、Head = 0、Sector = 2から始まります。 1.44MBおよび 3½ フロッピーディスク。
ユーザーがキャラクターを与える場合 ‘M’ or ‘m’ 入力として、ユーザーによる選択が次の場合、次のセクターの情報が表示されます ‘R’ or ‘r’ 回復関数が呼び出されます。関数のコーディング 回復する() 以下に与えられています:
/* 指定したファイルのリカバリを開始する機能 */
void recover(unsigned int *root,unsigned int len)
{
void clear_the_line(unsigned int r); /* Function to Clear a Row on the Screen */
/ * 指定されたファイルを統合する関数 */
void integrate(long unsigned int,unsigned int,
unsigned int,unsigned int);
unsigned int file_no,i;
char ch;
unsigned int *loc;
unsigned int cylinder,head,sector;
unsigned int start;
long unsigned int size;
clear_the_line(21); /* Clear The Row Number 21 */
clear_the_line(22); /* Clear The Row Number 22 */
clear_the_line(23); /* Clear The Row Number 23 */
clear_the_line(24); /* Clear The Row Number 24 */
gotoxy(10,21);
cprintf("Enter FNO. of the file you want to recover");
scanf("%u",&file_no); /* Get the File No. to be
Recovered */
loc=(root+(len*file_no/2));
/ * 復元するファイル名を確認します */
gotoxy(10,22);
cprintf("You want to recover");
for(i=0;i<8;i++)
{
gotoxy(30+i,22);
cprintf("%c",*(loc+i)); /* File name */
}
gotoxy(38,22);
cprintf(".");
for(i=0;i<3;i++)
{
gotoxy(39+i,22);
cprintf("%c",*(loc+8+i)); /* File Extension */
}
start=*(loc+12);
/// 申し訳ありませんが、ディレクトリを選択しました \\\
if(*(loc+11)==16)
{
gotoxy(5,23);
cprintf("Is A directory. Do you want to see the
contents of this directory Y/N");
ch=getch();
if(ch==27)
main();
if(ch=='y' || ch=='Y')
{
/ * 幾何学を計算する */
calculate(start,&cylinder,&head,§or);
/ * ディレクトリの内容を表示する */
Display_Information (cylinder,head,sector);
}
else
/* Ask for A file again and Continue Recovery */
recover(root,len);
}
else
{
size=*(loc+13);
/ * CHS情報を計算する */
calculate(start,&cylinder,&head,§or);
/ * ファイルを統合する */
integrate(size,cylinder,head,sector);
}
}
コーディングに関するコメント:
関数 recover()は、ユーザー入力を取得してリカバリを開始することです。ファイルを回復するためにユーザーが入力したファイル番号は、file_noに保存されます。
入力した番号がディレクトリエントリの場合は、Display_Information()にそのディレクトリの内容が表示されます。それ以外の場合は、ファイル名とファイル番号file_noの拡張子が画面に表示され、復元するファイルを確認します。
指定されたファイルを回復するために、関数 calculate()と integrate()が関数内で呼び出されます。関数calculate()のコーディングを以下に示します。
/ * 回復のためのCHSジオメトリを計算する関数 */
void calculate(unsigned int start,unsigned int *cylinder,
unsigned int *head,unsigned int *sector)
{
unsigned int temp;
*cylinder=0;
*head=1;
*sector=14;
if(start<5)
*sector=14+start;
else
{
temp= (start-4)/18;
if(temp>0)
{
if(temp%2==0)
*head=0;
else
*head=1;
*cylinder+=1+temp/2;
}
else
{
*head=0;
*cylinder=1;
}
*sector=(start-4)%18;
}
/// 回復するファイルのCHSを表示する \\\
gotoxy(10,23);
cprintf("Cylinder = %u, Head = %u, Sector = %u",
*cylinder,*head,*sector);
}
コーディングに関するコメント:
関数 calculate()は、復元するファイルのシリンダー、ヘッド、セクター情報を計算します。計算後、シリンダー、ヘッド、セクターの番号が画面に表示されます。
関数integrate()のコーディングを以下に示します。
/ * ファイルを統合し、回復したファイルを指定したパスとファイル名に保存します */
void integrate(long unsigned int size,
unsigned int cylinder,
unsigned int head,
unsigned int sector)
{
void clear_the_line(unsigned int);
/ * セクターのエラーを確認する関数 */
int verify_the_sector(unsigned int, unsigned int,
unsigned int);
int status;
char buf[512],*Filename_with_path;
struct diskinfo_t dinfo;
unsigned int result;
FILE *fp;
unsigned int left,i;
unsigned int sec;
/ * 復元されたファイルを保存するための宛先パスとファイル名を入力します */
gotoxy(2,24);
cprintf("Enter Path and Filename to recover the file: ");
fflush(stdin);
gets(Filename_with_path);
fp=fopen(Filename_with_path,"wb");
/ * エラーが発生した場合はエラーメッセージを表示し、入力パスとファイル名を再度取得します */
if(fp==NULL)
{
gotoxy(5,25);
cprintf("Error in opening the file");
getch();
clear_the_line(24);
gotoxy(0,25);
cprintf(" ");
integrate(size,cylinder,head,sector); /* Enter the
Destination Again */
}
/ * すべてが大丈夫なら、統合して書く */
gotoxy(50,23);
cprintf("Integrating........");
left= size%512;
sec = size/512;
sec++;
while(sec>0)
{
dinfo.drive = 0x00; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = cylinder; /* track number */
dinfo.sector= sector; /* sector number */
dinfo.nsectors=1; /* sector count */
dinfo.buffer = buf; /* data buffer */
result = _bios_disk(_DISK_READ, &dinfo);
/* If there is Error While Reading any Sector */
if( (result & 0xff00) != 0)
{
gotoxy(5,25);
cprintf("read error Cylinder %u, Head %u, Sector %u",
cylinder, head, sector);
}
else
{
if(sec==1)
{
for(i=0;i<left;i++)
fputc(buf[i],fp); /* Write The Integrated
Information to the File */
}
else
{
fwrite(buf,512,1,fp);
}
コーディングに関するコメント:
関数 integrate()は、このリカバリプログラムでユーザーが指定したファイルのリカバリを実行する実際のモジュールです。
復元されたファイルを保存する宛先パスを含むファイル名は、文字ポインター* Filename_with_pathに保存されます。宛先ファイルを開く際にエラーが発生した場合は、エラーメッセージが表示され、ユーザーは宛先の入力を再度求められます。
関数 _bios_disk(_DISK_READ, &dinfo);構造体dinfoで指定され、データ・バッファーbufに保管されている、セクターごとのディスク・セクターのデータ域からファイルのデータを読み取ります。この512バイトのデータは、宛先ファイルに書き込まれます。これは、完全なファイルが統合されるまで繰り返されます。
関数status = verify_the_sector(cylinder、head、sector);読み取るセクターを確認します。ステータス= 10の場合、不良(0xA)セクターを表します。関数のコーディングは以下のとおりです。
/// セクターを確認します。 (ここではデータは転送されません) \\\
int verify_the_sector(unsigned int c,unsigned int h,unsigned int s)
{
int status;
char *buf;
union REGS in, out;
struct SREGS sg;
in.h.ah = 0x04; /* Function Number */
in.h.al = 1; /* Number of Sectors to Verify*/
in.h.dl = 0x00; /* Drive Number for A: */
in.h.ch = c; /* Cylinder Number */
in.h.dh = h; /* Head Number */
in.h.cl = s; /* Sector Number */
in.x.bx = FP_OFF(buf);/* Offset */
sg.es = FP_SEG(buf); /* Segment */
int86x(0x13,&in,&out,&sg); /* Call the Function 4H
of INT 13H */
if(out.x.cflag)
{
status=out.h.ah;
}
return(status);
}
コーディングに関するコメント:
関数verify_the_sector()は、セクターが_bios_disk()関数によって読み取られることを確認し、操作のステータスを返します。この関数は、INT13Hと関数4Hを使用してセクターを検証します。
* bufはデータバッファ、0x04はin.h.ah = 0x04で指定された関数番号です。およびin.h.al = 1;一度に1つのセクターを検証するように指示します。 in.h.dl = 0x00;フロッピードライブAのドライブ番号に使用されます。、c、h、およびsはシリンダー、ヘッド、およびセクターの番号です。
関数 int86x()は、セグメントレジスタ値を使用してINT 13H(関数4H)を呼び出すために使用されます。操作のステータスは整数ステータスで返されます。
関数 clear_the_line()は、画面上の指定された行をクリアします。関数のコーディングは次のとおりです。
/ * 指定された行番号に対して、画面上の行をクリアする関数 */
void clear_the_line(unsigned int row)
{
unsigned int column;
/* There are 80 Columns in a Row (Line) */
for(column=1;column<=80;column++)
{
gotoxy(column,row);
cprintf(" "); /* Clear With " " */
}
}
コーディングに関するコメント:
この関数は、画面上の指定された行をクリアするために使用されます。関数は、画面からクリアされる行数で呼び出されます。