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

📄 fscan.c

📁 嵌入式系统中文件系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  }
  myMemSet(fileName, 0, FAT_MAX_LFN_LENGTH * 2);
#else
  if ((fileName = (unsigned char *)ap_malloc(13)) == NULL)
  {
	FATErrno = ERROR_ALLOC_MEM;
	return -1;
  }
  myMemSet(fileName, 0, 13);
#endif

#ifdef FAT_LFN

  if (strlen((const char *)upperDir) == 1)
	status = FAT_getLongName(drive, 1, longInfo, (unsigned char *)entry, fileName);
  else
	status = FAT_getLongName(drive, 0, longInfo, (unsigned char *)entry, fileName);

  if (status != 1)
  {
	// not a long filename
	// copy the file name from dir entry to buffer
	pIndex = 0;
	for (i = 0; i < FAT_FILE_NAME_LENGTH; i++)
	{
		if (entry->name[i] == ' ')
			break;
		fileName[pIndex++] = entry->name[i];
	}
	fileName[pIndex++] = '.';
	for (i = 0; i < FAT_EXT_NAME_LENGTH; i++)
	{
		if (entry->ext[i] == ' ')
			break;
		fileName[pIndex++] = entry->ext[i];
	}
	if (fileName[pIndex - 1] == '.')
		fileName[pIndex - 1] = '\0';
	else
		fileName[pIndex] = '\0';
  }
  else if (status == -1)
  {
  	ap_free(fileName);
  	return -1;
  }
//  else
  //	unicodeToASCII(fileName);

#else

  // copy the file name from dir entry to buffer
  pIndex = 0;
  for (i = 0; i < FAT_FILE_NAME_LENGTH; i++)
  {
	if (entry->name[i] == ' ')
		break;
	fileName[pIndex++] = entry->name[i];
  }
  fileName[pIndex++] = '.';
  for (i = 0; i < FAT_EXT_NAME_LENGTH; i++)
  {
	if (entry->ext[i] == ' ')
		break;
	fileName[pIndex++] = entry->ext[i];
  }
  if (fileName[pIndex - 1] == '.')
	fileName[pIndex - 1] = '\0';
  else
	fileName[pIndex] = '\0';

#endif

  // if this entry is a sub-dir, information is inserted to the dirList and is
  //   proceeded after all files in the same dir level are done checking
  if ((entry->attribute & DA_DIR) == DA_DIR)
  {
	if (echo == ECHO_ON)
	{
		printString("[DIR] ");
		printString((char *)upperDir);
		printString((char *)fileName);
	}
	// this is a sub-directory, check if it is valid

	// (1) check the starting cluster of the sub-directory
	if ((entry->startCluster >= FATTotalCluster[drive] + 2) ||
	    (entry->startCluster < 2))
	{
  		// cluster number out of bound => unrecoverable error
		if (echo == ECHO_ON)
			printStringLn(" [INVALID STARTING CLUSTER]");
#ifdef FAT_LFN
		if (autoFix == 1)
		{
			if (strlen((const char *)upperDir) == 1)
			{
				if (FAT_deleteLongName(drive, 1, longInfo, blockBuffer) != 1)
				{
					printStringLn("Delete long filename error!");
					ap_free(fileName);
					return -1;
				}
			}
			else
			{
				if (FAT_deleteLongName(drive, 0, longInfo, blockBuffer) != 1)
				{
					printStringLn("Delete long filename error!");
					ap_free(fileName);
					return -1;
				}
			}
		}
#else
		entry->name[0] = FAT_DELETED_ENTRY;
#endif
		ap_free(fileName);
  		fileErrCount++;
		return 1;
	}

	// (2) check if the 1st and 2nd entries in the sub-directory
	if ((dirBuf = (unsigned short *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
	{
		FATErrno = ERROR_ALLOC_MEM;
		ap_free(fileName);
		return -1;
	}
	pBuf = (unsigned char *)dirBuf;

	if (FAT_read_cluster(drive, entry->startCluster, dirBuf) == -1)
	{
		FATErrno = ERROR_ATA_READ;
		ap_free(fileName);
		ap_free(dirBuf);
		return -1;
	}

	if (pBuf[0] != '.' || pBuf[1] != ' ' ||
	    pBuf[0 + FAT_DIR_ENTRY_SIZE] != '.' || pBuf[1 + FAT_DIR_ENTRY_SIZE] != '.')
	{
		// the 1st and 2nd entries of the directory is not "." and ".."
		if (echo == ECHO_ON)
			printStringLn(" [INVALID DIRECTORY (. AND ..)]");
#ifdef FAT_LFN
		if (autoFix == 1)
		{
			if (strlen((const char *)upperDir) == 1)
			{
				if (FAT_deleteLongName(drive, 1, longInfo, blockBuffer) != 1)
				{
					printStringLn("Delete long filename error!");
					ap_free(fileName);
					ap_free(dirBuf);
					return -1;
				}
			}
			else
			{
				if (FAT_deleteLongName(drive, 0, longInfo, blockBuffer) != 1)
				{
					printStringLn("Delete long filename error!");
					ap_free(fileName);
					ap_free(dirBuf);
					return -1;
				}
			}
		}
#else
		entry->name[0] = FAT_DELETED_ENTRY;
#endif
  		fileErrCount++;
		ap_free(fileName);
		ap_free(dirBuf);
		return 1;
	}

	if (echo == ECHO_ON)
		printStringLn(" [OK]");

	ap_free(dirBuf);

	// this dir entry is ok, insert it to the dir list
	if ((mydir = (struct scan_dir *)ap_malloc(sizeof(struct scan_dir))) == NULL)
	{
		FATErrno = ERROR_ALLOC_MEM;
		ap_free(fileName);
		return -1;
	}
	// this buffer is free after it has been removed from the dir list

	// copy the name of the upper directory
	pIndex = 0;
	while (upperDir[pIndex] != 0)
	{
		mydir->pathName[pIndex] = upperDir[pIndex];
		pIndex++;
	}

	// copy the 8.3 name of the dir
	i = 0;
	while (fileName[i] != 0)
		mydir->pathName[pIndex++] = fileName[i++];
	mydir->pathName[pIndex++] = '\\';
	mydir->pathName[pIndex] = '\0';
		
	mydir->startCluster = entry->startCluster;

	if (insertTo(&dirList, (void *)mydir) == FAIL)
	{
		FATErrno = ERROR_OPERATING_SYSTEM_ERROR;
	  	ap_free(mydir);
		ap_free(fileName);
		return -1;
	}

	ap_free(fileName);
	return 0;
  }

  // this is a file, starting checking

  // print filename
  if (echo == ECHO_ON)
  {
  	printString("[FILE] ");
	printString((char *)upperDir);
	printString((char *)fileName);
  }

  if ((entry->startCluster >= FATTotalCluster[drive] + 2) || (entry->startCluster < 2))
  {
  	// cluster number out of bound => unrecoverable error
  	if (echo == ECHO_ON)
  		printStringLn(" [INVALID STARTING CLUSTER]");
#ifdef FAT_LFN
	if (autoFix == 1)
	{
		if (strlen((const char *)upperDir) == 1)
		{
			if (FAT_deleteLongName(drive, 1, longInfo, blockBuffer) != 1)
			{
				printStringLn("Delete long filename error!");
				ap_free(fileName);
				return -1;
			}
		}
		else
		{
			if (FAT_deleteLongName(drive, 0, longInfo, blockBuffer) != 1)
			{
				printStringLn("Delete long filename error!");
				ap_free(fileName);
				return -1;
			}
		}
	}
#else
	entry->name[0] = FAT_DELETED_ENTRY;
#endif
  	fileErrCount++;
	ap_free(fileName);
	return 1;
  }

  clusterNO = (unsigned short)(entry->fsize / FATBytesPerCluster[drive]);
  remains = (unsigned short)(entry->fsize % FATBytesPerCluster[drive]);
  if (remains != 0)
  	clusterNO++;

  // check FAT1 (FATBuf)
  traceCluster = entry->startCluster;
  
  pBuf = (unsigned char *) FATBuf;
  
  for (i = 1; i < clusterNO; i++)
  {
	// get next cluster in the chain
	
	// fat12
	if (FATType[drive] == PART_DOS2_FAT)
	{
		
		if ((traceCluster & 0x0001) == 0x0001)
		{
							// part1				// part2
			tempCluster = ((unsigned short)pBuf[(traceCluster * 3 / 2) + 1] << 4) + ((pBuf[traceCluster * 3 / 2] & 0xF0) >> 4);
			
			// clear this FAT entry since it has already been handled
			// part1
			pBuf[traceCluster * 3 / 2] &= 0x0F;
			// part2
			pBuf[(traceCluster * 3 / 2) + 1] = 0x0;
		}
		else
		{
							// part2				// part1
			tempCluster = (((unsigned short)pBuf[(traceCluster * 3 / 2) + 1] & 0x0F) << 8) + pBuf[traceCluster * 3 / 2];
			// clear this FAT entry since it has already been handled
			// part1
			pBuf[traceCluster * 3 / 2] &= 0x0;
			// part2
			pBuf[(traceCluster * 3 / 2) + 1] &= 0xF0;
		}
		
	}
	// fat16
	else
	{
		tempCluster = FATBuf[traceCluster];
		// clear this FAT entry since it has already been handled
		FATBuf[traceCluster] = 0x0;
	}
	// check if the cluster is valid
	if (tempCluster >= FATTotalCluster[drive] + 2 || tempCluster < 2)
	{
		if (autoFix == 1)
			FAT_write_fat_cluster(drive, traceCluster, FATEndOfChain[FATType[drive]]);
		entry->fsize = i * FATBytesPerCluster[drive];

		if (echo == ECHO_ON)
		{
			printStringLn(" [FILE SIZE AND CLUSTER CHAIN UNMATCH]");
		}
		fileErrCount++;
		ap_free(fileName);
		return 1;
	}
	traceCluster = tempCluster;
  }
  
  // fat12
  if (FATType[drive] == PART_DOS2_FAT)
  {
  	if ((traceCluster & 0x0001) == 0x0001)
	{
						// part1				// part2
		tempCluster = ((unsigned short)pBuf[(traceCluster * 3 / 2) + 1] << 4) + ((pBuf[traceCluster * 3 / 2] & 0xF0) >> 4);
			
		// clear this FAT entry since it has already been handled
		// part1
		pBuf[traceCluster * 3 / 2] &= 0x0F;
		// part2
		pBuf[(traceCluster * 3 / 2) + 1] = 0x0;
	}
	else
	{
						// part2				// part1
		tempCluster = (((unsigned short)pBuf[(traceCluster * 3 / 2) + 1] & 0x0F) << 8) + pBuf[traceCluster * 3 / 2];
		// clear this FAT entry since it has already been handled
		// part1
		pBuf[traceCluster * 3 / 2] &= 0x0;
		// part2
		pBuf[(traceCluster * 3 / 2) + 1] &= 0xF0;
	}
  }
  // fat16
  else
  {
  	tempCluster = FATBuf[traceCluster];
	// clear this FAT entry since it has already been handled
	FATBuf[traceCluster] = 0x0;
  }
  
  if (tempCluster < FATEndOfChain[FATType[drive]])
  {
	if (autoFix == 1)
		FAT_write_fat_cluster(drive, traceCluster, FATEndOfChain[FATType[drive]]);
	if (echo == ECHO_ON)
		printStringLn(" [FILE SIZE AND CLUSTER CHAIN UNMATCH]");
	fileErrCount++;
	ap_free(fileName);
	return 1;
  }

  if (echo == ECHO_ON)
	printStringLn(" [OK]");

  ap_free(fileName);
  return 0;
}


/*************************************************************
Fuction : checkDir
	Check the integrity of a sub-directory
Input:
	drive - the target drive
	name - the complete pathname of the target sub-directory
	head - the head cluster in the cluster chain of the target sub-directory
Output:
	 0: SUCCESS
	 1: directory has error
	-1: FAILURE (check FATErrno)
**************************************************************/
//int checkDir(unsigned char *name, unsigned short head)
int FAT_checkDir(int drive, unsigned char *name, unsigned short head)
{
  int i;
  int status;
  unsigned short *dirBuf;
  unsigned char *pBuf;
  unsigned short traceCluster, tempCluster;
  char changed = 0;
  char noMore = 0;
  
  unsigned char *pFatBuf;
  
#ifdef FAT_LFN
  struct FAT_LFNinfo longInfo;
  unsigned short prevCluster = 0;
#endif

  if ((dirBuf = (unsigned short *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
	FATErrno = ERROR_ALLOC_MEM;
	return -1;
  }
  pBuf = (unsigned char *)dirBuf;

  traceCluster = head;

  pFatBuf = (unsigned char*)FATBuf;
  
  while (traceCluster < FATEndOfChain[FATType[drive]])
  {
	changed = 0;
	// get the cluster of the sub-directory
	if (FAT_read_cluster(drive, traceCluster, dirBuf) == -1)
	{
		FATErrno = ERROR_ATA_READ;
		ap_free(dirBuf);
		return -1;
	}

	for (i = 0; i < FATBytesPerCluster[drive]; i += FAT_DIR_ENTRY_SIZE)
	{
		if (*(pBuf + i) == '\0')
		{
			noMore = 1;	// no more entry after empty one
			break;
		}
		else
		{
#ifdef FAT_LFN
			longInfo.startBlock = traceCluster;
			longInfo.startEntry = i;
			longInfo.endBlock = prevCluster;
			longInfo.endEntry = 0;
			status = FAT_checkEntry(drive, name, (struct FAT_directory *)(pBuf + i), &longInfo, dirBuf);
#else
			status = FAT_checkEntry(drive, name, (struct FAT_directory *)(pBuf + i));
#endif
			if (status == -1)
			{
				ap_free(dirBuf);
				// system error checking file
				return -1;
			}
			else if (status == 1)
			{
				// The entry has unrecoverable error and has been deleted,
				//   but the actual disk writing is not yet done
				// 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
			}
		}
	}

#ifdef FAT_LFN
#else
	// if the dir entries have been changed and the automatic fix is enabled,
	//   actually write the changes to the disk
	if (changed == 1 && autoFix == 1)
	{
		if (FAT_write_cluster(drive, traceCluster, dirBuf) == ATA_FAILURE)
		{
			FATErrno = ERROR_ATA_WRITE;
			ap_free(dirBuf);
			return -1;
		}
	}
#endif
	// fat12
	if (FATType[drive] == PART_DOS2_FAT)
	{
		if ((traceCluster & 0x0001) == 0x0001)
		{
							// part1				// part2
			tempCluster = ((unsigned short)pFatBuf[(traceCluster * 3 / 2) + 1] << 4) + ((pFatBuf[traceCluster * 3 / 2] & 0xF0) >> 4);
		
			// clear this FAT entry since it has already been handled
			// part1
			pFatBuf[traceCluster * 3 / 2] &= 0x0F;
			// part2
			pFatBuf[(traceCluster * 3 / 2) + 1] = 0x0;
		}
		else
		{
							// part2				// part1
			tempCluster = (((unsigned short)pFatBuf[(traceCluster * 3 / 2) + 1] & 0x0F) << 8) + pFatBuf[traceCluster * 3 / 2];
			// clear this FAT entry since it has already been handled
			// part1
			pFatBuf[traceCluster * 3 / 2] &= 0x0;
			// part2
			pFatBuf[(traceCluster * 3 / 2) + 1] &= 0xF0;
		}
	}
	else
	{
		tempCluster = FATBuf[traceCluster];
		// clear this FAT entry since it has already been handled
		FATBuf[traceCluster] = 0x0;
	}
	
	// get next cluster in the chain
//	tempCluster = FATBuf[traceCluster];
	// clear this FAT entry since it has already been proceeded
//	FATBuf[traceCluster] = 0x0;

	// empty dir entry found, see if the cluster chain actually ends at this cluster
	if (noMore == 1)
	{
		if (tempCluster < FATEndOfChain[FATType[drive]])
		{
			// there should be no more cluster but the cluster chain is not end yet
			if (echo == ECHO_ON)
			{
				printString("[DIR] ");
				printString((char *)name);
				printStringLn(" [CLUSTER CHAIN INCORRECT]");
			}
			if (autoFix == 1)
			{
				// well, fix this error by giving the chain a real end
				FAT_write_fat_cluster(drive, traceCluster, FATEndOfChain[FATType[drive]]);
			}
			fileErrCount++;

			ap_free(dirBuf);
			return 1;
		}
	}

	if (tempCluster >= FATEndOfChain[FATType[drive]])
		break;
		
	// check if the cluster is valid
	if (tempCluster >= FATTotalCluster[drive] + 2 || tempCluster < 2)
	{
		if (autoFix == 1)
			FAT_write_fat_cluster(drive, traceCluster, FATEndOfChain[FATType[drive]]);

		if (echo == ECHO_ON)
		{
			printString("[DIR] ");
			printString((char *)name);
			printStringLn(" [INCORRECT CLUSTER CHAIN]");
		}
		fileErrCount++;

		ap_free(dirBuf);
		
		return 1;
	}
#ifdef FAT_LFN
	prevCluster = traceCluster;
#endif
	traceCluster = tempCluster;
  }

  ap_free(dirBuf);

  return 0;
}


#endif // FAT_ID

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -