#include <stdio   .h>
#include <string  .h>
#include <stdlib  .h>
#include <dos     .h>

/*#include <isao    .h>*/

#include "def     .h"

struct {char			dflag;			/* ドライブのエラーフラグ */
		unsigned		all;			/* ドライブの総クラスタ数 */
		unsigned		free;			/* ドライブの総空きクラスタ数 */
		unsigned long	bytes;} 		/* 1クラスタのバイト数 */
								c[26];	/* A-Z計26ドライブ */

struct serr{unsigned deverror;			/* デバイスエラーコード */
			unsigned errcode;			/* エラーコード (下位バイトのみ) */
			unsigned far *pdevhdr;};	/* エラーを起こしたデバイス情報 */

unsigned char	i;					/* ドライブ番号用 汎用変数 */

void far int24h(struct serr); /* 致命的エラーハンドラの関数プロトタイプ宣言 */

main(int argc,char *argv[],char *envp[])
{
	unsigned char	drive=0;		/* 生きているドライブ数 */
	unsigned long	t_all=0l,		/* 全ドライブの総容量 (Bytes) */
					t_free=0l,		/* 全ドライブの空き容量 (Bytes) */
					all,			/* 各ドライブの総容量 (Bytes) */
					free;			/* 各ドライブの空き容量 (Bytes) */

	struct	diskfree_t	diskinfo;	/* <dos.h>定義のdiskfree_t構造体
										_dos_getdiskfree()で使用 */

	if (argc==1)					/* 引数なしなら オプション要求 */
	{
		printf("using : MCD [Drive[...]]\n");
		return;
	}

	_harderr(int24h);				/* int 24h ハンドラ設定 */

	printf("\nＭＣＤ Version %s   %s\n\n",VERSION,COPYRIGHT);	/* タイトル */

	ltou(argv[1]);					/* 宿題その１(^_^;) */

	if (argv[1][0]=='*')			/* 引数の一文字目が [*]の時の処理 */
		for (i=0;i<=25;i++)			/* 全ドライブに「調査フラグ」*/
			c[i].dflag=_DFLAG_CHK;
	else
	{
		for (i=0;i<=25;i++)			/* ひとまず全ドライブに「調査不要フラグ」*/
			c[i].dflag=_DFLAG_NCH;

		for (i=0;argv[1][i]!='\0';i++)	/* 引数を調べる */
			if(argv[1][i]>='A' && argv[1][i]<='Z') /* もしドライブ名(A-Z)なら*/
				c[argv[1][i]-'A'].dflag=_DFLAG_CHK;
										/* そのドライブに「調査フラグ」*/
	}

	for(i=0;i<=25;i++)				/* A:-Z:ドライブ */
	{
		if (c[i].dflag==_DFLAG_CHK)	/* 「調査フラグ」ありなら */
			if(_dos_getdiskfree(i+1,&diskinfo)==0)	/* ドライブが覗けたら */
			{
				c[i].all=diskinfo.total_clusters;
				c[i].free=diskinfo.avail_clusters;
				c[i].bytes= (unsigned long)diskinfo.sectors_per_cluster*
							(unsigned long)diskinfo.bytes_per_sector;
			}						/* 各情報を代入 */
			else					/* ドライブが覗けなかったら */
				if(c[i].dflag==_DFLAG_CHK) /* int24hでｴﾗｰ情報貰えなければ */
					c[i].dflag=_DFLAG_NCH;	/* このドライブはないンだろぉ */
	}

	printf("Drive  Total          Avail           Ratio\n");
/*			    A: 1234567 KBytes 1234567 KBytes  100.000%*/

	for(i=0;i<=25;i++)				/* A:-Z:ドライブ */
		switch(c[i].dflag)			/* 「調査フラグ」の中身によって… */
		{
			case _DFLAG_CHK:		/* 無事生きてるドライブ */
				all=(unsigned long)c[i].all*c[i].bytes/1024ul;
				free=(unsigned long)c[i].free*c[i].bytes/1024ul;
								/* ドライブの総容量・空き容量のBytes数代入 */

				printf("    %c: %7lu KBytes %7lu KBytes  %7.3f%%\n"
						,i+'A',all,free,100.0*free/all); /* 表示 */

				t_all+=all;			/* 全ドライブ総容量に加算 */
				t_free+=free;		/* 全ドライブ空き容量に加算 */
				drive++;			/* 生きているドライブ数に1加算名 */
				break;				/* switch文から脱出 */

			case _DFLAG_NR:			/* 準備出来ていないドライブ等 */
				printf("    %c: ------- KBytes ------- KBytes Not Ready\n"
						,i+'A');	/* エラー表示 */
				break;				/* switch文から脱出 (不要) */
		}

	if(drive>1)						/* 調査したドライブが 2つ以上なら */
		printf("\nTotal: %7lu KBytes %7lu KBytes  %7.3f%%\n"
				,t_all,t_free,100.0*t_free/t_all);	/* 合計の情報表示 */
}

void far int24h(struct serr systemerror)/* 致命的エラーハンドラ */
{
	unsigned err;						/* エラーコード代入用 */

	err=systemerror.errcode & 0x0f;		/* 不必要なデータをカットして代入 */

	switch (err)						/* エラーコードによって… */
	{
		case 0x02:						/* ドライブの準備ができていない */
		case 0x07:						/* 存在しないメディアタイプ */
			c[i].dflag=_DFLAG_NR;		/* 準備出来ていない等用フラグ代入 */
			break;						/* switch文から脱出 */

		case 0x01:						/* 存在しないユニット番号を指定 */
			c[i].dflag=_DFLAG_NCH;		/* このドライブはないンだろぉ */
			break;						/* switch文から脱出 (不要) */
	}

	_hardresume(_HARDERR_IGNORE);		/* エラーを無視して続けろ指令(^_^;) */
}


/************************************************
*												*
*	Moonlight's ChkDsk ＭＣＤ					*
*				Programmed by Moonlight			*
*												*
*					Version 0.00	1994. 2. 8	*
*					Version 0.01	1994. 2.11	*
*					Version 0.02	1994. 2.15	*
*												*
************************************************/
