ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ff_fat.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002  *  FullFAT - High Performance, Thread-Safe Embedded FAT File-System         *
00003  *  Copyright (C) 2009  James Walmsley (james@worm.me.uk)                    *
00004  *                                                                           *
00005  *  This program is free software: you can redistribute it and/or modify     *
00006  *  it under the terms of the GNU General Public License as published by     *
00007  *  the Free Software Foundation, either version 3 of the License, or        *
00008  *  (at your option) any later version.                                      *
00009  *                                                                           *
00010  *  This program is distributed in the hope that it will be useful,          *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00013  *  GNU General Public License for more details.                             *
00014  *                                                                           *
00015  *  You should have received a copy of the GNU General Public License        *
00016  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.    *
00017  *                                                                           *
00018  *  IMPORTANT NOTICE:                                                        *
00019  *  =================                                                        *
00020  *  Alternative Licensing is available directly from the Copyright holder,   *
00021  *  (James Walmsley). For more information consult LICENSING.TXT to obtain   *
00022  *  a Commercial license.                                                    *
00023  *                                                                           *
00024  *  See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT.       *
00025  *                                                                           *
00026  *  Removing the above notice is illegal and will invalidate this license.   *
00027  *****************************************************************************
00028  *  See http://worm.me.uk/fullfat for more information.                      *
00029  *  Or  http://fullfat.googlecode.com/ for latest releases and the wiki.     *
00030  *****************************************************************************/
00031 
00043 #include "ff_fat.h"
00044 #include "ff_config.h"
00045 #include <string.h>
00046 
00047 void FF_lockFAT(FF_IOMAN *pIoman) {
00048     FF_PendSemaphore(pIoman->pSemaphore);   // Use Semaphore to protect FAT modifications.
00049     {
00050         while((pIoman->Locks & FF_FAT_LOCK)) {
00051             FF_ReleaseSemaphore(pIoman->pSemaphore);
00052             FF_Yield();                     // Keep Releasing and Yielding until we have the Fat protector.
00053             FF_PendSemaphore(pIoman->pSemaphore);
00054         }
00055         pIoman->Locks |= FF_FAT_LOCK;
00056     }
00057     FF_ReleaseSemaphore(pIoman->pSemaphore);
00058 }
00059 
00060 void FF_unlockFAT(FF_IOMAN *pIoman) {
00061     FF_PendSemaphore(pIoman->pSemaphore);
00062     {
00063         pIoman->Locks &= ~FF_FAT_LOCK;
00064     }
00065     FF_ReleaseSemaphore(pIoman->pSemaphore);
00066 }
00067 
00071 FF_T_UINT32 FF_getRealLBA(FF_IOMAN *pIoman, FF_T_UINT32 LBA) {
00072     return LBA * pIoman->pPartition->BlkFactor;
00073 }
00074 
00078 FF_T_UINT32 FF_Cluster2LBA(FF_IOMAN *pIoman, FF_T_UINT32 Cluster) {
00079     FF_T_UINT32 lba = 0;
00080     FF_PARTITION *pPart;
00081     if(pIoman) {
00082         pPart = pIoman->pPartition;
00083 
00084         if(Cluster > 1) {
00085             lba = ((Cluster - 2) * pPart->SectorsPerCluster) + pPart->FirstDataSector;
00086         } else {
00087             lba = pPart->ClusterBeginLBA;
00088         }
00089     }
00090     return lba;
00091 }
00092 
00096 FF_T_UINT32 FF_LBA2Cluster(FF_IOMAN *pIoman, FF_T_UINT32 Address) {
00097     FF_T_UINT32 cluster = 0;
00098     FF_PARTITION *pPart;
00099     if(pIoman) {
00100         pPart = pIoman->pPartition;
00101         if(pPart->Type == FF_T_FAT32) {
00102             cluster = ((Address - pPart->ClusterBeginLBA) / pPart->SectorsPerCluster) + 2;
00103         } else {
00104             cluster = ((Address - pPart->ClusterBeginLBA) / pPart->SectorsPerCluster);
00105         }
00106     }
00107     return cluster;
00108 }
00109 
00113 FF_T_UINT32 FF_getFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster, FF_ERROR *pError) {
00114 
00115     FF_BUFFER   *pBuffer;
00116     FF_T_UINT32 FatOffset;
00117     FF_T_UINT32 FatSector;
00118     FF_T_UINT32 FatSectorEntry;
00119     FF_T_UINT32 FatEntry;
00120     FF_T_UINT8  LBAadjust;
00121     FF_T_UINT16 relClusterEntry;
00122 
00123 #ifdef FF_FAT12_SUPPORT
00124     FF_T_UINT8  F12short[2];        // For FAT12 FAT Table Across sector boundary traversal.
00125 #endif
00126     
00127     if(pIoman->pPartition->Type == FF_T_FAT32) {
00128         FatOffset = nCluster * 4;
00129     } else if(pIoman->pPartition->Type == FF_T_FAT16) {
00130         FatOffset = nCluster * 2;
00131     }else {
00132         FatOffset = nCluster + (nCluster / 2);
00133     }
00134     
00135     FatSector       = pIoman->pPartition->FatBeginLBA + (FatOffset / pIoman->pPartition->BlkSize);
00136     FatSectorEntry  = FatOffset % pIoman->pPartition->BlkSize;
00137     
00138     LBAadjust       = (FF_T_UINT8)  (FatSectorEntry / pIoman->BlkSize);
00139     relClusterEntry = (FF_T_UINT32) (FatSectorEntry % pIoman->BlkSize);
00140     
00141     FatSector = FF_getRealLBA(pIoman, FatSector);
00142     
00143 #ifdef FF_FAT12_SUPPORT
00144     if(pIoman->pPartition->Type == FF_T_FAT12) {
00145         if(relClusterEntry == (FF_T_UINT32)(pIoman->BlkSize - 1)) {
00146             // Fat Entry SPANS a Sector!
00147             // First Buffer get the last Byte in buffer (first byte of our address)!
00148             pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ);
00149             {
00150                 if(!pBuffer) {
00151                     *pError = FF_ERR_DEVICE_DRIVER_FAILED;
00152                     return 0;
00153                 }
00154                 F12short[0] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1));             
00155             }
00156             FF_ReleaseBuffer(pIoman, pBuffer);
00157             // Second Buffer get the first Byte in buffer (second byte of out address)!
00158             pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ);
00159             {
00160                 if(!pBuffer) {
00161                     *pError = FF_ERR_DEVICE_DRIVER_FAILED;
00162                     return 0;
00163                 }
00164                 F12short[1] = FF_getChar(pBuffer->pBuffer, 0);              
00165             }
00166             FF_ReleaseBuffer(pIoman, pBuffer);
00167             
00168             FatEntry = (FF_T_UINT32) FF_getShort((FF_T_UINT8*)&F12short, 0);    // Guarantee correct Endianess!
00169 
00170             if(nCluster & 0x0001) {
00171                 FatEntry = FatEntry >> 4;
00172             } 
00173             FatEntry &= 0x0FFF;
00174             return (FF_T_SINT32) FatEntry;
00175         }
00176     }
00177 #endif
00178     pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ);
00179     {
00180         if(!pBuffer) {
00181             *pError = FF_ERR_DEVICE_DRIVER_FAILED;
00182             return 0;
00183         }
00184         
00185         switch(pIoman->pPartition->Type) {
00186             case FF_T_FAT32:
00187                 FatEntry = FF_getLong(pBuffer->pBuffer, relClusterEntry);
00188                 FatEntry &= 0x0fffffff; // Clear the top 4 bits.
00189                 break;
00190 
00191             case FF_T_FAT16:
00192                 FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, relClusterEntry);
00193                 break;
00194 
00195 #ifdef FF_FAT12_SUPPORT
00196             case FF_T_FAT12:
00197                 FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, relClusterEntry);
00198                 if(nCluster & 0x0001) {
00199                     FatEntry = FatEntry >> 4;
00200                 } 
00201                 FatEntry &= 0x0FFF;
00202                 break;
00203 #endif
00204             default:
00205                 FatEntry = 0;
00206                 break;
00207         }
00208     }
00209     FF_ReleaseBuffer(pIoman, pBuffer);
00210 
00211     return (FF_T_SINT32) FatEntry;
00212 }
00213 
00214 FF_ERROR FF_ClearCluster(FF_IOMAN *pIoman, FF_T_UINT32 nCluster) {
00215     FF_BUFFER *pBuffer;
00216     FF_T_UINT16 i;
00217     FF_T_UINT32 BaseLBA;
00218 
00219     BaseLBA = FF_Cluster2LBA(pIoman, nCluster);
00220     BaseLBA = FF_getRealLBA(pIoman, BaseLBA);
00221 
00222     for(i = 0; i < pIoman->pPartition->SectorsPerCluster; i++) {
00223         pBuffer = FF_GetBuffer(pIoman, BaseLBA++, FF_MODE_WRITE);
00224         {
00225             if(!pBuffer) {
00226                 return FF_ERR_DEVICE_DRIVER_FAILED;
00227             }
00228             memset(pBuffer->pBuffer, 0x00, 512);
00229         }
00230         FF_ReleaseBuffer(pIoman, pBuffer);
00231     }
00232 
00233     return FF_ERR_NONE;
00234 }
00235 
00247 FF_T_UINT32 FF_TraverseFAT(FF_IOMAN *pIoman, FF_T_UINT32 Start, FF_T_UINT32 Count, FF_ERROR *pError) {
00248     
00249     FF_T_UINT32 i;
00250     FF_T_UINT32 fatEntry = Start, currentCluster = Start;
00251 
00252     *pError = FF_ERR_NONE;
00253 
00254     for(i = 0; i < Count; i++) {
00255         fatEntry = FF_getFatEntry(pIoman, currentCluster, pError);
00256         if(*pError) {
00257             return 0;
00258         }
00259 
00260         if(FF_isEndOfChain(pIoman, fatEntry)) {
00261             return currentCluster;
00262         } else {
00263             currentCluster = fatEntry;
00264         }   
00265     }
00266     
00267     return fatEntry;
00268 }
00269 
00270 FF_T_UINT32 FF_FindEndOfChain(FF_IOMAN *pIoman, FF_T_UINT32 Start, FF_ERROR *pError) {
00271 
00272     FF_T_UINT32 fatEntry = Start, currentCluster = Start;
00273     *pError = FF_ERR_NONE;
00274 
00275     while(!FF_isEndOfChain(pIoman, fatEntry)) {
00276         fatEntry = FF_getFatEntry(pIoman, currentCluster, pError);
00277         if(*pError) {
00278             return 0;
00279         }
00280 
00281         if(FF_isEndOfChain(pIoman, fatEntry)) {
00282             return currentCluster;
00283         } else {
00284             currentCluster = fatEntry;
00285         }   
00286     }
00287     
00288     return fatEntry;
00289 }
00290 
00291 
00302 FF_T_BOOL FF_isEndOfChain(FF_IOMAN *pIoman, FF_T_UINT32 fatEntry) {
00303     FF_T_BOOL result = FF_FALSE;
00304     if(pIoman->pPartition->Type == FF_T_FAT32) {
00305         if((fatEntry & 0x0fffffff) >= 0x0ffffff8) {
00306             result = FF_TRUE;
00307         }
00308     } else if(pIoman->pPartition->Type == FF_T_FAT16) {
00309         if(fatEntry >= 0x0000fff8) {
00310             result = FF_TRUE;
00311         }
00312     } else {
00313         if(fatEntry >= 0x00000ff8) {
00314             result = FF_TRUE;
00315         }   
00316     }
00317     if(fatEntry == 0x00000000) {
00318         result = FF_TRUE;   //Perhaps trying to read a deleted file!
00319     }
00320     return result;
00321 }
00322 
00323 
00332 FF_ERROR FF_putFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster, FF_T_UINT32 Value) {
00333 
00334     FF_BUFFER   *pBuffer;
00335     FF_T_UINT32 FatOffset;
00336     FF_T_UINT32 FatSector;
00337     FF_T_UINT32 FatSectorEntry;
00338     FF_T_UINT32 FatEntry;
00339     FF_T_UINT8  LBAadjust;
00340     FF_T_UINT32 relClusterEntry;
00341 #ifdef FF_FAT12_SUPPORT 
00342     FF_T_UINT8  F12short[2];        // For FAT12 FAT Table Across sector boundary traversal.
00343 #endif
00344     
00345     if(pIoman->pPartition->Type == FF_T_FAT32) {
00346         FatOffset = nCluster * 4;
00347     } else if(pIoman->pPartition->Type == FF_T_FAT16) {
00348         FatOffset = nCluster * 2;
00349     }else {
00350         FatOffset = nCluster + (nCluster / 2);
00351     }
00352     
00353     FatSector = pIoman->pPartition->FatBeginLBA + (FatOffset / pIoman->pPartition->BlkSize);
00354     FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
00355     
00356     LBAadjust = (FF_T_UINT8) (FatSectorEntry / pIoman->BlkSize);
00357     relClusterEntry = (FF_T_UINT32)(FatSectorEntry % pIoman->BlkSize);
00358     
00359     FatSector = FF_getRealLBA(pIoman, FatSector);
00360 
00361 #ifdef FF_FAT12_SUPPORT 
00362     if(pIoman->pPartition->Type == FF_T_FAT12) {
00363         if(relClusterEntry == (FF_T_UINT32)(pIoman->BlkSize - 1)) {
00364             // Fat Entry SPANS a Sector!
00365             // First Buffer get the last Byte in buffer (first byte of our address)!
00366             pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ);
00367             {
00368                 if(!pBuffer) {
00369                     return FF_ERR_DEVICE_DRIVER_FAILED;
00370                 }
00371                 F12short[0] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1));             
00372             }
00373             FF_ReleaseBuffer(pIoman, pBuffer);
00374             // Second Buffer get the first Byte in buffer (second byte of out address)!
00375             pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ);
00376             {
00377                 if(!pBuffer) {
00378                     return FF_ERR_DEVICE_DRIVER_FAILED;
00379                 }
00380                 F12short[1] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16) 0x0000);               
00381             }
00382             FF_ReleaseBuffer(pIoman, pBuffer);
00383 
00384                     
00385             FatEntry = FF_getShort((FF_T_UINT8*)&F12short, (FF_T_UINT16) 0x0000);   // Guarantee correct Endianess!
00386             if(nCluster & 0x0001) {
00387                 FatEntry   &= 0x000F;
00388                 Value       = (Value << 4);
00389                 Value      &= 0xFFF0;
00390             }  else {
00391                 FatEntry    &= 0xF000;
00392                 Value       &= 0x0FFF;
00393             }
00394 
00395             FF_putShort((FF_T_UINT8 *)F12short, 0x0000, (FF_T_UINT16) (FatEntry | Value));
00396 
00397             pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_WRITE);
00398             {
00399                 if(!pBuffer) {
00400                     return FF_ERR_DEVICE_DRIVER_FAILED;
00401                 }
00402                 FF_putChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1), F12short[0]);              
00403             }
00404             FF_ReleaseBuffer(pIoman, pBuffer);
00405             // Second Buffer get the first Byte in buffer (second byte of out address)!
00406             pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ);
00407             {
00408                 if(!pBuffer) {
00409                     return FF_ERR_DEVICE_DRIVER_FAILED;
00410                 }
00411                 FF_putChar(pBuffer->pBuffer, 0x0000, F12short[1]);              
00412             }
00413             FF_ReleaseBuffer(pIoman, pBuffer);
00414 
00415             return FF_ERR_NONE;
00416         }
00417     }
00418 #endif
00419     
00420     pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_WRITE);
00421     {
00422         if(!pBuffer) {
00423             return FF_ERR_DEVICE_DRIVER_FAILED;
00424         }
00425         if(pIoman->pPartition->Type == FF_T_FAT32) {
00426             Value &= 0x0fffffff;    // Clear the top 4 bits.
00427             FF_putLong(pBuffer->pBuffer, relClusterEntry, Value);
00428         } else if(pIoman->pPartition->Type == FF_T_FAT16) {
00429             FF_putShort(pBuffer->pBuffer, relClusterEntry, (FF_T_UINT16) Value);
00430         } else {
00431             FatEntry    = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, relClusterEntry);
00432             if(nCluster & 0x0001) {
00433                 FatEntry   &= 0x000F;
00434                 Value       = (Value << 4);
00435                 Value      &= 0xFFF0;
00436             }  else {
00437                 FatEntry    &= 0xF000;
00438                 Value       &= 0x0FFF;
00439             }
00440             
00441             FF_putShort(pBuffer->pBuffer, relClusterEntry, (FF_T_UINT16) (FatEntry | Value));
00442         }
00443     }
00444     FF_ReleaseBuffer(pIoman, pBuffer);
00445 
00446     return FF_ERR_NONE;
00447 }
00448 
00449 
00450 
00460 #ifdef FF_FAT12_SUPPORT
00461 static FF_T_UINT32 FF_FindFreeClusterOLD(FF_IOMAN *pIoman, FF_ERROR *pError) {
00462     FF_T_UINT32 nCluster;
00463     FF_T_UINT32 fatEntry;
00464 
00465     *pError = FF_ERR_NONE;
00466 
00467     for(nCluster = pIoman->pPartition->LastFreeCluster; nCluster < pIoman->pPartition->NumClusters; nCluster++) {
00468         fatEntry = FF_getFatEntry(pIoman, nCluster, pError);
00469         if(*pError) {
00470             return 0;
00471         }
00472         if(fatEntry == 0x00000000) {
00473             pIoman->pPartition->LastFreeCluster = nCluster;
00474             return nCluster;
00475         }
00476     }
00477     return 0;
00478 }
00479 #endif
00480 
00481 FF_T_UINT32 FF_FindFreeCluster(FF_IOMAN *pIoman, FF_ERROR *pError) {
00482     FF_BUFFER   *pBuffer;
00483     FF_T_UINT32 i, x, nCluster = pIoman->pPartition->LastFreeCluster;
00484     FF_T_UINT32 FatOffset;
00485     FF_T_UINT32 FatSector;
00486     FF_T_UINT32 FatSectorEntry;
00487     FF_T_UINT32 EntriesPerSector;
00488     FF_T_UINT32 FatEntry = 1;
00489 
00490     *pError = FF_ERR_NONE;
00491 
00492 #ifdef FF_FAT12_SUPPORT
00493     if(pIoman->pPartition->Type == FF_T_FAT12) {    // FAT12 tables are too small to optimise, and would make it very complicated!
00494         return FF_FindFreeClusterOLD(pIoman, pError);
00495     }
00496 #endif
00497 
00498     if(pIoman->pPartition->Type == FF_T_FAT32) {
00499         EntriesPerSector = pIoman->BlkSize / 4;
00500         FatOffset = nCluster * 4;
00501     } else {
00502         EntriesPerSector = pIoman->BlkSize / 2;
00503         FatOffset = nCluster * 2;
00504     }
00505     
00506     // HT addition: don't use non-existing clusters
00507     if (nCluster >= pIoman->pPartition->NumClusters) {
00508         *pError = FF_ERR_FAT_NO_FREE_CLUSTERS;
00509         return 0;
00510     }
00511 
00512     FatSector = (FatOffset / pIoman->pPartition->BlkSize);
00513     
00514     for(i = FatSector; i < pIoman->pPartition->SectorsPerFAT; i++) {
00515         pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA + i, FF_MODE_READ);
00516         {
00517             if(!pBuffer) {
00518                 *pError = FF_ERR_DEVICE_DRIVER_FAILED;
00519                 return 0;
00520             }
00521             for(x = nCluster % EntriesPerSector; x < EntriesPerSector; x++) {
00522                 if(pIoman->pPartition->Type == FF_T_FAT32) {
00523                     FatOffset = x * 4;
00524                     FatSectorEntry  = FatOffset % pIoman->pPartition->BlkSize;
00525                     FatEntry = FF_getLong(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
00526                     FatEntry &= 0x0fffffff; // Clear the top 4 bits.
00527                 } else {
00528                     FatOffset = x * 2;
00529                     FatSectorEntry  = FatOffset % pIoman->pPartition->BlkSize;
00530                     FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
00531                 }
00532                 if(FatEntry == 0x00000000) {
00533                     FF_ReleaseBuffer(pIoman, pBuffer);
00534                     pIoman->pPartition->LastFreeCluster = nCluster;
00535                     
00536                     return nCluster;
00537                 }
00538                 
00539                 nCluster++;
00540             }   
00541         }
00542         FF_ReleaseBuffer(pIoman, pBuffer);
00543     }
00544 
00545     return 0;
00546 }
00547 
00552 FF_T_UINT32 FF_CreateClusterChain(FF_IOMAN *pIoman, FF_ERROR *pError) {
00553     FF_T_UINT32 iStartCluster;
00554     FF_ERROR    Error;
00555     *pError = FF_ERR_NONE;
00556 
00557     FF_lockFAT(pIoman);
00558     {
00559         iStartCluster = FF_FindFreeCluster(pIoman, &Error);
00560         if(Error) {
00561             *pError = Error;
00562             FF_unlockFAT(pIoman);
00563             return 0;
00564         }
00565 
00566         if(iStartCluster) {
00567             Error = FF_putFatEntry(pIoman, iStartCluster, 0xFFFFFFFF); // Mark the cluster as End-Of-Chain
00568             if(Error) {
00569                 *pError = Error;
00570                 FF_unlockFAT(pIoman);
00571                 return 0;
00572             }
00573         }
00574     }
00575     FF_unlockFAT(pIoman);
00576 
00577     if(iStartCluster) {
00578         Error = FF_DecreaseFreeClusters(pIoman, 1);
00579         if(Error) {
00580             *pError = Error;
00581             return 0;
00582         }
00583     }
00584 
00585     return iStartCluster;
00586 }
00587 
00588 FF_T_UINT32 FF_GetChainLength(FF_IOMAN *pIoman, FF_T_UINT32 pa_nStartCluster, FF_T_UINT32 *piEndOfChain, FF_ERROR *pError) {
00589     FF_T_UINT32 iLength = 0;
00590 
00591     *pError = FF_ERR_NONE;
00592     
00593     FF_lockFAT(pIoman);
00594     {
00595         while(!FF_isEndOfChain(pIoman, pa_nStartCluster)) {
00596             pa_nStartCluster = FF_getFatEntry(pIoman, pa_nStartCluster, pError);
00597             if(*pError) {
00598                 return 0;
00599             }
00600             iLength++;
00601         }
00602         if(piEndOfChain) {
00603             *piEndOfChain = pa_nStartCluster;
00604         }
00605     }
00606     FF_unlockFAT(pIoman);
00607 
00608     return iLength;
00609 }
00610 
00620 /*
00621 FF_T_UINT32 FF_ExtendClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_T_UINT32 Count) {
00622     
00623     FF_T_UINT32 currentCluster = StartCluster, nextCluster;
00624     FF_T_UINT32 clusEndOfChain;
00625     FF_T_UINT32 i;
00626     
00627     clusEndOfChain = FF_FindEndOfChain(pIoman, StartCluster);
00628 
00629     nextCluster = FF_FindFreeCluster(pIoman);   // Find Free clusters!
00630 
00631     FF_putFatEntry(pIoman, clusEndOfChain, nextCluster);
00632 
00633     for(i = 0; i <= Count; i++) {
00634         currentCluster = nextCluster;
00635         if(i == Count) {
00636             FF_putFatEntry(pIoman, currentCluster, 0xFFFFFFFF);
00637             break;
00638         }
00639 
00640         nextCluster = FF_FindFreeCluster(pIoman);
00641         FF_putFatEntry(pIoman, currentCluster, ++nextCluster);
00642     }
00643     FF_FlushCache(pIoman);
00644     return currentCluster;
00645 }*/
00646 
00647 
00661 FF_ERROR FF_UnlinkClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_T_UINT16 Count) {
00662     
00663     FF_T_UINT32 fatEntry;
00664     FF_T_UINT32 currentCluster, chainLength = 0;
00665     FF_T_UINT32 iLen = 0;
00666     FF_T_UINT32 lastFree = StartCluster;    /* HT addition : reset LastFreeCluster */
00667     FF_ERROR    Error;
00668 
00669     fatEntry = StartCluster;
00670 
00671     if(Count == 0) {
00672         // Free all clusters in the chain!
00673         currentCluster = StartCluster;
00674         fatEntry = currentCluster;
00675         do {
00676             fatEntry = FF_getFatEntry(pIoman, fatEntry, &Error);
00677             if(Error) {
00678                 return Error;
00679             }
00680             Error = FF_putFatEntry(pIoman, currentCluster, 0x00000000);
00681             if(Error) {
00682                 return Error;
00683             }
00684 
00685             if (lastFree > currentCluster) {
00686                 lastFree = currentCluster;
00687             }
00688             currentCluster = fatEntry;
00689             iLen ++;
00690         }while(!FF_isEndOfChain(pIoman, fatEntry));
00691         if (pIoman->pPartition->LastFreeCluster > lastFree) {
00692             pIoman->pPartition->LastFreeCluster = lastFree;
00693         }
00694         Error = FF_IncreaseFreeClusters(pIoman, iLen);
00695         if(Error) {
00696             return Error;
00697         }
00698     } else {
00699         // Truncation - This is quite hard, because we can only do it backwards.
00700         do {
00701             fatEntry = FF_getFatEntry(pIoman, fatEntry, &Error);
00702             if(Error) {
00703                 return Error;
00704             }
00705             chainLength++;
00706         }while(!FF_isEndOfChain(pIoman, fatEntry));
00707     }
00708 
00709     return FF_ERR_NONE;
00710 }
00711 
00712 #ifdef FF_FAT12_SUPPORT
00713 FF_T_UINT32 FF_CountFreeClustersOLD(FF_IOMAN *pIoman, FF_ERROR *pError) {
00714     FF_T_UINT32 i;
00715     FF_T_UINT32 TotalClusters = pIoman->pPartition->DataSectors / pIoman->pPartition->SectorsPerCluster;
00716     FF_T_UINT32 FatEntry;
00717     FF_T_UINT32 FreeClusters = 0;
00718 
00719     *pError = FF_ERR_NONE;
00720 
00721     for(i = 0; i < TotalClusters; i++) {
00722         FatEntry = FF_getFatEntry(pIoman, i, pError);
00723         if(*pError) {
00724             return 0;
00725         }
00726         if(!FatEntry) {
00727             FreeClusters++;
00728         }
00729     }
00730 
00731     return FreeClusters;
00732 }
00733 #endif
00734 
00735 
00736 FF_T_UINT32 FF_CountFreeClusters(FF_IOMAN *pIoman, FF_ERROR *pError) {
00737     FF_BUFFER   *pBuffer;
00738     FF_T_UINT32 i, x, nCluster = 0;
00739     FF_T_UINT32 FatOffset;
00740     FF_T_UINT32 FatSector;
00741     FF_T_UINT32 FatSectorEntry;
00742     FF_T_UINT32 EntriesPerSector;
00743     FF_T_UINT32 FatEntry = 1;
00744     FF_T_UINT32 FreeClusters = 0;
00745 
00746     *pError = FF_ERR_NONE;
00747 
00748 #ifdef FF_FAT12_SUPPORT
00749     if(pIoman->pPartition->Type == FF_T_FAT12) {    // FAT12 tables are too small to optimise, and would make it very complicated!
00750         FreeClusters = FF_CountFreeClustersOLD(pIoman, pError);
00751         if(*pError) {
00752             return 0;
00753         }
00754     }
00755 #endif
00756 
00757     if(pIoman->pPartition->Type == FF_T_FAT32) {
00758         EntriesPerSector = pIoman->BlkSize / 4;
00759         FatOffset = nCluster * 4;
00760     } else {
00761         EntriesPerSector = pIoman->BlkSize / 2;
00762         FatOffset = nCluster * 2;
00763     }
00764 
00765     FatSector = (FatOffset / pIoman->pPartition->BlkSize);
00766     
00767     for(i = 0; i < pIoman->pPartition->SectorsPerFAT; i++) {
00768         pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA + i, FF_MODE_READ);
00769         {
00770             if(!pBuffer) {
00771                 *pError = FF_ERR_DEVICE_DRIVER_FAILED;
00772                 return 0;
00773             }
00774             for(x = nCluster % EntriesPerSector; x < EntriesPerSector; x++) {
00775                 if(pIoman->pPartition->Type == FF_T_FAT32) {
00776                     FatOffset = x * 4;
00777                     FatSectorEntry  = FatOffset % pIoman->pPartition->BlkSize;
00778                     FatEntry = FF_getLong(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
00779                     FatEntry &= 0x0fffffff; // Clear the top 4 bits.
00780                 } else {
00781                     FatOffset = x * 2;
00782                     FatSectorEntry  = FatOffset % pIoman->pPartition->BlkSize;
00783                     FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FatSectorEntry);
00784                 }
00785                 if(FatEntry == 0x00000000) {
00786                     FreeClusters += 1;
00787                 }
00788                 
00789                 nCluster++;
00790             }   
00791         }
00792         FF_ReleaseBuffer(pIoman, pBuffer);
00793     }
00794 
00795     return FreeClusters <= pIoman->pPartition->NumClusters ? FreeClusters : pIoman->pPartition->NumClusters;
00796 }
00797 
00798 #ifdef FF_64_NUM_SUPPORT
00799 FF_T_UINT64 FF_GetFreeSize(FF_IOMAN *pIoman, FF_ERROR *pError) {
00800     FF_T_UINT32 FreeClusters;
00801     FF_T_UINT64 FreeSize;
00802     FF_ERROR    Error;
00803     
00804     if(pIoman) {
00805         FF_lockFAT(pIoman);
00806         {   
00807             if(!pIoman->pPartition->FreeClusterCount) {
00808                 pIoman->pPartition->FreeClusterCount = FF_CountFreeClusters(pIoman, &Error);
00809                 if(Error) {
00810                     if(pError) {
00811                         *pError = Error;
00812                     }
00813                     FF_unlockFAT(pIoman);
00814                     return 0;
00815                 }
00816             }
00817             FreeClusters = pIoman->pPartition->FreeClusterCount;
00818         }
00819         FF_unlockFAT(pIoman);
00820         FreeSize = (FF_T_UINT64) ((FF_T_UINT64)FreeClusters * (FF_T_UINT64)((FF_T_UINT64)pIoman->pPartition->SectorsPerCluster * (FF_T_UINT64)pIoman->pPartition->BlkSize));
00821         return FreeSize;
00822     }
00823     return 0;
00824 }
00825 #else
00826 FF_T_UINT32 FF_GetFreeSize(FF_IOMAN *pIoman) {
00827     FF_T_UINT32 FreeClusters;
00828     FF_T_UINT32 FreeSize;
00829     
00830     if(pIoman) {
00831         FF_lockFAT(pIoman);
00832         {   
00833             if(!pIoman->pPartition->FreeClusterCount) {
00834                 pIoman->pPartition->FreeClusterCount = FF_CountFreeClusters(pIoman);
00835             }
00836             FreeClusters = pIoman->pPartition->FreeClusterCount;
00837         }
00838         FF_unlockFAT(pIoman);
00839         FreeSize = (FF_T_UINT32) ((FF_T_UINT32)FreeClusters * (FF_T_UINT32)((FF_T_UINT32)pIoman->pPartition->SectorsPerCluster * (FF_T_UINT32)pIoman->pPartition->BlkSize));
00840         return FreeSize;
00841     }
00842     return 0;
00843 }
00844 #endif

Generated on Sun May 27 2012 04:34:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.