📄 tmfat32.c
字号:
if (p->fatCity)
{
offset = entry;
}
else
{
// Determine the sector number for this entry and look
// for it in the cache. The locked sectors in the FAT
// are ordered so we don't have so search sequentially
// there.
if (sector < p->fatLockSectors + fatBase)
{
offset = ((sector - fatBase) * entries_per_sector) + entry % entries_per_sector;
goto done;
}
else
{
for (i = p->fatLockSectors; i < p->fatNumSectors; i++)
{
if (p->fatSector[i] == sector)
{
offset = (i * entries_per_sector) + entry % entries_per_sector;
index = i;
goto done;
}
}
}
// Sector is not in the cache
status = UTIL_fill_cache(FAT_CACHE, 0, sector);
if (status != TM_OK)
{
TMFAT_DEBUG2("filling FAT cache for sector %d failed 0x%X\n",
sector, status);
return 1;
}
// The data was placed in the previously available slot
if (p->fatCacheNext == p->fatLockSectors)
{
i = p->fatNumSectors - 1;
}
else
{
i = p->fatCacheNext - 1;
}
offset = (i * entries_per_sector) + entry % entries_per_sector;
}
done:
if (op == SET_FAT_ENTRY)
{
if (p->fsType == tmFat32_FAT32)
{
if (p->fatCache[offset] != value)
{
p->fatSectorDirty[index] = True;
p->fatCache[offset] = value;
}
}
else if (p->fsType == tmFat32_FAT16)
{
pfat = (UInt16 *) p->fatCache;
temp = value;
if (pfat[offset] != temp)
{
p->fatSectorDirty[index] = True;
pfat[offset] = temp;
}
}
else
{
UInt32 old;
offset = entry + (entry / 2); // Byte offset into the FAT
pfat = (UInt16 *) ((UInt32) &p->fatCache[0] + offset);
temp = *pfat;
if (entry & 1)
old = temp >> 4; // Cluster number is odd
else
old = temp & 0x0FFF; // Cluster number is even
if (old != value) // Set it only if it changed
{
if (entry & 1)
*pfat = (*pfat & 0x000F) | (value << 4);
else
*pfat = (*pfat & 0xF000) | (value & 0x0FFF);
// A FAT12 entry may span two sectors
index = (fatBase + offset / p->dev->Info->bytesPerSector) - fatBase;
p->fatSectorDirty[index] = True;
index = (fatBase + (offset + 1) / p->dev->Info->bytesPerSector) - fatBase;
p->fatSectorDirty[index] = True;
}
}
}
else
{
if (p->fsType == tmFat32_FAT32)
{
*result = p->fatCache[offset];
}
else if (p->fsType == tmFat32_FAT16)
{
pfat = (UInt16 *) p->fatCache;
temp = pfat[offset];
*result = temp;
}
else
{
offset = entry + (entry / 2); // Byte offset into the FAT
pfat = (UInt16 *) ((UInt32) &p->fatCache[0] + offset);
temp = *pfat;
if (entry & 1)
*result = temp >> 4; // Cluster number is odd
else
*result = temp & 0x0FFF; // Cluster number is even
}
}
return 0;
}
// Get address of a cluster in the data cache. Return Null if there
// is an error.
static UInt8 *UTIL_get_cluster_address(UInt32 cluster)
{
tmErrorCode_t status = TM_OK;
ptmFat32_FS_t p = GFS;
UInt32 i;
UInt32 index; // From beginning of cache
TMFAT_ASSERT (p != Null);
// Check parameter values
if (p->fsType == tmFat32_FAT32)
{
if (cluster < p->rootDirCluster || cluster > p->maxCluster)
{
TMFAT_DEBUG3("cluster %d is out of range (%d,%d)\n",
cluster, p->rootDirCluster, p->maxCluster);
return Null;
}
}
else
{
if (cluster > p->maxCluster)
{
TMFAT_DEBUG3("cluster %d is out of range (%d,%d)\n",
cluster, p->rootDirCluster, p->maxCluster);
return Null;
}
}
if (p->fsType != tmFat32_FAT32 && cluster == 0)
{
return p->rootDirCache;
}
// The locked clusters are always in order so we don't
// have to search sequentially there.
if (cluster < p->dataLockClusters + p->rootDirCluster)
{
index = cluster - p->rootDirCluster;
goto done;
}
else
{
for (i = p->dataLockClusters; i < p->dataNumClusters; i++)
{
if (cluster == p->dataCluster[i])
{
index = i;
goto done;
}
}
}
// Cluster is not in the cache
status = UTIL_fill_cache(DATA_CACHE, cluster, 0);
if (status != TM_OK)
{
TMFAT_DEBUG3("filling DATA cache for cluster %d failed 0x%X, maxCluster=%d\n",
cluster, status, p->maxCluster);
return Null;
}
// The data was placed in the previously available slot
if (p->dataCacheNext == p->dataLockClusters)
index = p->dataNumClusters - 1;
else
index = p->dataCacheNext - 1;
done:
return (p->dataCache + index * p->bytesPerCluster);
}
// Allocate a new cluster. Return 0 on success. Return 1 if the disk
// is full. Return 2 on error (usually disk I/O error). On success
// set the allocated cluster number in *clust. Clear the cluster
// if 'clear' is True. Clusters for directories must be cleared,
// clusters for files do not. If 'chain' is nonzero then chain the
// new cluster to the 'chain' cluster.
static int UTIL_allocate_cluster(UInt32 *clust, UInt32 chain, Bool clear)
{
UInt32 temp;
ptmFat32_FS_t p = GFS;
UInt32 cluster = 0;
Bool lastCluster;
Bool badCluster;
if (p->freeClusters == 0)
{
SET_ERRNO(ENOSPC);
return 1;
}
// If we're chaining the 'chain' cluster must already be allocated.
// It's possible that it's already chained so we don't have to
// allocate a new cluster.
if (chain)
{
lastCluster = False;
badCluster = False;
if (UTIL_fat_content(GET_FAT_ENTRY, chain, 0, &temp))
return 2;
if (p->fsType == tmFat32_FAT32)
{
temp = temp & FAT32_CLUSTER_MASK;
if (temp >= FAT32_EOC)
lastCluster = True;
if (temp == FAT32_BAD_CLUSTER)
badCluster = True;
}
else if (p->fsType == tmFat32_FAT16)
{
temp = temp & FAT16_CLUSTER_MASK;
if (temp >= FAT16_EOC)
lastCluster = True;
if (temp == FAT16_BAD_CLUSTER)
badCluster = True;
}
else
{
temp = temp & FAT12_CLUSTER_MASK;
if (temp >= FAT12_EOC)
lastCluster = True;
if (temp == FAT12_BAD_CLUSTER)
badCluster = True;
}
if ((temp == FAT_FREE_CLUSTER) || badCluster)
{
return 2;
}
if (lastCluster == False)
{
cluster = temp;
goto check_clear;
}
}
// We have to allocate a new one
while (p->freeClusters > 0)
{
Bool freeCluster;
if (UTIL_fat_content(GET_FAT_ENTRY, p->nextFreeCluster, 0, &temp))
return 2;
freeCluster = False;
if (p->fsType == tmFat32_FAT32)
{
if ((temp & FAT32_CLUSTER_MASK) == FAT_FREE_CLUSTER)
freeCluster = True;
}
else if (p->fsType == tmFat32_FAT16)
{
if ((temp & FAT16_CLUSTER_MASK) == FAT_FREE_CLUSTER)
freeCluster = True;
}
else
{
if ((temp & FAT12_CLUSTER_MASK) == FAT_FREE_CLUSTER)
freeCluster = True;
}
if (freeCluster)
{
cluster = p->nextFreeCluster;
p->freeClusters--;
p->nextFreeCluster++;
if (p->nextFreeCluster > p->maxCluster)
p->nextFreeCluster = p->rootDirCluster;
break;
}
p->nextFreeCluster++;
if (p->nextFreeCluster > p->maxCluster)
p->nextFreeCluster = p->rootDirCluster;
}
if (chain)
{
if (UTIL_fat_content(GET_FAT_ENTRY, chain, 0, &temp))
return 2;
if (p->fsType == tmFat32_FAT32)
temp = (temp & ~FAT32_CLUSTER_MASK) | cluster;
else if (p->fsType == tmFat32_FAT16)
temp = (temp & ~FAT16_CLUSTER_MASK) | cluster;
else
temp = (temp & ~FAT12_CLUSTER_MASK) | cluster;
if (UTIL_fat_content(SET_FAT_ENTRY, chain, temp, Null))
return 2;
}
// Terminate the new cluster
if (UTIL_fat_content(GET_FAT_ENTRY, cluster, 0, &temp))
return 2;
if (p->fsType == tmFat32_FAT32)
temp = (temp & ~FAT32_CLUSTER_MASK) | FAT32_CLUSTER_MASK;
else if (p->fsType == tmFat32_FAT16)
temp = (temp & ~FAT16_CLUSTER_MASK) | FAT16_CLUSTER_MASK;
else
temp = (temp & ~FAT12_CLUSTER_MASK) | FAT12_CLUSTER_MASK;
if (UTIL_fat_content(SET_FAT_ENTRY, cluster, temp, Null))
return 2;
check_clear:
if (clear)
{
UInt8 *dst;
UInt32 i;
if (!(dst = UTIL_get_cluster_address(cluster)))
{
TMFAT_DEBUG1("UTIL_allocate_cluster: UTIL_get_cluster_address(%d) failed.\n", cluster);
return 2;
}
memset(dst, 0, p->bytesPerCluster);
// Mark it as dirty
for (i = 0; i < p->dataNumClusters; i++)
{
if (cluster == p->dataCluster[i])
{
p->dataClusterDirty[i] = True;
break;
}
}
}
*clust = cluster;
return 0;
}
// Delete resources allocated to a file. This is for both directories and
// regular files. Free allocated clusters and make directory entries free
// in the parent directory. Return 0 on success, -1 on failure.
// The flags indicate what is to be deleted.
static int UTIL_delete_file(ptmFat32_File_t f, int flags)
{
int rval = -1;
ptmFat32_FS_t p = GFS;
UInt32 cluster;
UInt32 offset;
UInt32 next_cluster;
int nparts;
UInt8 mydir[DIR_ENTRY_SIZE];
Bool lastCluster;
TMFAT_ASSERT (f != Null);
if (flags & DELETE_FILE_CONTENT)
{
// Free its clusters. If the starting cluster is zero it's an empty
// file so don't spend time chasing its cluster chain.
cluster = f->base_cluster;
if (p->fsType == tmFat32_FAT32)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -