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

📄 fdefrag.c

📁 PDA上的CF CARD 文件系统的建立程式
💻 C
📖 第 1 页 / 共 3 页
字号:
/*************************************************************
File Name: fdefrag.c                                         *
**************************************************************
Programmer: chilong
Last Modified Date: 2001/6/3
Compiler : Gnu Cross-compiler
Platform : X86 protection mode
Usage :
	scanDisk functions for FAT1X_defrag
	See defrag.h for usage.
*************************************************************/
#include <pr2k.h>
#include <kernel/linklist.h>
#include <sys/syscall.h>
#include <kernel/malloc.h>

#include <stdio.h>

#ifdef _PROCOMP_
  #include "/rtos/driver/FileSys/FileSys.h"
#else
  #include "../../FileSys/include/FileSys.h"
#endif

#include "../include/init.h"
#include "../include/cluster.h"
#include "../include/unicode.h"
#include "../include/fat1x.h"
#include "../include/fdefrag.h"

#ifdef FAT_USE_PCMCIA
  
  /**** added by chilong ****/
  //#include "../pcm/cf_typedef.h"
  /**** added by chilong ****/
  
  //#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

#ifdef FAT_ID

/* 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[];

// fscan.c
extern unsigned short *FATBuf;

/**** added by chilong 12/4/2001 ****/
// fat1x.c
extern struct FAT_FILE **FATHandleTable;
/**** added by chilong 12/4/2001 ****/

unsigned short defragClusterNo;

// used to record subdirs that need defragging
struct dLinkList defragDirList;

/**** added by chilong 10/5/2001 ****/
#ifdef FAT_FAT_CACHE_ON
/* FAT cache */
extern struct FAT_fatCache FATFatCache[FAT_FAT_CACHE_BLOCK];
#endif

/**** added by chilong 10/5/2001 ****/

/*************************************************************
Fuction : FAT_defrag
	defrag FAT1x disk
	
	// method
	introduction:
	   1. Record all directories in defragDirList
	   2. Start defragging from root directory. 
	      a) We move all entries upwards by removing all deleted entries
	      b) We defrag root directory entries, sorting every entry from
	      	 cluster number 2.
	   3. Then according to defragDirList, we go through the same
	      steps as we do to root directory. Finally, we update the cluster
	      values of '.' and '..' that might be swapped during defragging
	   4. Because we keep swapping and modifying fat tables from the above
	      three steps, we need to update fat tables by writing the fat buffer
	      back to flash.
	      
	ex: (original)
	   dir/file		clusterNo
	   ---------------------------------
	   \f1.txt		246
	   \f2.txt		247
	   \f3.txt		248
	   \4dos		249
	   \4dos\fat1x.txt	250
	   \4dos\abc		2
	   \4dos\abc\fat1x.txt	3, 4

	ex: (after defragging)
	   dir/file		clusterNo
	   ---------------------------------
	   \f1.txt		2
	   \f2.txt		3
	   \f3.txt		4
	   \4dos		5
	   \4dos\fat1x.txt	6
	   \4dos\abc		7
	   \4dos\abc\fat1x.txt	8, 9
	// method
Input:
Output:
        0: no error is found
       -1: error (see FATError)
**************************************************************/
int FAT_defrag(void)
{
  short i;
  short status;
  short j;
  short fileOpened = 0;
  
  /**** added by chilong 12/10/2001 temporarily ****/
  return -1;
  /**** added by chilong 12/10/2001 temporarily ****/

  // check if fat1x file system is on
  if (InitFAT != TRUE)
  {
	FATErrno = ERROR_FILE_SYSTEM_NOT_INIT;
  	return -1;
  }
  
  sc_waitSemaphore(FATDirSemaphoreID);

  // check if any file is being opened
  for (i = 0; i < MAX_OPEN_FILE; i++)
  {
	if (FATHandleTable[i] != NULL)
	{
		if (FATHandleTable[i]->deviceID == FAT_ID)
		{
			// there are opened files
			// have to update the current block field in the file handle when moving blocks
			fileOpened = 1;
			break;
		}
	}
  }
  
  /**** added by chilong 12/10/2001 ****/
    
  for (i = 0; i < DRIVE_NUM; i++)
  {
  	// defrag from cluster 2
  	defragClusterNo = 2;
  	
  	if ((FATBuf = (unsigned short *) ap_malloc(SECTOR_SIZE * FATSecPerFAT[i])) == NULL)
  	{
  		FATErrno = ERROR_ALLOC_MEM;
  		sc_signalSemaphore(FATDirSemaphoreID);
  		
  		return -1;
  	}
  	
  	// read FAT1
  	if (ATA_READ(i, FATSecPerFAT[i], FAT1Begin[i], FATBuf) == ATA_FAILURE)
  	{
		FATErrno = ERROR_ATA_READ;
		ap_free(FATBuf);
		FAT_free_dirLinkList(&defragDirList);
		
		sc_signalSemaphore(FATDirSemaphoreID);
		return -1;
  	}
  	
  	initDLinkList(&defragDirList);
  	
  	if (FAT_set_defragDirList(i) == -1)
  	{
		ap_free(FATBuf);
		FAT_free_dirLinkList(&defragDirList);
		
		sc_signalSemaphore(FATDirSemaphoreID);
		
  		return -1;
  	}
  	
  	if (FAT_defrag_root(i) == -1)
  	{
		ap_free(FATBuf);
		FAT_free_dirLinkList(&defragDirList);
		
		sc_signalSemaphore(FATDirSemaphoreID);
		
  		return -1;
  	}
  	
  	if (FAT_defrag_subdir(i) == -1)
  	{
		ap_free(FATBuf);
		FAT_free_dirLinkList(&defragDirList);
		
		sc_signalSemaphore(FATDirSemaphoreID);
		
  		return -1;
  	}

	// write FATBuf back into FAT1
	if (ATA_WRITE(i, FATSecPerFAT[i], FAT1Begin[i], FATBuf) == ATA_FAILURE)
	{
		FATErrno = ERROR_ATA_WRITE;
		
		ap_free(FATBuf);
		FAT_free_dirLinkList(&defragDirList);
		
		sc_signalSemaphore(FATDirSemaphoreID);
		return -1;
	}
	
	// write FATBuf back into FAT2
	if (FAT1Begin[i] != FAT2Begin[i])
	{
		// write FATBuf back into FAT2
		if (ATA_WRITE(i, FATSecPerFAT[i], FAT2Begin[i], FATBuf) == ATA_FAILURE)
		{
			FATErrno = ERROR_ATA_WRITE;
		
			ap_free(FATBuf);
			FAT_free_dirLinkList(&defragDirList);
		
			sc_signalSemaphore(FATDirSemaphoreID);
			return -1;
		}
  	}
	
	FAT_free_dirLinkList(&defragDirList);
  }


#ifdef FAT_FAT_CACHE_ON	/* FAT cache is available */
  // update FAT_FAT_CACHE to make data consistent
  // The reason why we only update the cache with DirtySec FALSE
  // is that the caches sectors with DirtySec TRUE will be 
  // flushed later.
  for (i = 0; i < FAT_FAT_CACHE_BLOCK; i++)
  {
  	if (FATFatCache[i].DirtySec == FALSE)
  	{
		for (j = 0; j < WORDS_PER_SECTOR; j++)
		{
        		*(FATFatCache[i].Entry + j) = 
        			*(FATBuf + WORDS_PER_SECTOR * (FATFatCache[i].sec_num-FAT1Begin[FATFatCache[i].drive]) + j);
        	}
        }
  }
#endif

  ap_free(FATBuf);
  FAT_flushAll();
  
  
  sc_signalSemaphore(FATDirSemaphoreID);
  
  return 0;

}

/*************************************************************
Fuction : FAT_set_defragDirList
	Record all the directories in the global variable "defragDirList"
	(from root directory to all its subdirectories sorted in order)
Input:
	drive - drive number
Output:
	        0: no error is found
	       -1: error (see FATError)
**************************************************************/
int FAT_set_defragDirList(short drive)
{
  unsigned long 	i, j;
  unsigned char		*rootSecBuffer, *clusterBuffer;
  int			done = 0;
  unsigned short	clusterNo, currCluster, parentClusterNo;
  struct defrag_dir	*tmpDir, *currentDir;
  struct dLinkList	*pList, *tailNode;
  
  if ((rootSecBuffer = (unsigned char *)ap_malloc(SECTOR_SIZE)) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }

  if ((clusterBuffer = (unsigned char *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	
  	ap_free(rootSecBuffer);
  	return -1;
  }
  
  // search from root directory
  tailNode = &defragDirList;
  
  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)
  	{
  		// the end
  		if (rootSecBuffer[j] == '\0')
  		{
  			done = 1;
  			break;
  		}
  		// delete entries 
  		if (rootSecBuffer[j] == FAT_DELETED_ENTRY)
  		{
  			continue;
  		}

		// if this is a subdir entry, record it in the defragDirList
		if ((*(rootSecBuffer + j + 11) & DA_DIR) == DA_DIR)
		{
			clusterNo = *(rootSecBuffer + j + 27) << 8;
			clusterNo |= *(rootSecBuffer + j + 26);
			
			tmpDir = (struct defrag_dir *) ap_malloc(sizeof(struct defrag_dir));
			if (tmpDir == NULL)
			{
				FATErrno = ERROR_ALLOC_MEM;
					
				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
				return -1;
			}
				
			// we don't record clusterNo because it'll be replayed by defragClusterNo
			tmpDir->startCluster = clusterNo;
			tmpDir->parentCluster = 0;
			tmpDir->block = i;
			tmpDir->entry = j;
				
			if(insertTo(tailNode, (void *)tmpDir) == FAIL)
			{
				FATErrno = ERROR_OPERATING_SYSTEM_ERROR;
	 				
	 			ap_free(tmpDir);
  				ap_free(rootSecBuffer);
				ap_free(clusterBuffer);
  				
  				return -1;
			}
			tailNode = tailNode->back;
		}

  	}
  	if (done == 1)
  		break;
  }
  
  // we don't need this buffer anymore
  ap_free(rootSecBuffer);
  
  // search sub-directories
  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;
	#ifdef FAT_LFN
  			else if ((*(clusterBuffer + j + 11) & DA_VFAT) == DA_VFAT)
  				continue;
	#endif		
	
  			if(*(clusterBuffer + j) == '.' && *(clusterBuffer + j + 1) == '.')
  			{
				clusterNo = *(clusterBuffer + j + 27) << 8;
				clusterNo |= *(clusterBuffer + j + 26);
				
				parentClusterNo = currCluster;
  				continue;
  			}
  			
  				
			// if this is a subdir entry, record it in the defragDirList
			if (*(clusterBuffer + j) != '.' && (*(clusterBuffer + j + 11) & DA_DIR) == DA_DIR)
			{
				clusterNo = *(clusterBuffer + j + 27) << 8;
				clusterNo |= *(clusterBuffer + j + 26);
			
				tmpDir = (struct defrag_dir *) ap_malloc(sizeof(struct defrag_dir));
				if (tmpDir == NULL)
				{
					FATErrno = ERROR_ALLOC_MEM;
					
					ap_free(clusterBuffer);
					return -1;
				}
				
				tmpDir->startCluster = clusterNo;
				tmpDir->parentCluster = parentClusterNo;
				tmpDir->block = currCluster;
				tmpDir->entry = j;
				
				if(insertTo(tailNode, (void *)tmpDir) == FAIL)
				{
					FATErrno = ERROR_OPERATING_SYSTEM_ERROR;
	 				
					ap_free(tmpDir);
					ap_free(clusterBuffer);
  				
  					return -1;
				}
				tailNode = tailNode->back;
			}
  		}
		if (done == 1)
			break;
  		
		currCluster = read_fat_cluster_from_fatBuffer(drive, currCluster);
		
  		if (currCluster >= FATEndOfChain[FATType[drive]])
  		{
  			break;
  		}
  	}
	pList = pList->back;
  }

  return 0;    
}

/*************************************************************
Fuction : FAT_defrag_root
	defrag root directory
Input:
	drive - drive number
Output:
	        0: no error is found
	       -1: error (see FATError)
**************************************************************/
int FAT_defrag_root(short drive)
{
  unsigned long 	i, j, k;
  unsigned char		*oldRootSecBuffer, *newRootSecBuffer, *clusterBuffer;
  int			done = 0;
  unsigned long		updateRootSec;
  unsigned short	clusterNo;
  int			dirty;
  
  if ((oldRootSecBuffer = (unsigned char *)ap_malloc(SECTOR_SIZE)) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }
  
  if ((newRootSecBuffer = (unsigned char *)ap_malloc(SECTOR_SIZE)) == NULL)
  {
  	ap_free(oldRootSecBuffer);
  	FATErrno = ERROR_ALLOC_MEM;
  	return -1;
  }
  myMemSet(newRootSecBuffer, 0, SECTOR_SIZE);

  if ((clusterBuffer = (unsigned char *)ap_malloc(FATBytesPerCluster[drive])) == NULL)
  {
  	FATErrno = ERROR_ALLOC_MEM;
  	
  	ap_free(oldRootSecBuffer);
  	ap_free(newRootSecBuffer);
  	return -1;
  }
  
  // 1. rearrange root entries, not letting any unused entries be placed
  // 	between two used entries
  k = 0;
  for (i = updateRootSec = 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(newRootSecBuffer);
  		ap_free(clusterBuffer);
  		return -1;
  	}
  	
  	for (j = 0; j < SECTOR_SIZE; j += FAT_DIR_ENTRY_SIZE)
  	{
  		// the end
  		if (oldRootSecBuffer[j] == '\0')
  		{
  			if (FAT_update_root_sector(drive, updateRootSec, (unsigned short *)newRootSecBuffer) != ATA_OK)
  			{
  				ap_free(oldRootSecBuffer);
  				ap_free(newRootSecBuffer);
		  		ap_free(clusterBuffer);
  				return -1;
  			}
  			k = 0;
  			updateRootSec++;
  			myMemSet(newRootSecBuffer, 0, SECTOR_SIZE);
  			
  			done = 1;
  			break;
  		}
  		// delete entries 
  		if (oldRootSecBuffer[j] == FAT_DELETED_ENTRY)
  			continue;
  			
  		// copy the entry from the old sector to the new sector
  		myMemCpy(newRootSecBuffer + k, oldRootSecBuffer + j, FAT_DIR_ENTRY_SIZE);
  		k += FAT_DIR_ENTRY_SIZE;
  		
  		if (k > SECTOR_SIZE)
  		{
  			if (FAT_update_root_sector(drive, updateRootSec, (unsigned short *)newRootSecBuffer) != ATA_OK)
  			{
  				ap_free(oldRootSecBuffer);
  				ap_free(newRootSecBuffer);
		  		ap_free(clusterBuffer);
  				return -1;
  			}
  			
  			k = 0;
  			updateRootSec++;
  			myMemSet(newRootSecBuffer, 0, SECTOR_SIZE);
  		}
  	}
  	
  	if (done == 1)

⌨️ 快捷键说明

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