⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fscan.c

📁 嵌入式系统中文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************
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 + -