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

📄 fdefrag.c

📁 嵌入式系统中文件系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
  		break;
  }
  
  // we don't need newRootSecBuffer anymore
  ap_free(newRootSecBuffer);
  
  // 2. handle all clusters that all root entries occupy
  done = 0;
  for (i = FATRootBegin[drive]; i < FATRootBegin[drive] + FATSecPerROOT[drive]; i++)
  {
  	if (FAT_read_root_sector(drive, i, (unsigned short *)oldRootSecBuffer) == ATA_FAILURE)
  	{
  		ap_free(oldRootSecBuffer);
  		ap_free(clusterBuffer);
  		return -1;
  	}
  	
  	for (j = 0; j < SECTOR_SIZE; j += FAT_DIR_ENTRY_SIZE)
  	{
  		if (oldRootSecBuffer[j] == '\0')
  		{
  			done = 1;
  			break;
  		}
  		else if(*(oldRootSecBuffer + j) == FAT_DELETED_ENTRY)
  		{
  			continue;
  		}
#ifdef FAT_LFN
  		else if ((*(oldRootSecBuffer + j + 11) & DA_VFAT) == DA_VFAT)
  		{
  			continue;
  		}
#endif		
  		
  		// start cluster
		clusterNo = *(oldRootSecBuffer + j + 27) << 8;
		clusterNo |= *(oldRootSecBuffer + j + 26);

		dirty = 0;
		while(1)
		{
			if (clusterNo != defragClusterNo)
			{
	  			// 1. swap cluster values in fat table(s) or entries
  				if (FAT_swap_fat_cluster(drive, clusterNo, defragClusterNo) == -1)
  				{
  					ap_free(oldRootSecBuffer);
			  		ap_free(clusterBuffer);
  					return -1;
	  			}

				// 2. swap cluster
				if (FAT_swap_cluster_data(drive, clusterNo, defragClusterNo) == -1)
				{
  					ap_free(oldRootSecBuffer);
			  		ap_free(clusterBuffer);
  					return -1;
				}
  			
				// 3. update the entries with startCluster = defragClusterNo in the defragList 
				//    for fear that their startCluster might have been swapped
				FAT_update_clustersInDefragList(clusterNo, defragClusterNo);
	  			
				// After swapping, clusterNo should be defragClusterNo now
				clusterNo = defragClusterNo;
				
				dirty = 1;
			}
  			// move on to the next cluster that needs defragging
  			defragClusterNo++;
  			
  			if ((clusterNo = read_fat_cluster_from_fatBuffer(drive, clusterNo)) >= \
  				FATEndOfChain[FATType[drive]])
  			{
  				break;
  			}
		}

		// if we just did the defragging, we need to re-read 
		// rootSecBuffer for fear that the current rootSecBuffer
		// is not consistent with the new one
		if (dirty == 1)
		{
  			if (FAT_read_root_sector(drive, i, (unsigned short *)oldRootSecBuffer) == ATA_FAILURE)
  			{
  				ap_free(oldRootSecBuffer);
		  		ap_free(clusterBuffer);
  				return -1;
  			}
		}
		
  	}
  	
  	if (done == 1)
  		break;
  }

  ap_free(oldRootSecBuffer);
  ap_free(clusterBuffer);
  
  return 0;
}


/*************************************************************
Fuction : FAT_swap_cluster_data
	swap the cluster data
Input:
	drive - drive number
	clusterNo1 - cluster number 1 that's going to be swapped
	clusterNo2 - cluster number 2 that's going to be swapped
Output:
	        0: no error is found
	       -1: error (see FATError)
**************************************************************/
int FAT_swap_cluster_data(short drive, unsigned short clusterNo1, unsigned short clusterNo2)
{
  unsigned char		*clusterBuffer1, *clusterBuffer2, *tmpClusterBuffer;
  
  if (InitFAT == FALSE)
  	return -1;
  	
  if (clusterNo1 >= FATEndOfChain[FATType[drive]] || clusterNo2 >= FATEndOfChain[FATType[drive]])
  	return -1;
  
  if ((clusterBuffer1 = (unsigned char *) ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }
  
  if ((clusterBuffer2 = (unsigned char *) ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	
  	ap_free(clusterBuffer1);
  	return -1;
  }
  myMemSet(clusterBuffer2, 0, FATBytesPerCluster[drive]);

  if ((tmpClusterBuffer = (unsigned char *) ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	ap_free(clusterBuffer1);
  	ap_free(clusterBuffer2);
  	return -1;
  }

  // read clusterNo1
  if (FAT_read_cluster(drive, clusterNo1, (unsigned short *)clusterBuffer1) == -1)
  {
  	ap_free(clusterBuffer1);
  	ap_free(clusterBuffer2);
  	ap_free(tmpClusterBuffer);
  	return -1;
  }
  	
  // read clusterNo2
  if (FAT_read_cluster(drive, clusterNo2, (unsigned short *)clusterBuffer2) == -1)
  {
  	ap_free(clusterBuffer1);
  	ap_free(clusterBuffer2);
  	ap_free(tmpClusterBuffer);
  	return -1;
  }
  	
  // swap clusterNo1 data with clusterNo2 data
  myMemCpy(tmpClusterBuffer, clusterBuffer1, FATBytesPerCluster[drive]);
  myMemCpy(clusterBuffer1, clusterBuffer2, FATBytesPerCluster[drive]);
  myMemCpy(clusterBuffer2, tmpClusterBuffer, FATBytesPerCluster[drive]);

  // Only if clusterNo1 is not free, we swap the data
  if (read_fat_cluster_from_fatBuffer(drive, clusterNo1) != 0x0)
  {
  	if (FAT_write_cluster(drive, clusterNo1, (unsigned short *)clusterBuffer1) == -1)
  	{
  		ap_free(clusterBuffer1);
  		ap_free(clusterBuffer2);
  		ap_free(tmpClusterBuffer);
  		return -1;
  	}
  }
  	
  // Only if clusterNo1 is not free, we swap the data
  if (read_fat_cluster_from_fatBuffer(drive, clusterNo2) != 0x0)
  {
	if (FAT_write_cluster(drive, clusterNo2, (unsigned short *)clusterBuffer2) == -1)
  	{
  		ap_free(clusterBuffer1);
  		ap_free(clusterBuffer2);
  		ap_free(tmpClusterBuffer);
  		return -1;
  	}
  }

  ap_free(clusterBuffer1);
  ap_free(clusterBuffer2);
  ap_free(tmpClusterBuffer);
  
  return 0;
  	
}


/*************************************************************
Fuction : FAT_swap_fat_cluster
	swap the cluster value in fat tables and directory entries
Input:
	drive - drive number
	clusterNo1 - cluster number 1 that's going to be swapped
	clusterNo2 - cluster number 2 that's going to be swapped
Output:
	        0: no error is found
	       -1: error (see FATError)
**************************************************************/
int FAT_swap_fat_cluster(short drive, unsigned short clusterNo1, unsigned short clusterNo2)
{
  unsigned short 	parentClusterNo1, parentClusterNo2;
  int			isRoot1;
  int			isRoot2;
  int			sameBlock = 0;
  unsigned long		block1, entry1;
  unsigned long		block2, entry2;
  unsigned char		*rootSecBuffer, *clusterBuffer;
  long			i;
  unsigned short	tmpClusterNo;

  if (InitFAT == FALSE || drive < 0)
  	return -1;
  	
  if (clusterNo1 == clusterNo2)
  	return 0;
  	
  if (clusterNo1 < 2 || clusterNo2 < 2 || clusterNo1 >= FATEndOfChain[FATType[drive]] || \
  	clusterNo2 >= FATEndOfChain[FATType[drive]])
  {
  	return -1;
  }
  
  if ((clusterBuffer = (unsigned char *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	return -1;
  }
  
  if ((rootSecBuffer = (unsigned char *)ap_malloc(SECTOR_SIZE)) == NULL)
  {
  	ap_free(clusterBuffer);
  	return -1;
  }
  
  // find parent clusters of clusterNo1 and clusterNo2
  parentClusterNo1 = parentClusterNo2 = 0;
  for (i = 2; i < FATTotalCluster[drive] + 2; i++)
  {
  	tmpClusterNo = read_fat_cluster_from_fatBuffer(drive, i);
  
  	if (tmpClusterNo == clusterNo1)
  		parentClusterNo1 = i;
  			
	if (tmpClusterNo == clusterNo2)
		parentClusterNo2 = i;
		
	// two parent clusters are found
	if (parentClusterNo1 != 0 && parentClusterNo2 != 0)
		break;
  }
	
  // swap clusterNo1 value with clusterNo2 value in fat table(s)

  if (parentClusterNo1 != 0 && parentClusterNo2 != 0)
  {	
  	// no1
  	write_fat_cluster_to_fatBuffer(drive, parentClusterNo1, clusterNo2);
  	tmpClusterNo = read_fat_cluster_from_fatBuffer(drive, clusterNo2);
  	write_fat_cluster_to_fatBuffer(drive, clusterNo2, read_fat_cluster_from_fatBuffer(drive, clusterNo1));
  	
  	// no2
  	write_fat_cluster_to_fatBuffer(drive, parentClusterNo2, clusterNo1);
  	write_fat_cluster_to_fatBuffer(drive, clusterNo1, tmpClusterNo);
  }
  else if (parentClusterNo1 != 0 && parentClusterNo2 == 0)
  {
  	// no1
  	write_fat_cluster_to_fatBuffer(drive, parentClusterNo1, clusterNo2);
  	tmpClusterNo = read_fat_cluster_from_fatBuffer(drive, clusterNo2);
  	write_fat_cluster_to_fatBuffer(drive, clusterNo2, read_fat_cluster_from_fatBuffer(drive, clusterNo1));
  	
  	// no2
  	if (tmpClusterNo == 0)
  	{
  		// clusterNo2 is a free entry
  		write_fat_cluster_to_fatBuffer(drive, clusterNo1, 0);
  	}
  	else
  	{
		if(FAT_find_entry_location_by_startCluster(drive, clusterNo2, &block2, &entry2, &isRoot2) == -1)
  		{
  			// A cluster loss!
	  		ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
  			return -1;
	  	}
  		
		if (isRoot2 == 1)
		{
			if (FAT_read_root_sector(drive, block2, (unsigned short *)rootSecBuffer) != ATA_OK)
			{
	  			ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				return -1;
			}
				
			*(rootSecBuffer + entry2 + 26) = (unsigned char) (clusterNo1 & 0x00ff);
			*(rootSecBuffer + entry2 + 27) = (unsigned char) (clusterNo1 >> 8);
				
			if (FAT_update_root_sector(drive, block2, (unsigned short *)rootSecBuffer) == ATA_FAILURE)
			{
	  			ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				return -1;
			}
			
			write_fat_cluster_to_fatBuffer(drive, clusterNo1, tmpClusterNo);
		}
		else
		{
			if (FAT_read_cluster(drive, block2, (unsigned short *)clusterBuffer) == -1)
			{
				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
	  			return -1;
			}
		
			*(clusterBuffer + entry2 + 26) = (unsigned char) (clusterNo1 & 0x00ff);
			*(clusterBuffer + entry2 + 27) = (unsigned char) (clusterNo1 >> 8);
				
			if (FAT_write_cluster(drive, block2, (unsigned short *)clusterBuffer) == -1)
			{
  				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
	  			return -1;
			}

			write_fat_cluster_to_fatBuffer(drive, clusterNo1, tmpClusterNo);
		}
  	}
  }
  else if (parentClusterNo1 == 0 && parentClusterNo2 != 0)
  {
  	// no2
  	write_fat_cluster_to_fatBuffer(drive, parentClusterNo2, clusterNo1);
  	tmpClusterNo = read_fat_cluster_from_fatBuffer(drive, clusterNo1);
  	write_fat_cluster_to_fatBuffer(drive, clusterNo1, read_fat_cluster_from_fatBuffer(drive, clusterNo2));
  	
  	// no1
	if (tmpClusterNo == 0)
  	{
  		// clusterNo1 is a free entry
  		write_fat_cluster_to_fatBuffer(drive, clusterNo2, 0);
  	}
  	else
  	{
		if(FAT_find_entry_location_by_startCluster(drive, clusterNo1, &block1, &entry1, &isRoot1) == -1)
  		{
  			// A cluster loss!
	  		ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
  			return -1;
	  	}
  		
		if (isRoot1 == 1)
		{
			if (FAT_read_root_sector(drive, block1, (unsigned short *)rootSecBuffer) != ATA_OK)
			{
	  			ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				return -1;
			}
				
			*(rootSecBuffer + entry1 + 26) = (unsigned char) (clusterNo2 & 0x00ff);
			*(rootSecBuffer + entry1 + 27) = (unsigned char) (clusterNo2 >> 8);
				
			if (FAT_update_root_sector(drive, block1, (unsigned short *)rootSecBuffer) == ATA_FAILURE)
			{
	  			ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				return -1;
			}
			
			write_fat_cluster_to_fatBuffer(drive, clusterNo2, tmpClusterNo);
		}
		else
		{
			if (FAT_read_cluster(drive, block1, (unsigned short *)clusterBuffer) == -1)
			{
				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
	  			return -1;
			}
		
			*(clusterBuffer + entry1 + 26) = (unsigned char) (clusterNo2 & 0x00ff);
			*(clusterBuffer + entry1 + 27) = (unsigned char) (clusterNo2 >> 8);
				
			if (FAT_write_cluster(drive, block1, (unsigned short *)clusterBuffer) == -1)
			{
  				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
	  			return -1;
			}

			write_fat_cluster_to_fatBuffer(drive, clusterNo2, tmpClusterNo);
		}
  	}
  	
  }
  else
  {
  	// no1
/*	if (read_fat_cluster_from_fatBuffer(drive, clusterNo1) == 0)
  	{
  		// clusterNo1 is a free entry
  		write_fat_cluster_to_fatBuffer(drive, clusterNo2, 0);
  	}
  	else
  	{
		if(FAT_find_entry_location_by_startCluster(drive, clusterNo1, &block1, &entry1, &isRoot1) == -1)
  		{
  			// A cluster loss!
	  		ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
  			return -1;
	  	}
  	}*/

  	// no1
  	
  	// attention: we don't use the above code because we assume only clusterNo2 could be a free cluster
	if(FAT_find_entry_location_by_startCluster(drive, clusterNo1, &block1, &entry1, &isRoot1) == -1)
	{
		// A cluster loss!
 		ap_free(rootSecBuffer);
		ap_free(clusterBuffer);
		return -1;
  	}

	// record the next cluster of clusterNo2 temporarily
	tmpClusterNo = read_fat_cluster_from_fatBuffer(drive, clusterNo2);
  	if (tmpClusterNo != 0)
  	{
  		// we need to find the block where clusterNo2 locates before we update the block where clusterNo1
  		// locates for later updates
		if(FAT_find_entry_location_by_startCluster(drive, clusterNo2, &block2, &entry2, &isRoot2) == -1)
  		{
  			// A cluster loss!
	  		ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
  			return -1;
	  	}
	  	
	  	if (isRoot1 == isRoot2 && block1 == block2)
	  		sameBlock = 1;
  	}
	
	if (isRoot1 == 1)
	{
		if (FAT_read_root_sector(drive, block1, (unsigned short *)rootSecBuffer) != ATA_OK)
		{
	 		ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
  			return -1;
		}
				
		*(rootSecBuffer + entry1 + 26) = (unsigned char) (clusterNo2 & 0x00ff);
		*(rootSecBuffer + entry1 + 27) = (unsigned char) (clusterNo2 >> 8);

		if (sameBlock == 0)
		{				
			if (FAT_update_root_sector(drive, block1, (unsigned short *)rootSecBuffer) == ATA_FAILURE)
			{
	  			ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				return -1;
			}
		}
			
		write_fat_cluster_to_fatBuffer(drive, clusterNo2, \
			read_fat_cluster_from_fatBuffer(drive, clusterNo1));
	}
	else
	{
		if (FAT_read_cluster(drive, block1, (unsigned short *)clusterBuffer) == -1)
		{
			ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
	  		return -1;
		}
		
		*(clusterBuffer + entry1 + 26) = (unsigned char) (clusterNo2 & 0x00ff);
		*(clusterBuffer + entry1 + 27) = (unsigned char) (clusterNo2 >> 8);

		if (sameBlock == 0)
		{				
			if (FAT_write_cluster(drive, block1, (unsigned short *)clusterBuffer) == -1)
			{
  				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
	  			return -1;
			}
		}

		write_fat_cluster_to_fatBuffer(drive, clusterNo2, \
			read_fat_cluster_from_fatBuffer(drive, clusterNo1));
	}
  	
  	
  	// no2
  	if (tmpClusterNo == 0)
  	{
  		// clusterNo2 is a free entry
  		write_fat_cluster_to_fatBuffer(drive, clusterNo1, 0);
  	}
  	else
  	{
		// only if clusterNo1 and clusterNo2 locate in different blocks do we read
		// the new block
		if (sameBlock == 0)
		{
			if (isRoot2 == 1)
			{
				if (FAT_read_root_sector(drive, block2, (unsigned short *)rootSecBuffer) != ATA_OK)
				{
	  				ap_free(rootSecBuffer);
					ap_free(clusterBuffer);
  					return -1;
				}
			}
			else
			{
				if (FAT_read_cluster(drive, block2, (unsigned short *)clusterBuffer) == -1)
				{
					ap_free(rootSecBuffer);
					ap_free(clusterBuffer);
		  			return -1;
				}
			}
		}
		
		if (isRoot2 == 1)
		{
			*(rootSecBuffer + entry2 + 26) = (unsigned char) (clusterNo1 & 0x00ff);
			*(rootSecBuffer + entry2 + 27) = (unsigned char) (clusterNo1 >> 8);
				
			if (FAT_update_root_sector(drive, block2, (unsigned short *)rootSecBuffer) == ATA_FAILURE)
			{
	  			ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				return -1;
			}
			
			write_fat_cluster_to_fatBuffer(drive, clusterNo1, tmpClusterNo);
		}
		else
		{
			*(clusterBuffer + entry2 + 26) = (unsigned char) (clusterNo1 & 0x00ff);
			*(clusterBuffer + entry2 + 27) = (unsigned char) (clusterNo1 >> 8);
				
			if (FAT_write_cluster(drive, block2, (unsigned short *)clusterBuffer) == -1)
			{
  				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
	  			return -1;
			}

⌨️ 快捷键说明

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