Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenff_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
1.7.6.1
|