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

📄 tmfat32.c

📁 PNX1500上Fat32文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -