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

📄 fdefrag.c

📁 PDA上的CF CARD 文件系统的建立程式
💻 C
📖 第 1 页 / 共 3 页
字号:
			write_fat_cluster_to_fatBuffer(drive, clusterNo1, tmpClusterNo);
		}

  	}

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

}

/*************************************************************
Fuction : FAT_find_entry_location_by_startCluster
	Search the block where startCluster value locates
Input:
	drive - drive number
	startCluster - cluster value that's going to be searched
Output:
        0: no error is found
       -1: error (see FATError)
       
       block: the block number
       entry: the entry in the block
       isRoot: in the root directory?
**************************************************************/
int FAT_find_entry_location_by_startCluster(short drive, unsigned short startCluster, \
	unsigned long *block, unsigned long *entry, int *isRoot)
{
  // used to search for an entry that matches a certain clusterNo
  // in FAT_find_entry_location_by_startCluster()
  struct dLinkList 	*pList;

  unsigned long		i, j;
  unsigned char		*rootSecBuffer;
  unsigned char 	*clusterBuffer;
  unsigned short	clusterNo;
  unsigned short	currCluster;
  int			done;
  struct defrag_dir	*currentDir;
  
  if ((rootSecBuffer = (unsigned char *) ap_malloc(SECTOR_SIZE)) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }
  
  if ((clusterBuffer = (unsigned char *) ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	ap_free(rootSecBuffer);
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }
  
  
  // search from root directory
  done = 0;
  
  for (i = FATRootBegin[drive]; i < FATRootBegin[drive] + FATSecPerROOT[drive]; i++)
  {
  	if (FAT_read_root_sector(drive, i, (unsigned short *)rootSecBuffer) == ATA_FAILURE)
  	{
  		ap_free(rootSecBuffer);
  		ap_free(clusterBuffer);
  		return -1;
  	}
  	
  	for (j = 0; j < SECTOR_SIZE; j += FAT_DIR_ENTRY_SIZE)
  	{
  		if (*(rootSecBuffer + j) == '\0')
  		{
  			done = 1;
  			break;
  		}
  		else if(*(rootSecBuffer + j) == FAT_DELETED_ENTRY)
  			continue;
#ifdef FAT_LFN
  		else if ((*(rootSecBuffer + j + 11) & DA_VFAT) == DA_VFAT)
  			continue;
#endif		
		// get its start cluster
		clusterNo = *(rootSecBuffer + j + 27) << 8;
		clusterNo |= *(rootSecBuffer + j + 26);
			
		if (clusterNo == startCluster)
		{
			*block = i;
			*entry = j;
			*isRoot = 1;
				
			ap_free(rootSecBuffer);
			ap_free(clusterBuffer);
				
			return 0;
		}
  	}
  	
  	if (done == 1)
  		break;
  }
  
  // rootSecBuffer won't be used anymore
  ap_free(rootSecBuffer);
  
  // search from subdir
  pList = &defragDirList;
  while(pList->back != NULL)
  {
  	currentDir = (struct defrag_dir *)pList->back->elementPointer;
  	currCluster = currentDir->startCluster;
  	
  	for (;;)
  	{
  		if (FAT_read_cluster(drive, currCluster, (unsigned short *)clusterBuffer) == -1)
  		{
  			ap_free(clusterBuffer);
  			
  			return -1;
  		}

		done = 0;  		
  		for (j = 0; j < FATBytesPerCluster[drive]; j += FAT_DIR_ENTRY_SIZE)
  		{
  			if (*(clusterBuffer + j) == '\0')
  			{
  				done = 1;
  				break;
  			}
  			else if(*(clusterBuffer + j) == FAT_DELETED_ENTRY)
  				continue;
  			else if (*(clusterBuffer + j) == '.')
  				continue;
	#ifdef FAT_LFN
  			else if ((*(clusterBuffer + j + 11) & DA_VFAT) == DA_VFAT)
	  			continue;
	#endif		
			// get its start cluster
			clusterNo = *(clusterBuffer + j + 27) << 8;
			clusterNo |= *(clusterBuffer + j + 26);
			
			if (clusterNo == startCluster)
			{
				*block = currCluster;
				*entry = j;
				*isRoot = 0;
				
				ap_free(clusterBuffer);
				
				return 0;
			}
  		}
		if (done == 1)
			break;
  		
		currCluster = read_fat_cluster_from_fatBuffer(drive, currCluster);
		
  		if (currCluster >= FATEndOfChain[FATType[drive]])
  		{
  			break;
  		}
  	}
  	pList = pList->back;
  }
  
  ap_free(clusterBuffer);

  // not found
  return -1;
  
}

/*************************************************************
Fuction : FAT_free_dirLinkList
	free resources from directory linking list(defragDirList),
	including the memory pointed to by the elementPointer
Input:
	list - the pointer to the linking list
Output:
        0: no error is found
       -1: error (see FATError)
       
**************************************************************/
void FAT_free_dirLinkList(struct dLinkList *list)
{
  struct defrag_dir *currentDir;
  
  while (list->back != NULL)
  {
  	currentDir = (struct defrag_dir *)list->back->elementPointer;
	removeFrom(list->back);

	ap_free(currentDir);
  }
}

/*************************************************************
Fuction : FAT_defrag_subdir
	defrag all subdirectories
Input:
	drive - drive number
Output:
        0: no error is found
       -1: error (see FATError)
**************************************************************/
int FAT_defrag_subdir(short drive)
{

  unsigned long 	j, k;
  unsigned char		*oldClusterBuffer, *newClusterBuffer;
  int			done;
  unsigned long		updateClusterNo;
  unsigned short	clusterNo, currCluster;
  struct defrag_dir	*currentDir;
  struct dLinkList	*pList;
  int			dirty;

  if ((oldClusterBuffer = (unsigned char *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }
  
  if ((newClusterBuffer = (unsigned char *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	
  	ap_free(oldClusterBuffer);
  	return -1;
  }
  myMemSet(newClusterBuffer, 0, FATBytesPerCluster[drive]);
  
  
  // 1. rearrange dir entries, not letting any unused entries be placed
  // 	between two used entries
  k = 0;
  pList = &defragDirList;
  while(pList->back != NULL)
  {
  	currentDir = (struct defrag_dir *)pList->back->elementPointer;
  	currCluster = currentDir->startCluster;

	updateClusterNo = currCluster;
  	for (;;)
  	{
  		if (FAT_read_cluster(drive, currCluster, (unsigned short *)oldClusterBuffer) == -1)
  		{
  			ap_free(oldClusterBuffer);
  			ap_free(newClusterBuffer);
  			
  			return -1;
  		}

		done = 0;
  		for (j = 0; j < FATBytesPerCluster[drive]; j += FAT_DIR_ENTRY_SIZE)
  		{
  			if (*(oldClusterBuffer + j) == '\0')
  			{
	  			if (FAT_write_cluster(drive, updateClusterNo, \
	  				(unsigned short *)newClusterBuffer) == -1)
  				{
  					ap_free(oldClusterBuffer);
  					ap_free(newClusterBuffer);
  					return -1;
  				}
	  			k = 0;
  				myMemSet(newClusterBuffer, 0, FATBytesPerCluster[drive]);
  				
  				done = 1;
  				break;
  			}
  			else if(*(oldClusterBuffer + j) == FAT_DELETED_ENTRY)
  			{
  				continue;
  			}
  			// copy the entry from the old sector to the new sector
  			myMemCpy(newClusterBuffer + k, oldClusterBuffer + j, FAT_DIR_ENTRY_SIZE);
  			k += FAT_DIR_ENTRY_SIZE;
  		
  			if (k > FATBytesPerCluster[drive])
  			{
  				if (FAT_write_cluster(drive, updateClusterNo, \
  					(unsigned short *)newClusterBuffer) == -1)
  				{
  					ap_free(oldClusterBuffer);
  					ap_free(newClusterBuffer);
  					return -1;
  				}
  			
	  			k = 0;
				updateClusterNo = read_fat_cluster_from_fatBuffer(drive, updateClusterNo);
				
  				myMemSet(newClusterBuffer, 0, FATBytesPerCluster[drive]);
  			}
  			
  		}
		if (done == 1)
			break;
  		
		currCluster = read_fat_cluster_from_fatBuffer(drive, currCluster);
		
  		if (currCluster >= FATEndOfChain[FATType[drive]])
  		{
  			break;
  		}
  	}
	pList = pList->back;
  }
  
  // we don't need newClusterBuffer anymore
  ap_free(newClusterBuffer);
  
  // 2. handle all clusters that all subdir entries occupy
  pList = &defragDirList;
  while(pList->back != NULL)
  {
  	currentDir = (struct defrag_dir *)pList->back->elementPointer;
  	currCluster = currentDir->startCluster;
  	
  	for (;;)
  	{
  		if (FAT_read_cluster(drive, currCluster, (unsigned short *)oldClusterBuffer) == -1)
  		{
  			ap_free(oldClusterBuffer);
  			
  			return -1;
  		}

		done = 0;
  		for (j = 0; j < FATBytesPerCluster[drive]; j += FAT_DIR_ENTRY_SIZE)
  		{
  			if (*(oldClusterBuffer + j) == '\0')
  			{
  				done = 1;
  				break;
  			}
  			else if(*(oldClusterBuffer + j) == FAT_DELETED_ENTRY)
  			{
  				continue;
  			}
	#ifdef FAT_LFN
  			else if ((*(oldClusterBuffer + j + 11) & DA_VFAT) == DA_VFAT)
  			{
	  			continue;
  			}
	#endif		
			else if (*(oldClusterBuffer + j) == '.')
				continue;
  		
 	 		// start cluster
			clusterNo = *(oldClusterBuffer + j + 27) << 8;
			clusterNo |= *(oldClusterBuffer + 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(oldClusterBuffer);
	  					return -1;
	  				}
	  				
					// 2. swap cluster data
					if (FAT_swap_cluster_data(drive, clusterNo, defragClusterNo) == -1)
					{
	  					ap_free(oldClusterBuffer);
  						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 
			// clusterBuffer for fear that the current clusterBuffer
			// is not consistent with the new one
			if (dirty == 1)
			{
  				if (FAT_read_cluster(drive, currCluster, \
  					(unsigned short *)oldClusterBuffer) == -1)
	  			{
  					ap_free(oldClusterBuffer);
  					return -1;
  				}
			}
		}
		
	  	if (done == 1)
  			break;
  			
		currCluster = read_fat_cluster_from_fatBuffer(drive, currCluster);
  		if (currCluster >= FATEndOfChain[FATType[drive]])
  		{
  			break;
  		}
		
  	}

	pList = pList->back;  	
  }

  // 3. update the cluster value of all '.' and '..'
  pList = &defragDirList;
  while (pList->back != NULL)
  {
  	currentDir = (struct defrag_dir *) pList->back->elementPointer;
  	
	if (FAT_read_cluster(drive, currentDir->startCluster, (unsigned short *)oldClusterBuffer) == -1)
	{
		ap_free(oldClusterBuffer);
		return -1;
	}
	
	// update the cluster value of '.'
	*(oldClusterBuffer + 26) = (unsigned char) (currentDir->startCluster & 0x00ff);
	*(oldClusterBuffer + 27) = (unsigned char) (currentDir->startCluster >> 8);
	
	// update the cluster value of '..'
	*(oldClusterBuffer + FAT_DIR_ENTRY_SIZE + 26) = (unsigned char) (currentDir->parentCluster & 0x00ff);
	*(oldClusterBuffer + FAT_DIR_ENTRY_SIZE + 27) = (unsigned char) (currentDir->parentCluster >> 8);
	
	if (FAT_write_cluster(drive, currentDir->startCluster, (unsigned short *)oldClusterBuffer) == -1)
	{
		ap_free(oldClusterBuffer);
		return -1;
	}
	
	pList = pList->back;
  }
  
  ap_free(oldClusterBuffer);
  return 0;

}

/*************************************************************
Fuction : FAT_update_clustersInDefragList
	update startCluster and parentCluster in defrag_dir if 
	they are swapped while defragging
Input:
	swapClusterNo1 - cluster number 1 that's going to be swapped with swapClusterNo2
	swapClusterNo2 - cluster number 2 that's going to be swapped with swapClusterNo1
Output:
**************************************************************/
void FAT_update_clustersInDefragList(unsigned short swapClusterNo1, unsigned short swapClusterNo2)
{
  struct dLinkList *tmpLinkList;
  struct defrag_dir *tmpDir;
  
  tmpLinkList = &defragDirList;
  while(tmpLinkList->back != NULL)
  {
  	tmpDir = (struct defrag_dir *) tmpLinkList->back->elementPointer;

  	if (tmpDir->startCluster == swapClusterNo1)
  		tmpDir->startCluster = swapClusterNo2;
  	else if (tmpDir->startCluster == swapClusterNo2)
  		tmpDir->startCluster = swapClusterNo1;
  		
  	if (tmpDir->parentCluster == swapClusterNo1)
  		tmpDir->parentCluster = swapClusterNo2;
  	else if (tmpDir->parentCluster == swapClusterNo2)
  		tmpDir->parentCluster = swapClusterNo1;

  	tmpLinkList = tmpLinkList->back;
  }
  
  return;
}

/*************************************************************
Fuction : read_fat_cluster_from_fatBuffer
	read cluster value from fat buffer
Input:
	drive - drive number
	clusterNo - the clusterNo-th entry in fat tables
Output:
	the next cluster value
**************************************************************/
unsigned short read_fat_cluster_from_fatBuffer(short drive, unsigned short clusterNo)
{
  unsigned char *pFatBuf = (unsigned char *) FATBuf;
  unsigned short result;
  
  // fat12  
  if (FATType[drive] == PART_DOS2_FAT)
  {
  	if (clusterNo & 0x0001 == 0x0001)
  	{
     		result = ((unsigned short)pFatBuf[(clusterNo * 3 / 2) + 1] << 4) + \
     			((pFatBuf[clusterNo * 3 / 2] & 0xF0) >> 4);
  	}
	else
  	{
		result = (((unsigned short)pFatBuf[(clusterNo * 3 / 2) + 1] & 0x0F) << 8) + \
			pFatBuf[clusterNo * 3 / 2];
  	}
  	
  	return result;
  }
  // fat 16
  else
  {
  	return FATBuf[clusterNo];
  }
  
}

/*************************************************************
Fuction : write_fat_cluster_to_fatBuffer
	write cluster value to fat buffer
Input:
	drive - drive number
	clusterNo - the clusterNo-th entry in fat tables
	cluster - the cluster value that's going to be written
Output:
**************************************************************/
void write_fat_cluster_to_fatBuffer(short drive, unsigned short clusterNo, unsigned short cluster)
{
  unsigned char part1, part2;
  unsigned char *pFatBuf = (unsigned char *)FATBuf;

  if (FATType[drive] == PART_DOS2_FAT)
  {
	// update the next cluster value of clusterNo2 to the next cluster of clusterNo1
  	if ((clusterNo & 0x0001) == 0x0001)
  	{
  		// write clusterNo1 into fat tables
		part1 = (unsigned char)((cluster & 0x000F) << 4);
		part2 = (unsigned char)((cluster & 0x0FF0) >> 4);
		pFatBuf[clusterNo * 3 / 2] = (pFatBuf[clusterNo * 3 / 2] & 0x0F) | part1;
		pFatBuf[(clusterNo * 3 / 2) + 1] = part2;
  	}
  	else
  	{
  		// write clusterNo1 into fat tables
		part1 = (unsigned char)(cluster & 0x00FF);
		part2 = (unsigned char)((cluster & 0x0F00) >> 8);
		pFatBuf[clusterNo * 3 / 2] = part1;
		pFatBuf[(clusterNo * 3 / 2) + 1] = (pFatBuf[(clusterNo * 3 / 2) + 1] & 0xF0) | part2;
  	}
  }
  // fat16
  else
  {
  	FATBuf[clusterNo] = cluster;
  }

}
#endif // FAT_ID

⌨️ 快捷键说明

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