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

📄 fat.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
📖 第 1 页 / 共 2 页
字号:
            nextcluster = *((euint16*)buf + offset);
            break;
        case FAT32:
            offset=cluster_addr%128;
            nextcluster = *((euint32*)buf + offset);
            break;
    }
    return(nextcluster);
}
/*****************************************************************************/

/* ****************************************************************************
 * void fat_setNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr,euint8* buf)
 * Description: This function fills in a fat entry. The entry is cluster_addr and the
 * data entered is next_cluster_addr. This function is also given a *buf, so it does
 * not write the data itself, except in the case of FAT 12 cross sector data, where
 * the second sector is handled by this function.
 * Return value:
*/
void fat_setNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr,euint8* buf)
{
    euint16 offset;
    euint8 *buf2;
        
    switch(fs->type)
    {
        case FAT12:
            offset = ((cluster_addr%1024)*3/2)%512;
            if(offset == 511){
                if(cluster_addr%2==0){
                    buf[offset]=next_cluster_addr&0xFF;
                }else{
                    buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0);
                }
                buf2=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cluster_addr)+1,IOM_MODE_READWRITE);
                if(cluster_addr%2==0){
                    buf2[0]=(buf2[0]&0xF0)+((next_cluster_addr>>8)&0xF);
                }else{
                    buf2[0]=(next_cluster_addr>>4)&0xFF;
                }
                part_relSect(fs->part,buf2);
            }else{
                if(cluster_addr%2==0){
                    buf[offset]=next_cluster_addr&0xFF;
                    buf[offset+1]=(buf[offset+1]&0xF0)+((next_cluster_addr>>8)&0xF);
                }else{
                    buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0);
                    buf[offset+1]=(next_cluster_addr>>4)&0xFF;
                }
            }
            break;
        case FAT16:
            offset=cluster_addr%256;
            *((euint16*)buf+offset)=next_cluster_addr;
            break;
        case FAT32:
            offset=cluster_addr%128;
            *((euint32*)buf+offset)=next_cluster_addr;
            break;
    }
}
/*****************************************************************************/

/* ****************************************************************************
 * esint16 fat_getNextClusterChain(FileSystem *fs, ClusterChain *Cache)
 * Description: This function is to advance the clusterchain of a Cache.
 * First, the function verifies if the Cache is valid. It could correct it if it
 * is not, but this is not done at the time. If the cachen is valid, the next step is
 * to see what the next cluster is, if this is the End of Clustermark, the cache is
 * updated to know the lastcluster but will remain untouched otherwise. -1 is returned.
 * If there are more clusters the function scans the rest of the chain until the next
 * cluster is no longer lineair, or until it has run out of fat data (only 1 sector) is
 * examined, namely the one fetched to check for EoC.
 * With lineair is meant that logical cluster n+1 should be 1 more than logical cluster n
 * at the disc level.
 * Return value: 0 on success, or -1 when EoC.
*/
esint16 fat_getNextClusterChain(FileSystem *fs, ClusterChain *Cache)
{
    euint32 sect,lr,nlr,dc;
    esint16 lin=0;
    euint8 *buf;

    if(Cache->DiscCluster==0)
    {
        return(-1);
    }

    sect=fat_getSectorAddressFatEntry(fs,Cache->DiscCluster);
    buf=part_getSect(fs->part,sect,IOM_MODE_READONLY);
    dc=fat_getNextClusterAddressWBuf(fs,Cache->DiscCluster,buf);
    if(fat_isEocMarker(fs,dc))
    {
        Cache->LastCluster=Cache->DiscCluster;
        part_relSect(fs->part,buf);
        return(-1);
    }
    
    Cache->DiscCluster=dc;
    Cache->LogicCluster++;
        
    lr=Cache->DiscCluster-1;
    nlr=lr+1;
    
    while(nlr-1==lr && fat_getSectorAddressFatEntry(fs,nlr)==sect)
    {
        lr=nlr;
        nlr=fat_getNextClusterAddressWBuf(fs,lr,buf);
        lin++;  
    }
    
    Cache->Linear=lin-1<0?0:lin-1;
    
    part_relSect(fs->part,buf);
    return(0);
}
/*****************************************************************************/


/* ****************************************************************************
 * esint16 fat_LogicToDiscCluster(FileSystem *fs, ClusterChain *Cache,euint32 logiccluster)
 * Description: This function is used to follow clusterchains. When called it will convert
 * a logical cluster, to a disc cluster, using a Cache object. All it does is call
 * getNextClusterChain in the proper manner, and rewind clusterchains if required.
 * It is NOT recommended to go backwards in clusterchains, since this will require
 * scanning the entire chain every time.
 * Return value: 0 on success and -1 on failure (meaning out of bounds).
*/
esint16 fat_LogicToDiscCluster(FileSystem *fs, ClusterChain *Cache,euint32 logiccluster)
{
    if(logiccluster<Cache->LogicCluster || Cache->DiscCluster==0){
        Cache->LogicCluster=0;
        Cache->DiscCluster=Cache->FirstCluster;
        Cache->Linear=0;
    }
    
    if(Cache->LogicCluster==logiccluster){
        return(0);
    }
    
    while(Cache->LogicCluster!=logiccluster)
    {
        if(Cache->Linear!=0)
        {
            Cache->Linear--;
            Cache->LogicCluster++;
            Cache->DiscCluster++;
        }
        else
        {
            if((fat_getNextClusterChain(fs,Cache))!=0){
                return(-1);
            }
        }
    }
    return(0);
}
/*****************************************************************************/

/* ****************************************************************************
 * eint16 fat_allocClusterChain(FileSystem *fs,ClusterChain *Cache,euint32 num_clusters)
 * Description: This function extends a clusterchain by num_clusters. It returns the
 * number of clusters it *failed* to allocate.
 * Return value: 0 on success, all other values are the number of clusters it could
 * not allocate.
*/
eint16 fat_allocClusterChain(FileSystem *fs,ClusterChain *Cache,euint32 num_clusters)
{
    euint32 cc,ncl=num_clusters,lc;
    euint8 *bufa=0,*bufb=0;
    euint8  overflow=0;

    if(Cache->FirstCluster<=1)return(num_clusters);
    
    lc=fs_getLastCluster(fs,Cache);
    cc=lc;
    
    while(ncl > 0){
        cc++;
        if(cc>=fs->DataClusterCount+1){
            if(overflow){
                bufa=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,lc),IOM_MODE_READWRITE);
                fat_setNextClusterAddressWBuf(fs,lc,fat_giveEocMarker(fs),bufa);
                Cache->LastCluster=lc;
                part_relSect(fs->part,bufa);
                fs->FreeClusterCount-=num_clusters-ncl;
                return(num_clusters-ncl);
            }
            cc=2;
            overflow++;
        }
        bufa=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cc),IOM_MODE_READONLY);
        if(fat_getNextClusterAddressWBuf(fs,cc,bufa)==0){
            bufb=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,lc),IOM_MODE_READWRITE);
            fat_setNextClusterAddressWBuf(fs,lc,cc,bufb);
            part_relSect(fs->part,bufb);
            ncl--;
            lc=cc;
        }
        part_relSect(fs->part,bufa);
        if(ncl==0){
            bufa=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,lc),IOM_MODE_READWRITE);
            fat_setNextClusterAddressWBuf(fs,lc,fat_giveEocMarker(fs),bufa);
            Cache->LastCluster=lc;
            part_relSect(fs->part,bufa);
        }
    }
    if(Cache->ClusterCount)Cache->ClusterCount+=num_clusters;
    return(0);
}

/* ****************************************************************************
 * eint16 fat_unlinkClusterChain(FileSystem *fs,ClusterChain *Cache)
 * Description: This function removes a clusterchain. Starting at FirstCluster
 * it follows the chain until the end, resetting all values to 0.
 * Return value: 0 on success.
*/
eint16 fat_unlinkClusterChain(FileSystem *fs,ClusterChain *Cache)
{
    euint32 c,tbd=0;
    
    Cache->LogicCluster=0;
    Cache->DiscCluster=Cache->FirstCluster;
    
    c=0;
    
    while(!fat_LogicToDiscCluster(fs,Cache,c++)){
        if(tbd!=0){
            fat_setNextClusterAddress(fs,tbd,0);
        }
        tbd=Cache->DiscCluster;
    }
    fat_setNextClusterAddress(fs,Cache->DiscCluster,0);
    fs->FreeClusterCount+=c;    
    return(0);
}

euint32 fat_countClustersInChain(FileSystem *fs,euint32 firstcluster)
{
    ClusterChain cache;
    euint32 c=0;
    
    if(firstcluster<=1)return(0);
    
    cache.DiscCluster = cache.LogicCluster = cache.LastCluster = cache.Linear = 0;
    cache.FirstCluster = firstcluster;
    
    while(!(fat_LogicToDiscCluster(fs,&cache,c++)));
    
    return(c-1);
}

euint32 fat_DiscToLogicCluster(FileSystem *fs,euint32 firstcluster,euint32 disccluster)
{
    ClusterChain cache;
    euint32 c=0,r=0;
    
    cache.DiscCluster = cache.LogicCluster = cache.LastCluster = cache.Linear = 0;
    cache.FirstCluster = firstcluster;
    
    while(!(fat_LogicToDiscCluster(fs,&cache,c++)) && !r){
        if(cache.DiscCluster == disccluster){
            r = cache.LogicCluster;
        }
    }
    return(r);
}

euint32 fat_countFreeClusters(FileSystem *fs)
{
    euint32 c=2,fc=0;
    
    while(c<=fs->DataClusterCount+1){
        if(fat_getNextClusterAddress(fs,c,0)==0)fc++;
        c++;
    }
    return(fc);
}

⌨️ 快捷键说明

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