📄 fscan.c
字号:
/*************************************************************
File Name: SCAN.C *
**************************************************************
Programmer: MSC
Last Modified Date: 1999/07/08
Compiler : Gnu Cross-compiler
Platform : X86 protection mode
Usage :
scanDisk functions for FAT1X_Disk
See scan.h for usage.
*************************************************************/
#include <pr2k.h>
#include <kernel/linklist.h>
#include <sys/syscall.h>
#include <kernel/malloc.h>
#include <stdio.h>
#include "../../FileSys/include/FileSys.h"
#include "../include/fat1x.h"
#include "../include/init.h"
#include "../include/cluster.h"
#include "../include/unicode.h"
#include "../include/fscan.h"
#ifdef FAT_USE_PCMCIA
//#include "../pcm/cf_typedef.h"
//#include "pcmcia/include/pcmcia.h"
#ifdef __WIN32__
#include"../include/ata_emu.h"
#else
#include "pcmcia/include/pcmcia.h"
#endif
#include "../include/ata_pcc.h"
#else
#include "../include/ata_pcc.h"
#endif
//#include "myansi.h"
#ifdef FAT_ID
/* the list of sub-dirs to be processed */
struct dLinkList dirList;
/* buffers for FAT1 and FAT2 */
unsigned short *FATBuf;
int fileErrCount;
char echo;
char autoFix;
/* fat1x.c */
//extern int hdDriver;
/* init.c */
extern unsigned long FAT1Begin[DRIVE_NUM];
extern unsigned long FAT2Begin[DRIVE_NUM];
extern unsigned long FATRootBegin[DRIVE_NUM];
extern unsigned short FATSecPerFAT[DRIVE_NUM];
extern unsigned short FATSecPerROOT[DRIVE_NUM];
extern unsigned short FATTotalCluster[DRIVE_NUM];
extern unsigned long FATBytesPerCluster[DRIVE_NUM];
extern unsigned char FATType[DRIVE_NUM];
extern int FATErrno;
extern int InitFAT;
extern int FATDirSemaphoreID;
// cluster.c
extern unsigned short FATEndOfChain[];
/*************************************************************
Fuction : scanDisk
Scan the FAT1x Disk for errors
Input:
interactive - ECHO_ON: show progress during scanning
ECHO_OFF: show nothing during scanning
fix - 1: automatically fix error
0: report only, don't fix
Output:
0: no error is found
-1: system error (check FATErrno)
Otherwise:
bit 0: FAT tables unmatch
bit 1: File/Dir error
bit 2: Unchained clusters
**************************************************************/
char FAT_scanDisk(char interactive, char fix)
{
int status;
int returnValue = 0;
unsigned short *rootSecBuf;
unsigned char *p;
char noMore = 0; // no more entry in this directory
char changed = 0; // this root sector has been changed
int unchained = 0; // number of unchained clusters
unsigned long i, j;
struct scan_dir *currentDir;
unsigned char rootDir[10];
int k;
#ifdef FAT_LFN
struct FAT_LFNinfo longInfo;
#endif
/**** added by chilong 05/02/2002 temporarily ****/
return (char) 1;
/**** added by chilong 05/02/2002 temporarily ****/
if (InitFAT == FALSE)
{
FATErrno = ERROR_FILE_SYSTEM_NOT_INIT;
return (char)-1;
}
strcpy((char *)rootDir, "\\");
echo = interactive;
autoFix = fix;
sc_waitSemaphore(FATDirSemaphoreID);
for(k = 0; k < DRIVE_NUM; k++)
{
// Step 1: compare the FAT tables
if (echo == ECHO_ON)
printString("Comparing the two FAT tables...");
status = FAT_fat_compare(k);
if (echo == ECHO_ON)
printStringLn("done.");
switch (status)
{
case 0: // FATs match
if (echo == ECHO_ON)
{
printStringLn("The two FAT tables match!");
}
break;
case 1: // FATs unmatch and FAT1 is guessed correct
if (echo == ECHO_ON)
{
printStringLn("The two FAT tables unmatch and FAT1 is considered to be the correct one!");
}
returnValue |= ERR_FAT;
if (autoFix == 1)
{
if (echo == ECHO_ON)
printStringLn("Copying FAT1 to FAT2...");
if (FAT_fat_copy(k, FAT1Begin[k], FAT2Begin[k]) == 1)
{
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
}
break;
case 2: // FATs unmatch and FAT2 is guessed correct
if (echo == ECHO_ON)
{
printStringLn("The two FAT tables unmatch and FAT2 is considered to be the correct one.");
}
returnValue |= ERR_FAT;
if (autoFix == 1)
{
if (echo == ECHO_ON)
printStringLn("Copying FAT2 to FAT1...");
if (FAT_fat_copy(k, FAT2Begin[k], FAT1Begin[k]) == -1)
{
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
}
break;
case -1: // system error during comparison, check FATErrno
if (echo == ECHO_ON)
{
printStringLn("System error during comparison!");
printString("Error number is ");
printInt(FATErrno, DEC);
}
returnValue |= ERR_FAT;
break;
}
if (echo == ECHO_ON)
printStringLn("Checking files and directories...");
if ((FATBuf = (unsigned short *)ap_malloc(SECTOR_SIZE * FATSecPerFAT[k])) == NULL)
{
FATErrno = ERROR_ALLOC_MEM;
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
// read FAT1
if (ATA_READ(k, FATSecPerFAT[k], FAT1Begin[k], FATBuf) == ATA_FAILURE)
{
ap_free(FATBuf);
FATErrno = ERROR_ATA_READ;
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
if ((rootSecBuf = (unsigned short *)ap_malloc(SECTOR_SIZE)) == NULL)
{
ap_free(FATBuf);
FATErrno = ERROR_ALLOC_MEM;
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
// initialize the double linked list of sub-directories
initDLinkList(&dirList);
// initialize the error counts of FATs
fileErrCount = 0;
// currrent path is ROOT dir
// check root directory sector by sector
for (i = FATRootBegin[k]; i < FATRootBegin[k] + FATSecPerROOT[k]; i++)
{
// if (ATA_READ(k, 1, i, rootSecBuf) == ATA_FAILURE)
if (FAT_read_root_sector(k, i, rootSecBuf) == ATA_FAILURE)
{
ap_free(rootSecBuf);
ap_free(FATBuf);
sc_signalSemaphore(FATDirSemaphoreID);
FATErrno = ERROR_ATA_READ;
return (char)-1;
}
changed = 0; // this sector has been changed
p = (unsigned char *)rootSecBuf;
// check root sector entry by entry
for (j = 0; j < SECTOR_SIZE; j += FAT_DIR_ENTRY_SIZE)
{
if (*(p + j) == '\0')
{
noMore = 1; // no more entry after empty one
break;
}
else
{
#ifdef FAT_LFN
longInfo.startBlock = i;
longInfo.startEntry = j;
if (i == FATRootBegin[k])
longInfo.endBlock = 0;
else
longInfo.endBlock = i - 1;
longInfo.endEntry = 0;
status = FAT_checkEntry(k, rootDir, (struct FAT_directory *)(p + j), &longInfo, rootSecBuf);
#else
status = FAT_checkEntry(k, rootDir, (struct FAT_directory *)(p + j));
#endif
if (status == -1)
{
// system error checking file
ap_free(rootSecBuf);
ap_free(FATBuf);
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
else if (status == 1)
{
// The file has unrecoverable error, delete it.
// Note that the cluster chain has not been cleared and
// becomes unchained, will be handled in next phase
changed = 1; // this sector has been changed
returnValue |= ERR_FILEDIR; // there is file error
}
}
}
#ifdef FAT_LFN
#else
if (changed == 1 && autoFix == 1)
{
if (FAT_update_root_sector(k, i, rootSecBuf) == ATA_FAILURE)
{
ap_free(rootSecBuf);
ap_free(FATBuf);
sc_signalSemaphore(FATDirSemaphoreID);
FATErrno = ERROR_ATA_WRITE;
return (char)-1;
}
}
#endif
if (noMore == 1)
break;
}
// this buffer is no longer required
ap_free(rootSecBuf);
// proceed with the DIRs in the list of directories to be scaned
while (dirList.back != NULL)
{
currentDir = (struct scan_dir *)dirList.back->elementPointer;
removeFrom(dirList.back);
status = FAT_checkDir(k, currentDir->pathName, currentDir->startCluster);
if (status == -1)
{
// system error
ap_free(rootSecBuf);
ap_free(FATBuf);
sc_signalSemaphore(FATDirSemaphoreID);
return (char)-1;
}
else if (status == 1)
returnValue |= ERR_FILEDIR;
ap_free(currentDir);
}
if (fileErrCount != 0)
{
if (echo == ECHO_ON)
{
printString("Number of file/dir errors = ");
printInt(fileErrCount, DEC);
}
returnValue |= ERR_FILEDIR;
}
else
{
if (echo == ECHO_ON)
{
printStringLn("There is no file/dir error.");
}
}
// check if there are unchained clusters in FATs
if (echo == ECHO_ON)
printStringLn("Clearing unlinked clusters in FAT...");
// checkEntry() clears the cluster chains of the existing files inside the buffers
// the clusters left after all file are checked must be unchained clusters
// if there are more file errors in FAT2, FAT2 is discarded and not checked here
for (i = 2; i < SECTOR_SIZE * FATSecPerFAT[k] / 2; i++)
{
if (FATBuf[i] != 0)
{
unchained++;
FAT_write_fat_cluster(k, i, 0x0);
returnValue |= ERR_ORPHAN;
}
}
// this buffer is no longer required
ap_free(FATBuf);
// both error counts are 0 only if there is no file error and no unchained cluster
if (echo == ECHO_ON)
{
if (unchained == 0)
printStringLn("No unchained cluster found.");
else
{
printString("Number of unchained cluster = ");
printInt(unchained, DEC);
}
}
if (echo == ECHO_ON)
printStringLn("File system integrity checking done.");
}
sc_signalSemaphore(FATDirSemaphoreID);
return returnValue;
}
/*************************************************************
Fuction : FAT_fat_compare
Compare the two FATs
Output:
0: match
1: unmatch and FAT1 is considered correct
2: unmatch and FAT2 is considered correct
-1: error, check FATErrno
Note:
A FAT table is considered correct when it has a higher
non-zero count than the other table.
**************************************************************/
int FAT_fat_compare(int drive)
{
unsigned long i;
int j, status;
char match = 1;
char returnValue = 0;
unsigned short *FAT1SecBuf;
unsigned short *FAT2SecBuf;
unsigned short FAT1Count = 0; // the number of non-zero entries in FAT1
unsigned short FAT2Count = 0; // the number of non-zero entries in FAT2
// we don't need to compare the partition with only one fat table
if (FAT1Begin[drive] == FAT2Begin[drive])
return 0;
if ((FAT1SecBuf = (unsigned short *)ap_malloc(SECTOR_SIZE)) == NULL)
{
FATErrno = ERROR_ALLOC_MEM;
return -1;
}
if ((FAT2SecBuf = (unsigned short *)ap_malloc(SECTOR_SIZE)) == NULL)
{
ap_free(FAT1SecBuf);
FATErrno = ERROR_ALLOC_MEM;
return (char)-1;
}
for (i = FAT1Begin[drive]; i < FAT2Begin[drive]; i++)
{
/* read the current sector from FAT1 */
status = ATA_READ(drive, 1, i, FAT1SecBuf);
if (status == ATA_FAILURE)
{
FATErrno = ERROR_ATA_READ;
returnValue = (char)-1;
break;
}
/* read the current sector from FAT2 */
status = ATA_READ(drive, 1, i + FATSecPerFAT[drive], FAT2SecBuf);
if (status == ATA_FAILURE)
{
FATErrno = ERROR_ATA_READ;
returnValue = (char)-1;
break;
}
/* compare the current sectors */
for (j = 0; j < SECTOR_SIZE / 2; j++)
{
if (FAT1SecBuf[j] != 0)
FAT1Count++;
if (FAT2SecBuf[j] != 0)
FAT2Count++;
if (FAT1SecBuf[j] != FAT2SecBuf[j])
match = 0; /* unmatch */
}
}
ap_free(FAT2SecBuf);
ap_free(FAT1SecBuf);
if (returnValue == -1)
return (char)-1;
if (match == 1)
return (char)0; /* match */
else
{
if (FAT1Count >= FAT2Count)
return (char)1;
else
return (char)2;
}
}
/*************************************************************
Fuction : FAT_fat_copy
Copy a FAT table to another
Input:
drive - the target drive
source - the starting sector number of the source FAT table
target - the starting sector number of the target FAT table
Output:
0: SUCCESS
-1: FAILURE
**************************************************************/
//int FATCopy(unsigned long source, unsigned long target)
int FAT_fat_copy(int drive, unsigned long source, unsigned long target)
{
int i;
int returnValue = 0;
unsigned short *secBuf;
if ((secBuf = (unsigned short *)ap_malloc(SECTOR_SIZE)) == NULL)
{
FATErrno = ERROR_ALLOC_MEM;
return -1;
}
for (i = 0; i < FATSecPerFAT[drive]; i++)
{
// read a source FAT sector
if (ATA_READ(drive, 1, source + i, secBuf) == ATA_FAILURE)
{
FATErrno = ERROR_ATA_READ;
returnValue = -1;
break;
}
// write the sector to target
if (ATA_WRITE(drive, 1, target + i, secBuf) == ATA_FAILURE)
{
FATErrno = ERROR_ATA_WRITE;
returnValue = -1;
break;
}
}
ap_free(secBuf);
return returnValue;
}
/*************************************************************
Fuction : FAT_checkEntry
Check the integrity of a dir entry
Input:
upperDir - the directory in which this file is stored
entry - the directory structure of the target file
Output:
0: SUCCESS
1: file has error
-1: FAILURE (check FATErrno)
**************************************************************/
/*
#ifdef LFN
int checkEntry(unsigned char *upperDir, struct directory *entry, struct LFNinfo *longInfo, unsigned short *blockBuffer)
#else
int checkEntry(unsigned char *upperDir, struct directory *entry)
#endif
*/
#ifdef FAT_LFN
int FAT_checkEntry(int drive, unsigned char *upperDir, struct FAT_directory *entry, struct FAT_LFNinfo *longInfo, unsigned short *blockBuffer)
#else
int FAT_checkEntry(int drive, unsigned char *upperDir, struct FAT_directory *entry)
#endif
{
int pIndex;
int i;
unsigned short tempCluster, traceCluster;
unsigned short clusterNO;
unsigned short remains;
struct scan_dir *mydir;
unsigned char *fileName;
unsigned short *dirBuf;
unsigned char *pBuf;
#ifdef FAT_LFN
char status;
#endif
if ((entry->attribute & DA_VFAT) == DA_VFAT)
{
// skip long entry
return 0;
}
else if ((entry->attribute & DA_VOLUME) == DA_VOLUME)
{
// skip volume label
return 0;
}
else if ((unsigned char)(entry->name[0]) == FAT_DELETED_ENTRY)
{
// skip deleted entry
return 0;
}
else if ((unsigned char)(entry->name[0]) == '.')
{
// skip "." and ".."
return 0;
}
#ifdef FAT_LFN
if ((fileName = (unsigned char *)ap_malloc(FAT_MAX_LFN_LENGTH * 2)) == NULL)
{
FATErrno = ERROR_ALLOC_MEM;
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -