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