📄 fdefrag.c
字号:
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 + -