#include <error.h>
#include "defines.h"
#include "ascsi.h"
#include "acmp.h"
#include "acdata.h"
#include "FAT32.h"

//#define	DEBUG	1

#if DEBUG >=1
#define	Fat2Sec0(fp,fat)	(fp->secdata+((fat-fp->fatroot)*fp->clu1sec))
#endif

static int FatWrite(FILE32 *fp,unlong sec)
// FAT領域データ書きだし
// 複数FAT対応
// 複数FATの時は、それぞれの内容が一致していることを前提としている。
// （同じ内容を全fatに書き出すだけだから、元々の内容が一致しているかどうかは比較していない）
{
int ret=0;
short fats;
	#if DEBUG
	printf("FatWrite\n");
	#endif
	fats=fp->fats;
	do {
		ret=S_SecWrite(sec,1,fp->scsiid,fp->blksz,(unchar *)fp->fbuff);
		if (ret) {
			fp->error=ENODEV; // 読めない
			break;
		}
		sec+=fp->fatsecs; // 次のFAT領域へ
	} while (--fats>0);
	return(ret);
}

int _DelFatLink32(FILE32 *fp)
// ＦＡＴリンクを削除する
// ディレクトリエントリは削除しないので注意
// ＦＡＴが複数存在する時にはその全てで削除する
// 常にvfat対応である
// fp : 削除するファイル／ディレクトリを示すFILE32構造体
// return : =0:ok , !=0:error
{
int ret=0;
unlong sec,fat,count=0L,ofst;
unlong fatlast=0L; // ループチェック
	#if DEBUG
	printf("DelFatLink\n");
	#endif
	// 原型はNextFat()である
	fat=fp->topfat; // このファイルの先頭fat番号
	sec=fp->secfat1+fat/FATS1SEC; // この番号のFATが含まれるセクター
	#if DEBUG
	printf("fat=$%x(sec=$%x)/fbufffat=$%x\n",fat,sec,fp->fbufffat);
	#endif
	do {
	    if (fat>=fp->allsec/fp->clu1sec) { // 有効セクターより大きい
	    	// 現在までのところを確定して、後は打ち切る
		ret=FatWrite(fp,sec);
		if (ret) return(ret); // 読めない
		fp->error=E2BIG; // 適当
		return(fp->error); // 適当
	    }
	    if (fat<fp->fbufffat || fat>=fp->fbufffat+FATS1SEC) {
		if (count>=1L) { // fbuff[]を切り替える時は、その前にfbuff[]を書き出す
			ret=FatWrite(fp,sec);
			if (ret) return(ret); // 読めない
		}
		// 現在のfbuffの中にfat辺りのデータがない→読み込む
		sec=fp->secfat1+fat/FATS1SEC; // この番号のFATが含まれるセクター
		#if DEBUG
		printf("SecRead:sector=$%x,id=%d,blksz=%d\n",sec,fp->scsiid,fp->blksz);
		#endif
		ret=S_SecRead(sec,1,fp->scsiid,fp->blksz,(unchar *)fp->fbuff);
		if (ret) {
			fp->error=ENODEV;
			return(ret); // 読めない
		}
		// 読み込んだ領域の先頭FAT番号
		fp->fbufffat=(fat/FATS1SEC)*FATS1SEC;
	    } // fbuff[]内にFAT[fp->fat]のデータがある
	    if (fatlast<fat) fatlast=fat; // 最大FATの検知
	    else if (fat==fatlast) { // ループしている
	    	// 現在までのところを確定して、後は打ち切る
		ret=FatWrite(fp,sec);
		if (ret) return(ret); // 読めない
		fp->error=EAGAIN; // 適当
		return(fp->error); // 適当
	    }
	    ofst=fat-fp->fbufffat;
	    fat=ctol80((unchar *)&fp->fbuff[ofst]); // 記録されているのは次のFAT番号
		#if DEBUG
		printf("fat=$%x(ofst=$%x)\n",fat,ofst);
		#endif
	    fp->fbuff[ofst]=0x00000000L;
	    count++; // 消去した数
	} while (fat!=ENDofFATs);
	// 現在のfbuff[]を書き出し
	return(FatWrite(fp,sec));
}

// サイズチェックも入れたいが、入れても無駄なので止め。
// （ループは暴走につながるので切るが、サイズ異常は消してしまう以上どうしようもない。）
