📄 fat.c
字号:
part_relSect(fs->part,buf2); }else{ lb = buf[offset + 1]; } if(cluster_addr%2==0){ nextcluster = ( ((lb&0x0F)<<8) + (hb) ); }else{ nextcluster = ( (lb<<4) + (hb>>4) ); } break; case FAT16: offset=cluster_addr%256; 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); 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); } } 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); 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -