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_dir.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_dir.h"
00044 #include "ff_string.h"
00045 #include "ff_unicode.h"
00046 #include <stdio.h>
00047 
00048 
00049 #ifdef FF_UNICODE_SUPPORT
00050 #include <wchar.h>
00051 #endif
00052 
00053 #ifdef WIN32
00054 #else
00055 #include <ctype.h>  // tolower()
00056 int strcasecmp(const char *s1, const char *s2)
00057 {
00058   unsigned char c1,c2;
00059   do {
00060     c1 = *s1++;
00061     c2 = *s2++;
00062     c1 = (unsigned char) tolower( (unsigned char) c1);
00063     c2 = (unsigned char) tolower( (unsigned char) c2);
00064   }
00065   while((c1 == c2) && (c1 != '\0'));
00066   return (int) c1-c2;
00067 }
00068 #endif
00069 
00070 
00071 #ifdef FF_UNICODE_SUPPORT
00072 static void FF_ProcessShortName(FF_T_WCHAR *name);
00073 #else
00074 static void FF_ProcessShortName(FF_T_INT8 *name);
00075 #endif
00076 
00077 void FF_lockDIR(FF_IOMAN *pIoman) {
00078     FF_PendSemaphore(pIoman->pSemaphore);   // Use Semaphore to protect DIR modifications.
00079     {
00080         while((pIoman->Locks & FF_DIR_LOCK)) {
00081             FF_ReleaseSemaphore(pIoman->pSemaphore);
00082             FF_Yield();                     // Keep Releasing and Yielding until we have the DIR protector.
00083             FF_PendSemaphore(pIoman->pSemaphore);
00084         }
00085         pIoman->Locks |= FF_DIR_LOCK;
00086     }
00087     FF_ReleaseSemaphore(pIoman->pSemaphore);
00088 }
00089 
00090 void FF_unlockDIR(FF_IOMAN *pIoman) {
00091     FF_PendSemaphore(pIoman->pSemaphore);
00092     {
00093         pIoman->Locks &= ~FF_DIR_LOCK;
00094     }
00095     FF_ReleaseSemaphore(pIoman->pSemaphore);
00096 }
00097 
00098 static FF_T_UINT8 FF_CreateChkSum(const FF_T_UINT8 *pa_pShortName) {
00099     FF_T_UINT8  cNameLen;
00100     FF_T_UINT8  ChkSum = 0;
00101 
00102     for(cNameLen = 11; cNameLen != 0; cNameLen--) {
00103         ChkSum = ((ChkSum & 1) ? 0x80 : 0) + (ChkSum >> 1) + *pa_pShortName++;
00104     }
00105     return ChkSum;
00106 }
00107 
00108 
00109 FF_ERROR FF_FindNextInDir(FF_IOMAN *pIoman, FF_DIRENT *pDirent, FF_FETCH_CONTEXT *pFetchContext) {
00110     
00111     FF_T_UINT8      numLFNs;
00112     FF_T_UINT8      EntryBuffer[32];
00113     FF_ERROR        Error;
00114 
00115     if(!pIoman) {
00116         return FF_ERR_NULL_POINTER;
00117     }
00118 
00119     for(; pDirent->CurrentItem < 0xFFFF; pDirent->CurrentItem += 1) {
00120         
00121         Error = FF_FetchEntryWithContext(pIoman, pDirent->CurrentItem, pFetchContext, EntryBuffer);
00122         
00123         if(Error) {
00124             return Error;
00125         }
00126         
00127         if(EntryBuffer[0] != 0xE5) {
00128             if(FF_isEndOfDir(EntryBuffer)){
00129                 return FF_ERR_DIR_END_OF_DIR;
00130             }
00131             pDirent->Attrib = FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB));
00132             if((pDirent->Attrib & FF_FAT_ATTR_LFN) == FF_FAT_ATTR_LFN) {
00133                 // LFN Processing
00134                 numLFNs = (FF_T_UINT8)(EntryBuffer[0] & ~0x40);
00135                 //pDirent->NumLFNs = numLFNs;
00136 #ifdef FF_LFN_SUPPORT
00137                 Error = FF_PopulateLongDirent(pIoman, pDirent, pDirent->CurrentItem, pFetchContext);
00138                 if(Error) {
00139                     return Error;
00140                 }
00141                 return FF_ERR_NONE;
00142 #else 
00143                 pDirent->CurrentItem += (numLFNs - 1);
00144 #endif
00145             } else if((pDirent->Attrib & FF_FAT_ATTR_VOLID) == FF_FAT_ATTR_VOLID) {
00146                 // Do Nothing
00147             
00148             } else {
00149                 FF_PopulateShortDirent(pIoman, pDirent, EntryBuffer);
00150                 pDirent->CurrentItem += 1;
00151                 return FF_ERR_NONE;
00152             }
00153         }
00154     }
00155     
00156     return FF_ERR_DIR_END_OF_DIR;
00157 }
00158 
00159 #ifdef FF_UNICODE_SUPPORT
00160 static FF_T_BOOL FF_ShortNameExists(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster, FF_T_WCHAR *szShortName, FF_ERROR *pError) {
00161 #else
00162 static FF_T_BOOL FF_ShortNameExists(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster, FF_T_INT8 *szShortName, FF_ERROR *pError) {
00163 #endif
00164 
00165     FF_T_UINT16         i;
00166     FF_T_UINT8          EntryBuffer[32];
00167     FF_T_UINT8          Attrib;
00168     FF_FETCH_CONTEXT    FetchContext;
00169 
00170 #ifdef FF_UNICODE_SUPPORT
00171     FF_T_WCHAR          UTF16EntryBuffer[32];
00172 #endif
00173     
00174 #ifdef FF_HASH_CACHE
00175     FF_T_UINT32         ulHash;
00176 #endif
00177 
00178     *pError = FF_ERR_NONE;
00179 
00180 
00181 #ifdef FF_HASH_CACHE
00182     if(!FF_DirHashed(pIoman, ulDirCluster)) {
00183         // Hash the directory
00184         FF_HashDir(pIoman, ulDirCluster);
00185     }
00186 
00187 #if FF_HASH_FUNCTION == CRC16
00188     ulHash = (FF_T_UINT32) FF_GetCRC16((FF_T_UINT8 *) szShortName, strlen(szShortName));
00189 #elif FF_HASH_FUNCTION == CRC8
00190     ulHash = (FF_T_UINT32) FF_GetCRC8((FF_T_UINT8 *) szShortName, strlen(szShortName));
00191 #endif
00192     
00193     if(!FF_CheckDirentHash(pIoman, ulDirCluster, ulHash)) {
00194         return FF_FALSE;
00195     }
00196 
00197 #endif
00198 
00199     *pError = FF_InitEntryFetch(pIoman, ulDirCluster, &FetchContext);
00200     if(*pError) {
00201         return FF_FALSE;
00202     }
00203 
00204     for(i = 0; i < 0xFFFF; i++) {
00205         *pError = FF_FetchEntryWithContext(pIoman, i, &FetchContext, EntryBuffer);
00206         if(*pError) {
00207             FF_CleanupEntryFetch(pIoman, &FetchContext);
00208             return FF_FALSE;            
00209         }
00210         Attrib = FF_getChar(EntryBuffer, FF_FAT_DIRENT_ATTRIB);
00211         if(FF_getChar(EntryBuffer, 0x00) != 0xE5) {
00212             if(Attrib != FF_FAT_ATTR_LFN) {
00213 #ifdef FF_UNICODE_SUPPORT
00214                 // Convert Entry Buffer into UTF16
00215                 FF_cstrntowcs(UTF16EntryBuffer, (FF_T_INT8 *) EntryBuffer, 32);
00216                 FF_ProcessShortName(UTF16EntryBuffer);
00217 #else
00218                 FF_ProcessShortName((FF_T_INT8 *)EntryBuffer);
00219 #endif
00220                 if(FF_isEndOfDir(EntryBuffer)) {
00221                     FF_CleanupEntryFetch(pIoman, &FetchContext);
00222                     return FF_FALSE;
00223                 }
00224 #ifdef FF_UNICODE_SUPPORT
00225                 if(wcscmp(szShortName, UTF16EntryBuffer) == 0) {
00226 #else
00227                 if(strcmp(szShortName, (FF_T_INT8 *)EntryBuffer) == 0) {
00228 #endif
00229                     FF_CleanupEntryFetch(pIoman, &FetchContext);
00230                     return FF_TRUE;
00231                 }
00232             }
00233         }
00234     }
00235 
00236     FF_CleanupEntryFetch(pIoman, &FetchContext);
00237     return FF_FALSE;
00238 }
00239 
00240 
00241 #ifdef FF_UNICODE_SUPPORT
00242 FF_T_UINT32 FF_FindEntryInDir(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, const FF_T_WCHAR *name, FF_T_UINT8 pa_Attrib, FF_DIRENT *pDirent, FF_ERROR *pError) {
00243 #else
00244 FF_T_UINT32 FF_FindEntryInDir(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, const FF_T_INT8 *name, FF_T_UINT8 pa_Attrib, FF_DIRENT *pDirent, FF_ERROR *pError) {
00245 #endif
00246 
00247     FF_FETCH_CONTEXT FetchContext;
00248     FF_T_UINT8  *src;   // Pointer to read from pBuffer
00249     FF_T_UINT8  *lastSrc;
00250 #ifdef FF_UNICODE_UTF8_SUPPORT
00251     FF_T_SINT32 utf8Error;
00252     FF_T_UINT8  bSurrogate = FF_FALSE;
00253 #endif
00254 #ifdef FF_UNICODE_SUPPORT
00255     FF_T_WCHAR  *ptr;       // Pointer to store a LFN
00256 #else
00257     FF_T_INT8   *ptr;       // Pointer to store a LFN
00258 #endif
00259 #ifdef FF_UNICODE_SUPPORT
00260     FF_T_WCHAR  *lastPtr = pDirent->FileName + sizeof(pDirent->FileName);
00261 #else
00262     FF_T_INT8   *lastPtr = pDirent->FileName + sizeof(pDirent->FileName);
00263 #endif
00264     FF_T_UINT8  CheckSum = 0;
00265     FF_T_UINT8  lastAttrib;
00266     FF_T_INT8   totalLFNs = 0;
00267     FF_T_INT8   numLFNs = 0;
00268     FF_T_INT32  i;
00269     FF_T_UINT16 lfnItem = 0;
00270 
00271     pError = NULL;
00272 
00273     pDirent->CurrentItem = 0;
00274     pDirent->Attrib = 0;
00275 
00276     FF_InitEntryFetch(pIoman, DirCluster, &FetchContext);
00277 
00278     while(pDirent->CurrentItem < 0xFFFF) {
00279         if (FF_FetchEntryWithContext(pIoman, pDirent->CurrentItem, &FetchContext, NULL)) {
00280             break;
00281         }
00282         lastSrc = FetchContext.pBuffer->pBuffer + pIoman->BlkSize;
00283         for (src = FetchContext.pBuffer->pBuffer; src < lastSrc; src += 32, pDirent->CurrentItem++) {
00284             if (FF_isEndOfDir(src)) {   // 0x00: end-of-dir
00285                 FF_CleanupEntryFetch(pIoman, &FetchContext);
00286                 return 0;
00287             }
00288             if (src[0] == 0xE5) {   // Entry not used
00289                 pDirent->Attrib = 0;
00290                 continue;
00291             }
00292             lastAttrib = pDirent->Attrib;
00293             pDirent->Attrib = FF_getChar(src, FF_FAT_DIRENT_ATTRIB);
00294             if((pDirent->Attrib & FF_FAT_ATTR_LFN) == FF_FAT_ATTR_LFN) {
00295                 // LFN Processing
00296 #ifdef FF_LFN_SUPPORT
00297                 if (numLFNs == 0 || (lastAttrib & FF_FAT_ATTR_LFN) != FF_FAT_ATTR_LFN) {
00298                     totalLFNs = numLFNs = (FF_T_UINT8)(src[0] & ~0x40);
00299                     lfnItem = pDirent->CurrentItem;
00300                     CheckSum = FF_getChar(src, FF_FAT_LFN_CHECKSUM);
00301                     lastPtr[-1] = '\0';
00302                 }
00303                 if (numLFNs) {
00304                     numLFNs--;
00305                     ptr = pDirent->FileName + (numLFNs * 13);
00306 
00307                     /*
00308                         This section needs to extract the name and do the comparison
00309                         dependent on UNICODE settings in the ff_config.h file.
00310                     */
00311 #ifdef FF_UNICODE_SUPPORT
00312                     // Add UTF-16 Routine here
00313                     memcpy(ptr, &src[FF_FAT_LFN_NAME_1], 10);   // Copy first 5 UTF-16 chars (10 bytes).
00314                     ptr += 5;                                   // Increment Filename pointer 5 utf16 chars.
00315                     
00316                     memcpy(ptr, &src[FF_FAT_LFN_NAME_2], 12);   //Copy next 6 chars (12 bytes).
00317                     ptr += 6;
00318 
00319                     memcpy(ptr, &src[FF_FAT_LFN_NAME_3], 4);        // You're getting the idea by now!
00320                     ptr += 2;
00321 
00322 #endif
00323 #ifdef FF_UNICODE_UTF8_SUPPORT
00324                     // UTF-8 Routine here
00325                     for(i = 0; i < 5 && ptr < lastPtr; i++) {
00326                         // Was there a surrogate sequence? -- Add handling here.
00327                         utf8Error = FF_Utf16ctoUtf8c((FF_T_UINT8 *) ptr, (FF_T_UINT16 *) &src[FF_FAT_LFN_NAME_1 + (2*i)], lastPtr - ptr);
00328                         if(utf8Error > 0) {
00329                             ptr += utf8Error;
00330 
00331                         } else {
00332                             if(utf8Error == FF_ERR_UNICODE_INVALID_SEQUENCE) {
00333                                 // Handle potential surrogate sequence across entries.
00334 
00335                             }
00336                         }
00337                     }
00338 
00339                     for(i = 0; i < 6 && ptr < lastPtr; i++) {
00340                         // Was there a surrogate sequence? -- To add handling here.
00341                         utf8Error = FF_Utf16ctoUtf8c((FF_T_UINT8 *) ptr, (FF_T_UINT16 *) &src[FF_FAT_LFN_NAME_2 + (2*i)], lastPtr - ptr);
00342                         if(utf8Error > 0) {
00343                             ptr += utf8Error;
00344                         } else {
00345                             if(utf8Error == FF_ERR_UNICODE_INVALID_SEQUENCE) {
00346                                 // Handle potential surrogate sequence across entries.
00347                             }
00348                         }
00349                     }
00350 
00351                     for(i = 0; i < 2 && ptr < lastPtr; i++) {
00352                         // Was there a surrogate sequence? -- To add handling here.
00353                         utf8Error = FF_Utf16ctoUtf8c((FF_T_UINT8 *) ptr, (FF_T_UINT16 *) &src[FF_FAT_LFN_NAME_3 + (2*i)], lastPtr - ptr);
00354                         if(utf8Error > 0) {
00355                             ptr += utf8Error;
00356                         } else {
00357                             if(utf8Error == FF_ERR_UNICODE_INVALID_SEQUENCE) {
00358                                 // Handle potential surrogate sequence across entries.
00359                             }
00360                         }
00361                     } 
00362                     
00363 #endif
00364 #ifndef FF_UNICODE_SUPPORT
00365 #ifndef FF_UNICODE_UTF8_SUPPORT
00366                     for(i = 0; i < 10 && ptr < lastPtr; i += 2)
00367                         *(ptr++) = src[FF_FAT_LFN_NAME_1 + i];
00368 
00369                     for(i = 0; i < 12 && ptr < lastPtr; i += 2)
00370                         *(ptr++) = src[FF_FAT_LFN_NAME_2 + i];
00371 
00372                     for(i = 0; i < 4 && ptr < lastPtr; i += 2)
00373                         *(ptr++) = src[FF_FAT_LFN_NAME_3 + i];
00374 
00375                     if (numLFNs == totalLFNs-1 && ptr < lastPtr)
00376                         *ptr = '\0';    // Important when name len is multiple of 13
00377 #endif
00378 #endif
00379                     if (numLFNs == totalLFNs-1 && ptr < lastPtr)
00380                         *ptr = '\0';    // Important when name len is multiple of 13
00381                         
00382                 }
00383 #endif
00384                 continue;
00385             }
00386             if ((pDirent->Attrib & FF_FAT_ATTR_VOLID) == FF_FAT_ATTR_VOLID) {
00387                 totalLFNs = 0;
00388                 continue;
00389             }
00390 #ifdef FF_LFN_SUPPORT
00391             if(!totalLFNs || CheckSum != FF_CreateChkSum(src)) 
00392 #endif
00393             {
00394 #ifdef FF_UNICODE_SUPPORT
00395                 for(i = 0; i < 11; i++) {
00396                     pDirent->FileName[i] = (FF_T_WCHAR) src[i];
00397                 }
00398                 FF_ProcessShortName(pDirent->FileName);
00399 #else
00400                 memcpy(pDirent->FileName, src, 11);
00401                 FF_ProcessShortName(pDirent->FileName);
00402 #endif
00403                 totalLFNs = 0;
00404             }
00405 
00406             if((pDirent->Attrib & pa_Attrib) == pa_Attrib){
00407 #ifdef FF_UNICODE_SUPPORT
00408                 if(!wcsicmp(name, pDirent->FileName)) {
00409 #else
00410                 if (!FF_stricmp(name, pDirent->FileName)) {
00411 #endif
00412                     // Finally get the complete information
00413 #ifdef FF_LFN_SUPPORT
00414                     if (totalLFNs) {
00415                         FF_PopulateLongDirent(pIoman, pDirent, lfnItem, &FetchContext);
00416                     } else
00417 #endif
00418                     {
00419                         FF_PopulateShortDirent(pIoman, pDirent, src);
00420                     }
00421                     // Object found!
00422                     FF_CleanupEntryFetch(pIoman, &FetchContext);
00423                     return pDirent->ObjectCluster;  // Return the cluster number
00424                 }
00425             }
00426             totalLFNs = 0;
00427         }
00428     }   // for (src = FetchContext.pBuffer->pBuffer; src < lastSrc; src += 32, pDirent->CurrentItem++)
00429 
00430     FF_CleanupEntryFetch(pIoman, &FetchContext);
00431 
00432     return 0;
00433 }
00434 
00435 
00436 
00440 #ifdef FF_UNICODE_SUPPORT
00441 FF_T_UINT32 FF_FindDir(FF_IOMAN *pIoman, const FF_T_WCHAR *path, FF_T_UINT16 pathLen, FF_ERROR *pError) {
00442 #else
00443 FF_T_UINT32 FF_FindDir(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT16 pathLen, FF_ERROR *pError) {
00444 #endif
00445     FF_T_UINT32     dirCluster = pIoman->pPartition->RootDirCluster;
00446 #ifdef FF_UNICODE_SUPPORT
00447     FF_T_WCHAR      mytoken[FF_MAX_FILENAME];
00448     FF_T_WCHAR      *token;
00449 #else
00450     FF_T_INT8       mytoken[FF_MAX_FILENAME];
00451     FF_T_INT8       *token;
00452 #endif
00453     
00454     FF_T_UINT16     it = 0;         // Re-entrancy Variables for FF_strtok()
00455     FF_T_BOOL       last = FF_FALSE;
00456     FF_DIRENT       MyDir;
00457 #ifdef FF_PATH_CACHE
00458     FF_T_UINT32     i;
00459 #endif
00460 
00461     *pError = FF_ERR_NONE;
00462 
00463     if(pathLen <= 1) {      // Must be the root dir! (/ or \)
00464         return pIoman->pPartition->RootDirCluster;
00465     }
00466     
00467     if(path[pathLen-1] == '\\' || path[pathLen-1] == '/') {
00468         pathLen--;      
00469     }
00470     
00471 #ifdef FF_PATH_CACHE    // Is the requested path in the PATH CACHE?
00472     FF_PendSemaphore(pIoman->pSemaphore);   // Thread safety on shared object!
00473     {
00474         for(i = 0; i < FF_PATH_CACHE_DEPTH; i++) {
00475 #ifdef FF_UNICODE_SUPPORT
00476             if(wcslen(pIoman->pPartition->PathCache[i].Path) == pathLen) {
00477                 if(FF_strmatch(pIoman->pPartition->PathCache[i].Path, path, pathLen)) {
00478 #else
00479             if(strlen(pIoman->pPartition->PathCache[i].Path) == pathLen) {
00480                 if(FF_strmatch(pIoman->pPartition->PathCache[i].Path, path, pathLen)) {
00481 #endif
00482                 
00483                     FF_ReleaseSemaphore(pIoman->pSemaphore);
00484                     return pIoman->pPartition->PathCache[i].DirCluster;
00485                 }
00486             }
00487         }
00488     }
00489     FF_ReleaseSemaphore(pIoman->pSemaphore);
00490 #endif
00491 
00492     token = FF_strtok(path, mytoken, &it, &last, pathLen);
00493 
00494      do{
00495             MyDir.CurrentItem = 0;
00496             dirCluster = FF_FindEntryInDir(pIoman, dirCluster, token, FF_FAT_ATTR_DIR, &MyDir, pError);
00497 
00498             if(*pError) {
00499                 return 0;
00500             }
00501 
00502             /*if(dirCluster == 0 && MyDir.CurrentItem == 2 && MyDir.FileName[0] == '.') { // .. Dir Entry pointing to root dir.
00503                 dirCluster = pIoman->pPartition->RootDirCluster;
00504             }*/
00505             token = FF_strtok(path, mytoken, &it, &last, pathLen);
00506     }while(token != NULL);
00507 
00508 #ifdef FF_PATH_CACHE    // Update the PATH CACHE with a new PATH
00509      if(dirCluster) {   // Only cache if the dir was actually found!
00510         FF_PendSemaphore(pIoman->pSemaphore);
00511         {
00512             if(pathLen < FF_MAX_PATH) { // Ensure the PATH won't cause a buffer overrun.
00513 #ifdef FF_UNICODE_SUPPORT
00514                 memcpy(pIoman->pPartition->PathCache[pIoman->pPartition->PCIndex].Path, path, pathLen * sizeof(FF_T_WCHAR));
00515 #else
00516                 memcpy(pIoman->pPartition->PathCache[pIoman->pPartition->PCIndex].Path, path, pathLen);
00517 #endif
00518                 pIoman->pPartition->PathCache[pIoman->pPartition->PCIndex].Path[pathLen] = '\0';
00519                 pIoman->pPartition->PathCache[pIoman->pPartition->PCIndex].DirCluster = dirCluster;
00520 #ifdef FF_HASH_TABLE_SUPPORT                
00521                 FF_ClearHashTable(pIoman->pPartition->PathCache[pIoman->pPartition->PCIndex].pHashTable);
00522 #endif          
00523                 pIoman->pPartition->PCIndex += 1;
00524                 if(pIoman->pPartition->PCIndex >= FF_PATH_CACHE_DEPTH) {
00525                     pIoman->pPartition->PCIndex = 0;
00526                 }
00527             }
00528         }
00529         FF_ReleaseSemaphore(pIoman->pSemaphore);
00530      }
00531 #endif
00532 
00533     return dirCluster;
00534 }
00535 
00536 
00537 #if defined(FF_SHORTNAME_CASE)
00538 
00543 #ifdef FF_UNICODE_SUPPORT
00544 static void FF_CaseShortName(FF_T_WCHAR *name, FF_T_UINT8 attrib) {
00545 #else
00546 static void FF_CaseShortName(FF_T_INT8 *name, FF_T_UINT8 attrib) {
00547 #endif
00548     FF_T_UINT8 testAttrib = FF_FAT_CASE_ATTR_BASE;
00549     for (; *name; name++) {
00550         if (*name == '.') {
00551             testAttrib = FF_FAT_CASE_ATTR_EXT;
00552         } else if ((attrib & testAttrib)) {
00553             if (*name >= 'A' && *name <= 'Z')
00554                 *name += 0x20;
00555         } else if (*name >= 'a' && *name <= 'z') {
00556             *name -= 0x20;
00557         }
00558     }
00559 }
00560 #endif
00561 
00566 #ifdef FF_UNICODE_SUPPORT
00567 static void FF_ProcessShortName(FF_T_WCHAR *name) {
00568     FF_T_WCHAR  shortName[13];
00569     FF_T_WCHAR  *ptr = name;
00570 #else
00571 static void FF_ProcessShortName(FF_T_INT8 *name) {
00572     FF_T_INT8   shortName[13];
00573     FF_T_INT8   *ptr = name;
00574 #endif
00575     FF_T_UINT8  i;
00576 #ifdef FF_UNICODE_SUPPORT
00577     memcpy(shortName, name, 11 * sizeof(FF_T_WCHAR));
00578 #else
00579     memcpy(shortName, name, 11);
00580 #endif
00581 
00582     for(i = 0; i < 11; i++) {
00583         if(shortName[i] == 0x20) {
00584             if (i >= 8)
00585                 break;
00586             i = 7;
00587         } else {
00588             if (i == 8)
00589                 *(ptr++) = '.';
00590             *(ptr++) = shortName[i];
00591         }
00592     }
00593     *ptr = '\0';
00594 }
00595 
00596 /*
00597 #ifdef FF_UNICODE_SUPPORT
00598 static void FF_ProcessShortName(FF_T_WCHAR *name) {
00599     FF_T_WCHAR  shortName[13];
00600 #else
00601 static void FF_ProcessShortName(FF_T_INT8 *name) {
00602     FF_T_INT8   shortName[13];
00603 #endif
00604     
00605     FF_T_UINT8  i;
00606 #ifdef FF_UNICODE_SUPPORT
00607     memcpy(shortName, name, 11 * sizeof(FF_T_WCHAR));
00608 #else
00609     memcpy(shortName, name, 11);
00610 #endif
00611     
00612     for(i = 0; i < 8; i++) {
00613         if(shortName[i] == 0x20) {
00614             name[i] = '\0';
00615             break;
00616         }
00617         name[i] = shortName[i];
00618     }
00619 
00620     if(shortName[8] != 0x20){
00621         name[i] = '.';
00622         name[i+1] = shortName[8];
00623         name[i+2] = shortName[9];
00624         name[i+3] = shortName[10];
00625         name[i+4] = '\0';
00626         for(i = 0; i < 11; i++) {
00627             if(name[i] == 0x20) {
00628                 name[i] = '\0';
00629                 break;
00630             }
00631         }
00632     } else {
00633         name[i] = '\0';
00634     }
00635 
00636 }*/
00637 
00638 #ifdef FF_TIME_SUPPORT
00639 static void FF_PlaceTime(FF_T_UINT8 *EntryBuffer, FF_T_UINT32 Offset) {
00640     FF_T_UINT16     myShort;
00641     FF_SYSTEMTIME   str_t;
00642 
00643     FF_GetSystemTime(&str_t);
00644                 
00645     myShort = 0;
00646     myShort |= ((str_t.Hour    << 11) & 0xF800);
00647     myShort |= ((str_t.Minute  <<  5) & 0x07E0);
00648     myShort |= ((str_t.Second   /  2) & 0x001F);
00649     FF_putShort(EntryBuffer, (FF_T_UINT16) Offset, myShort);
00650 }
00651 
00652 static void FF_PlaceDate(FF_T_UINT8 *EntryBuffer, FF_T_UINT32 Offset) {
00653     FF_T_UINT16     myShort;
00654     FF_SYSTEMTIME   str_t;
00655 
00656     FF_GetSystemTime(&str_t);
00657     
00658     myShort = 0;
00659     myShort |= (((str_t.Year- 1980)  <<  9) & 0xFE00) ;
00660     myShort |= ((str_t.Month <<  5) & 0x01E0);
00661     myShort |= (str_t.Day & 0x001F);
00662     FF_putShort(EntryBuffer, (FF_T_UINT16) Offset, myShort);
00663 }
00664 
00665 
00666 static void FF_GetTime(FF_SYSTEMTIME *pTime, FF_T_UINT8 *EntryBuffer, FF_T_UINT32 Offset) {
00667     FF_T_UINT16 myShort;
00668     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16) Offset);
00669     pTime->Hour     = (((myShort & 0xF800) >> 11) & 0x001F);
00670     pTime->Minute   = (((myShort & 0x07E0) >>  5) & 0x003F);
00671     pTime->Second   = 2 * (myShort & 0x01F);
00672 }
00673 
00674 static void FF_GetDate(FF_SYSTEMTIME *pTime, FF_T_UINT8 *EntryBuffer, FF_T_UINT32 Offset) {
00675     FF_T_UINT16 myShort;
00676     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16) Offset);
00677     pTime->Year     = 1980 + (((myShort & 0xFE00) >> 9) & 0x07F);
00678     pTime->Month    = (((myShort & 0x01E0) >> 5) & 0x000F);
00679     pTime->Day      = myShort & 0x01F;
00680 }
00681 #endif
00682 
00683 void FF_PopulateShortDirent(FF_IOMAN *pIoman, FF_DIRENT *pDirent, FF_T_UINT8 *EntryBuffer) {
00684     FF_T_UINT16 myShort;
00685 #ifdef FF_UNICODE_SUPPORT
00686     FF_T_WCHAR UTF16EntryBuffer[12];
00687     FF_cstrntowcs(UTF16EntryBuffer, (FF_T_INT8 *) EntryBuffer, 11);
00688     memcpy(pDirent->FileName, UTF16EntryBuffer, 11 * sizeof(FF_T_WCHAR));
00689 #else
00690     memcpy(pDirent->FileName, EntryBuffer, 11); // Copy the filename into the Dirent object.
00691 #endif
00692 #if defined(FF_LFN_SUPPORT) && defined(FF_INCLUDE_SHORT_NAME)
00693     memcpy(pDirent->ShortName, EntryBuffer, 11);
00694     pDirent->ShortName[11] = '\0';
00695     FF_ProcessShortName(pDirent->ShortName);        // Format the shortname, for pleasant viewing.
00696 
00697 #endif
00698     FF_ProcessShortName(pDirent->FileName);     // Format the shortname, for pleasant viewing.
00699 
00700 #ifdef FF_HASH_TABLE_SUPPORT
00701 /*#if FF_HASH_FUNCTION == CRC16
00702     FF_AddDirentHash(pIoman, pDirent->DirCluster, (FF_T_UINT32)FF_GetCRC16((FF_T_UINT8 *) pDirent->FileName, strlen(pDirent->FileName)));
00703 #elif FF_HASH_FUNCTION == CRC8
00704     FF_AddDirentHash(pIoman, pDirent->DirCluster, (FF_T_UINT32)FF_GetCRC8((FF_T_UINT8 *) pDirent->FileName, strlen(pDirent->FileName)));
00705 #endif*/
00706 #else
00707     pIoman = NULL;  // Silence a compiler warning, about not referencing pIoman.
00708 #endif
00709 
00710 #ifdef FF_UNICODE_SUPPORT
00711     FF_tolower(pDirent->FileName, (FF_T_UINT32)wcslen(pDirent->FileName));
00712 #else
00713     FF_tolower(pDirent->FileName, (FF_T_UINT32)strlen(pDirent->FileName));
00714 #endif
00715 
00716     // Get the item's Cluster address.
00717     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH));
00718     pDirent->ObjectCluster = (FF_T_UINT32) (myShort << 16);
00719     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW));
00720     pDirent->ObjectCluster |= myShort;
00721 #ifdef FF_TIME_SUPPORT
00722     // Get the creation Time & Date
00723     FF_GetTime(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_CREATE_TIME);
00724     FF_GetDate(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_CREATE_DATE);
00725     // Get the modified Time & Date
00726     FF_GetTime(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME);
00727     FF_GetDate(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE);
00728     // Get the last accessed Date.
00729     FF_GetDate(&pDirent->AccessedTime, EntryBuffer, FF_FAT_DIRENT_LASTACC_DATE);
00730     pDirent->AccessedTime.Hour      = 0;
00731     pDirent->AccessedTime.Minute    = 0;
00732     pDirent->AccessedTime.Second    = 0;
00733 #endif
00734     // Get the filesize.
00735     pDirent->Filesize = FF_getLong(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE));
00736     // Get the attribute.
00737     pDirent->Attrib = FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB));
00738 }
00739 
00740 /*
00741     Initialises a context object for FF_FetchEntryWithContext()
00742 */
00743 FF_ERROR FF_InitEntryFetch(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster, FF_FETCH_CONTEXT *pContext) {
00744     
00745     FF_ERROR Error;
00746 
00747     memset(pContext, 0, sizeof(FF_FETCH_CONTEXT));
00748 
00749     pContext->ulChainLength         = FF_GetChainLength(pIoman, ulDirCluster, NULL, &Error);    // Get the total length of the chain.
00750     if(Error) {
00751         return Error;
00752     }
00753     pContext->ulDirCluster          = ulDirCluster;
00754     pContext->ulCurrentClusterLCN   = ulDirCluster;
00755     pContext->ulCurrentClusterNum   = 0;
00756     pContext->ulCurrentEntry        = 0;
00757 
00758     if(pIoman->pPartition->Type != FF_T_FAT32) {
00759         // Handle Root Dirs that don't have cluster chains!
00760         if(pContext->ulDirCluster == pIoman->pPartition->RootDirCluster) {
00761             // This is a RootDIR, special consideration needs to be made, because it doesn't have a Cluster chain!
00762             pContext->ulChainLength = pIoman->pPartition->RootDirSectors / pIoman->pPartition->SectorsPerCluster;
00763             if(!pContext->ulChainLength) {      // Some media has RootDirSectors < SectorsPerCluster. This is wrong, as it should be atleast 1 cluster!
00764                 pContext->ulChainLength = 1;
00765             }
00766         }
00767     }
00768 
00769     return FF_ERR_NONE;
00770 }
00771 
00772 void FF_CleanupEntryFetch(FF_IOMAN *pIoman, FF_FETCH_CONTEXT *pContext) {
00773     if(pContext->pBuffer) {
00774         FF_ReleaseBuffer(pIoman, pContext->pBuffer);
00775         pContext->pBuffer = NULL;
00776     }
00777 }
00778 
00779 FF_ERROR FF_FetchEntryWithContext(FF_IOMAN *pIoman, FF_T_UINT32 ulEntry, FF_FETCH_CONTEXT *pContext, FF_T_UINT8 *pEntryBuffer) {
00780     
00781     FF_T_UINT32 ulItemLBA;
00782     FF_T_UINT32 ulRelItem;
00783     FF_T_UINT32 ulClusterNum;
00784     FF_ERROR    Error;
00785 
00786     ulClusterNum                    = FF_getClusterChainNumber(pIoman, ulEntry, (FF_T_UINT16)32);
00787     ulRelItem                       = FF_getMinorBlockEntry     (pIoman, ulEntry, (FF_T_UINT16)32);
00788 
00789     if(ulClusterNum != pContext->ulCurrentClusterNum) {
00790         // Traverse the fat gently!
00791         if(ulClusterNum > pContext->ulCurrentClusterNum) {
00792             pContext->ulCurrentClusterLCN = FF_TraverseFAT(pIoman, pContext->ulCurrentClusterLCN, (ulClusterNum - pContext->ulCurrentClusterNum), &Error);
00793             if(Error) {
00794                 return Error;
00795             }
00796         } else {
00797             pContext->ulCurrentClusterLCN = FF_TraverseFAT(pIoman, pContext->ulDirCluster, ulClusterNum, &Error);
00798             if(Error) {
00799                 return Error;
00800             }
00801         }
00802         pContext->ulCurrentClusterNum = ulClusterNum;
00803     }
00804 
00805     if(pIoman->pPartition->Type != FF_T_FAT32) {
00806         // Handle Root Dirs that don't have cluster chains!
00807         if(pContext->ulDirCluster == pIoman->pPartition->RootDirCluster) {
00808             // This is a RootDIR, special consideration needs to be made, because it doesn't have a Cluster chain!
00809             pContext->ulCurrentClusterLCN = pContext->ulDirCluster;
00810             ulClusterNum = 0;
00811             if(ulEntry > ((pIoman->pPartition->RootDirSectors * pIoman->pPartition->BlkSize) / 32)) {
00812                 return FF_ERR_DIR_END_OF_DIR;
00813             }
00814         }
00815     }
00816 
00817     if((ulClusterNum + 1) > pContext->ulChainLength) {
00818         return FF_ERR_DIR_END_OF_DIR;   // End of Dir was reached!
00819     }
00820 
00821     ulItemLBA = FF_Cluster2LBA  (pIoman, pContext->ulCurrentClusterLCN) + FF_getMajorBlockNumber(pIoman, ulEntry, (FF_T_UINT16)32);
00822     ulItemLBA = FF_getRealLBA   (pIoman, ulItemLBA) + FF_getMinorBlockNumber(pIoman, ulRelItem, (FF_T_UINT16)32);
00823 
00824     if(!pContext->pBuffer || (pContext->pBuffer->Sector != ulItemLBA)) {
00825         if(pContext->pBuffer) {
00826             FF_ReleaseBuffer(pIoman, pContext->pBuffer);
00827         }
00828         pContext->pBuffer = FF_GetBuffer(pIoman, ulItemLBA, FF_MODE_READ);
00829         if(!pContext->pBuffer) {
00830             return FF_ERR_DEVICE_DRIVER_FAILED;
00831         }
00832     }
00833     
00834     if (pEntryBuffer) { // HT Because it might be called with NULL
00835         memcpy(pEntryBuffer, (pContext->pBuffer->pBuffer + (ulRelItem*32)), 32);
00836     }
00837      
00838     return FF_ERR_NONE;
00839 }
00840 
00841 
00842 FF_ERROR FF_PushEntryWithContext(FF_IOMAN *pIoman, FF_T_UINT32 ulEntry, FF_FETCH_CONTEXT *pContext, FF_T_UINT8 *pEntryBuffer) {
00843     FF_T_UINT32 ulItemLBA;
00844     FF_T_UINT32 ulRelItem;
00845     FF_T_UINT32 ulClusterNum;
00846     FF_ERROR    Error;
00847 
00848     ulClusterNum                    = FF_getClusterChainNumber(pIoman, ulEntry, (FF_T_UINT16)32);
00849     ulRelItem                       = FF_getMinorBlockEntry     (pIoman, ulEntry, (FF_T_UINT16)32);
00850 
00851     if(ulClusterNum != pContext->ulCurrentClusterNum) {
00852         // Traverse the fat gently!
00853         if(ulClusterNum > pContext->ulCurrentClusterNum) {
00854             pContext->ulCurrentClusterLCN = FF_TraverseFAT(pIoman, pContext->ulCurrentClusterLCN, (ulClusterNum - pContext->ulCurrentClusterNum), &Error);
00855             if(Error) {
00856                 return Error;
00857             }
00858         } else {
00859             pContext->ulCurrentClusterLCN = FF_TraverseFAT(pIoman, pContext->ulDirCluster, ulClusterNum, &Error);
00860             if(Error) {
00861                 return Error;
00862             }
00863         }
00864         pContext->ulCurrentClusterNum = ulClusterNum;
00865     }
00866 
00867     if(pIoman->pPartition->Type != FF_T_FAT32) {
00868         // Handle Root Dirs that don't have cluster chains!
00869         if(pContext->ulDirCluster == pIoman->pPartition->RootDirCluster) {
00870             // This is a RootDIR, special consideration needs to be made, because it doesn't have a Cluster chain!
00871             pContext->ulCurrentClusterLCN = pContext->ulDirCluster;
00872             ulClusterNum = 0;
00873             if(ulEntry > ((pIoman->pPartition->RootDirSectors * pIoman->pPartition->BlkSize) / 32)) {
00874                 return FF_ERR_DIR_END_OF_DIR;
00875             }
00876         }
00877     }
00878 
00879     if((ulClusterNum + 1) > pContext->ulChainLength) {
00880         return FF_ERR_DIR_END_OF_DIR;   // End of Dir was reached!
00881     }
00882 
00883     ulItemLBA = FF_Cluster2LBA  (pIoman, pContext->ulCurrentClusterLCN) + FF_getMajorBlockNumber(pIoman, ulEntry, (FF_T_UINT16)32);
00884     ulItemLBA = FF_getRealLBA   (pIoman, ulItemLBA) + FF_getMinorBlockNumber(pIoman, ulRelItem, (FF_T_UINT16)32);
00885 
00886     if(!pContext->pBuffer || (pContext->pBuffer->Sector != ulItemLBA)) {
00887         if(pContext->pBuffer) {
00888             FF_ReleaseBuffer(pIoman, pContext->pBuffer);
00889         }
00890         pContext->pBuffer = FF_GetBuffer(pIoman, ulItemLBA, FF_MODE_READ);
00891         if(!pContext->pBuffer) {
00892             return FF_ERR_DEVICE_DRIVER_FAILED;
00893         }
00894     }
00895 
00896     memcpy((pContext->pBuffer->pBuffer + (ulRelItem*32)), pEntryBuffer, 32);
00897     pContext->pBuffer->Mode = FF_MODE_WRITE;
00898     pContext->pBuffer->Modified = FF_TRUE;
00899      
00900     return FF_ERR_NONE;
00901 }
00902 
00903 
00907 FF_ERROR FF_GetEntry(FF_IOMAN *pIoman, FF_T_UINT16 nEntry, FF_T_UINT32 DirCluster, FF_DIRENT *pDirent) {
00908     FF_T_UINT8          EntryBuffer[32];
00909     FF_T_UINT8          numLFNs;
00910     FF_FETCH_CONTEXT    FetchContext;
00911     FF_ERROR            Error;
00912 
00913     Error = FF_InitEntryFetch(pIoman, DirCluster, &FetchContext);
00914     if(Error) {
00915         return Error;
00916     }
00917     
00918     Error = FF_FetchEntryWithContext(pIoman, nEntry, &FetchContext, EntryBuffer);
00919     if(Error) {
00920         FF_CleanupEntryFetch(pIoman, &FetchContext);
00921         return Error;
00922     }
00923     if(EntryBuffer[0] != 0xE5) {
00924         if(FF_isEndOfDir(EntryBuffer)){
00925             FF_CleanupEntryFetch(pIoman, &FetchContext);
00926             return FF_ERR_DIR_END_OF_DIR;
00927         }
00928         
00929         pDirent->Attrib = FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB));
00930         
00931         if((pDirent->Attrib & FF_FAT_ATTR_LFN) == FF_FAT_ATTR_LFN) {
00932             // LFN Processing
00933             numLFNs = (FF_T_UINT8)(EntryBuffer[0] & ~0x40);
00934     #ifdef FF_LFN_SUPPORT
00935             Error = FF_PopulateLongDirent(pIoman, pDirent, nEntry, &FetchContext);
00936             FF_CleanupEntryFetch(pIoman, &FetchContext);
00937             if(Error) {
00938                 return Error;
00939             }
00940             return FF_ERR_NONE;
00941     #else 
00942             pDirent->CurrentItem += (numLFNs - 1);
00943     #endif
00944         } else if((pDirent->Attrib & FF_FAT_ATTR_VOLID) == FF_FAT_ATTR_VOLID) {
00945             // Do Nothing
00946         
00947         } else {
00948             FF_PopulateShortDirent(pIoman, pDirent, EntryBuffer);
00949             pDirent->CurrentItem += 1;
00950             FF_CleanupEntryFetch(pIoman, &FetchContext);
00951             return 0;
00952         }
00953     }
00954 
00955     FF_CleanupEntryFetch(pIoman, &FetchContext);
00956     return FF_ERR_NONE;
00957 }
00958 
00959 FF_T_BOOL FF_isEndOfDir(FF_T_UINT8 *EntryBuffer) {
00960     if(EntryBuffer[0] == 0x00) {
00961         return FF_TRUE;
00962     }
00963     return FF_FALSE;
00964 }
00965 
00966 #ifdef FF_HASH_CACHE
00967 FF_ERROR FF_AddDirentHash(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster, FF_T_UINT32 ulHash) {
00968     FF_T_UINT32 i;
00969     FF_HASH_TABLE pHash = NULL;
00970     for(i = 0; i < FF_HASH_CACHE_DEPTH; i++) {
00971         if(pIoman->HashCache[i].ulDirCluster == ulDirCluster) {
00972             pHash = pIoman->HashCache[i].pHashTable;
00973             break;
00974         }
00975     }
00976 
00977     if(pHash) {
00978         FF_SetHash(pHash, ulHash);
00979     }
00980 
00981     return FF_ERR_NONE;
00982 }
00983 
00984 FF_T_BOOL FF_CheckDirentHash(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster, FF_T_UINT32 ulHash) {
00985     FF_T_UINT32 i;
00986     FF_HASH_TABLE pHash = NULL;
00987     for(i = 0; i < FF_HASH_CACHE_DEPTH; i++) {
00988         if(pIoman->HashCache[i].ulDirCluster == ulDirCluster) {
00989             pHash = pIoman->HashCache[i].pHashTable;
00990             break;
00991         }
00992     }
00993 
00994     if(pHash) {
00995         return FF_isHashSet(pHash, ulHash);
00996     }
00997 
00998     return FF_FALSE;
00999 }
01000 
01001 FF_T_BOOL FF_DirHashed(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster) {
01002     FF_T_UINT32 i;
01003     for(i = 0; i < FF_HASH_CACHE_DEPTH; i++) {
01004         if(pIoman->HashCache[i].ulDirCluster == ulDirCluster) {
01005             return FF_TRUE;
01006         }
01007     }
01008 
01009     return FF_FALSE;
01010 }
01011 
01012 FF_ERROR FF_HashDir(FF_IOMAN *pIoman, FF_T_UINT32 ulDirCluster) {
01013     // Find most suitable Hash Table to replace!
01014     FF_T_UINT32         i;
01015     FF_HASHCACHE        *pHashCache = NULL;
01016     FF_FETCH_CONTEXT    FetchContext;
01017     FF_T_UINT8          EntryBuffer[32], ucAttrib;
01018     FF_T_UINT32         ulHash;
01019 
01020     if(FF_DirHashed(pIoman, ulDirCluster)) {
01021         return FF_ERR_NONE;         // Don't wastefully re-hash a dir!
01022     }
01023 
01024     //printf("----- Hashing Directory\n");
01025 
01026     for(i = 0; i < FF_HASH_CACHE_DEPTH; i++) {
01027         if(!pIoman->HashCache[i].ulNumHandles) {
01028             if(!pHashCache) {
01029                 pHashCache = &pIoman->HashCache[i];
01030             } else {
01031                 if((pIoman->HashCache[i].ulMisses > pHashCache->ulMisses)) {
01032                     pHashCache = &pIoman->HashCache[i];
01033                 }
01034             }
01035         }
01036     }
01037 
01038     if(pHashCache) {
01039         // Clear the hash table!
01040         FF_ClearHashTable(pHashCache->pHashTable);
01041         pHashCache->ulDirCluster = ulDirCluster;
01042         pHashCache->ulMisses = 0;
01043         
01044         // Hash the directory!
01045         
01046         FF_InitEntryFetch(pIoman, ulDirCluster, &FetchContext);
01047 
01048         for(i = 0; i < 0xFFFF; i++) {
01049             if(FF_FetchEntryWithContext(pIoman, i, &FetchContext, EntryBuffer)) {
01050                 break;  // HT addition
01051             }
01052             ucAttrib = FF_getChar(EntryBuffer, FF_FAT_DIRENT_ATTRIB);
01053             if(FF_getChar(EntryBuffer, 0x00) != 0xE5) {
01054                 if(ucAttrib != FF_FAT_ATTR_LFN) {
01055                     FF_ProcessShortName((FF_T_INT8 *)EntryBuffer);
01056                     if(FF_isEndOfDir(EntryBuffer)) {
01057                         // HT uncommented
01058                         FF_CleanupEntryFetch(pIoman, &FetchContext);
01059                         return FF_ERR_NONE;
01060                     }
01061                     
01062                     // Generate the Hash
01063 #if FF_HASH_FUNCTION == CRC16
01064                     ulHash = FF_GetCRC16(EntryBuffer, strlen((const FF_T_INT8 *) EntryBuffer));
01065 #elif FF_HASH_FUNCTION == CRC8
01066                     ulHash = FF_GetCRC8(EntryBuffer, strlen((const FF_T_INT8 *) EntryBuffer));
01067 #endif
01068                     FF_SetHash(pHashCache->pHashTable, ulHash);
01069                     
01070                 }
01071             }
01072         }
01073 
01074         FF_CleanupEntryFetch(pIoman, &FetchContext);
01075 
01076         return FF_ERR_NONE;
01077     }
01078 
01079     return -1;
01080 }
01081 
01082 /*void FF_SetDirHashed(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster) {
01083     int i;
01084     for(i = 0; i < FF_PATH_CACHE_DEPTH; i++) {
01085         if(pIoman->pPartition->PathCache[i].DirCluster == DirCluster) {
01086             pIoman->pPartition->PathCache[i].bHashed = FF_TRUE;
01087             return;
01088         }
01089     }
01090 }*/
01091 #endif
01092 
01093 FF_ERROR FF_PopulateLongDirent(FF_IOMAN *pIoman, FF_DIRENT *pDirent, FF_T_UINT16 nEntry, FF_FETCH_CONTEXT *pFetchContext) {
01094     // First get the entire name as UTF-16 from the LFN's.
01095     // Then transform into the API's native string format.
01096 
01097     FF_ERROR    Error;
01098     FF_T_UINT   uiNumLFNs;
01099     FF_T_UINT   uiLfnLength = 0;
01100 #ifdef FF_UNICODE_UTF8_SUPPORT
01101     FF_T_UINT   i,y;
01102 //  FF_T_SINT32 slRetVal;
01103     FF_T_UINT16 nLfnBegin;
01104     FF_T_UINT16 usUtf8Len = 0;
01105 #endif
01106     FF_T_UINT16 myShort;
01107     FF_T_UINT8  ucCheckSum;
01108 
01109     FF_T_UINT8  EntryBuffer[32];
01110     //FF_T_UINT16   UTF16Name[FF_MAX_FILENAME];
01111 
01112 #ifdef FF_UNICODE_SUPPORT
01113     FF_T_WCHAR  WCEntryBuffer[32];
01114     FF_T_WCHAR  ShortName[13];
01115 #else
01116     FF_T_INT8   ShortName[13];
01117 #endif
01118 
01119     Error = FF_FetchEntryWithContext(pIoman, nEntry++, pFetchContext, EntryBuffer);
01120     if(Error) {
01121         return Error;
01122     }
01123 
01124     uiNumLFNs = (FF_T_UINT)(EntryBuffer[0] & ~0x40);
01125     ucCheckSum = FF_getChar(EntryBuffer, FF_FAT_LFN_CHECKSUM);
01126 
01127 #ifdef FF_UNICODE_SUPPORT   // UTF-16 Can simply get segments of the UTF-16 sequence going forward
01128                             // in the dirents. (I.e. reversed order).
01129 
01130     while(uiNumLFNs) {  // Avoid stack intensive use of a UTF-16 buffer. Stream direct to FileName dirent field in correct format.
01131 
01132         // memcopy direct!-UTF-16 support
01133         memcpy(pDirent->FileName + ((uiNumLFNs - 1) * 13) + 0,  &EntryBuffer[FF_FAT_LFN_NAME_1], 10);
01134         memcpy(pDirent->FileName + ((uiNumLFNs - 1) * 13) + 5,  &EntryBuffer[FF_FAT_LFN_NAME_2], 12);
01135         memcpy(pDirent->FileName + ((uiNumLFNs - 1) * 13) + 11, &EntryBuffer[FF_FAT_LFN_NAME_3], 4);
01136 
01137 
01138         uiLfnLength += 13;
01139 
01140         Error = FF_FetchEntryWithContext(pIoman, nEntry++, pFetchContext, EntryBuffer);
01141         if(Error) {
01142             return Error;
01143         }
01144         uiNumLFNs--;
01145     }
01146 
01147     pDirent->FileName[uiLfnLength] = '\0';
01148 #endif
01149 
01150 #ifdef FF_UNICODE_UTF8_SUPPORT
01151     // UTF-8 Sequence, we can only convert this from the beginning, must receive entries in reverse.
01152     nLfnBegin = nEntry - 1;
01153 
01154     for(i = 0; i < uiNumLFNs; i++) {
01155         Error = FF_FetchEntryWithContext(pIoman, (nLfnBegin + (uiNumLFNs - 1) - i), pFetchContext, EntryBuffer);
01156         if(Error) {
01157             return Error;
01158         }
01159         
01160         // Now have the first part of the UTF-16 sequence. Stream into a UTF-8 sequence.
01161         for(y = 0; y < 5; y++) {
01162             Error = FF_Utf16ctoUtf8c((FF_T_UINT8 *) &pDirent->FileName[usUtf8Len], (FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_1 + (y*2)], sizeof(pDirent->FileName) - usUtf8Len);
01163             if(Error > 0) {
01164                 usUtf8Len += (FF_T_UINT16) Error;
01165             }
01166         }
01167 
01168         for(y = 0; y < 6; y++) {
01169             Error = FF_Utf16ctoUtf8c((FF_T_UINT8 *) &pDirent->FileName[usUtf8Len], (FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_2 + (y*2)], sizeof(pDirent->FileName) - usUtf8Len);
01170             if(Error > 0) {
01171                 usUtf8Len += (FF_T_UINT16) Error;
01172             }
01173         }
01174 
01175         for(y = 0; y < 2; y++) {
01176             Error = FF_Utf16ctoUtf8c((FF_T_UINT8 *) &pDirent->FileName[usUtf8Len], (FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_3 + (y*2)], sizeof(pDirent->FileName) - usUtf8Len);
01177             if(Error > 0) {
01178                 usUtf8Len += (FF_T_UINT16) Error;
01179             }
01180         }
01181         nEntry++;
01182     }
01183 
01184     pDirent->FileName[usUtf8Len] = '\0';
01185     
01186     // Put Entry context to correct position.
01187     Error = FF_FetchEntryWithContext(pIoman, nEntry-1, pFetchContext, EntryBuffer);
01188     if(Error) {
01189         return Error;
01190     }
01191 
01192 #endif
01193 
01194 #ifndef FF_UNICODE_SUPPORT
01195 #ifndef FF_UNICODE_UTF8_SUPPORT // No Unicode, simple ASCII.
01196     while(uiNumLFNs) {  // Avoid stack intensive use of a UTF-16 buffer. Stream direct to FileName dirent field in correct format.
01197         
01198         for(i = 0; i < 5; i++) {
01199             pDirent->FileName[((uiNumLFNs - 1) * 13) + i] = EntryBuffer[FF_FAT_LFN_NAME_1 + (i*2)];
01200         }
01201 
01202         for(i = 0; i < 6; i++) {
01203             pDirent->FileName[((uiNumLFNs - 1) * 13) + i + 5] = EntryBuffer[FF_FAT_LFN_NAME_2 + (i*2)];
01204         }
01205 
01206         for(i = 0; i < 2; i++) {
01207             pDirent->FileName[((uiNumLFNs - 1) * 13) + i + 11] = EntryBuffer[FF_FAT_LFN_NAME_3 + (i*2)];
01208         }
01209 
01210         uiLfnLength += 13;
01211 
01212         Error = FF_FetchEntryWithContext(pIoman, nEntry++, pFetchContext, EntryBuffer);
01213         if(Error) {
01214             return Error;
01215         }
01216         uiNumLFNs--;
01217     }
01218 
01219     pDirent->FileName[uiLfnLength] = '\0';
01220 
01221     
01222 #endif
01223 #endif
01224     // Process the Shortname. -- LFN Transformation is now complete.
01225     // Process the ShortName Entry
01226 
01227     // if SHORTNAMES must be included, simple byte copy into shortname buffer.
01228 #if defined(FF_LFN_SUPPORT) && defined(FF_INCLUDE_SHORT_NAME)
01229     memcpy(pDirent->ShortName, EntryBuffer, 11);
01230     pDirent->ShortName[11] = '\0';
01231     FF_ProcessShortName(pDirent->ShortName);
01232 #endif
01233 
01234 #ifdef FF_UNICODE_SUPPORT
01235     FF_cstrntowcs(WCEntryBuffer, (FF_T_INT8 *) EntryBuffer, 32);
01236     memcpy(ShortName, WCEntryBuffer, 11 * sizeof(FF_T_WCHAR));
01237 #else
01238     memcpy(ShortName, EntryBuffer, 11);
01239 #endif
01240     FF_ProcessShortName(ShortName);
01241     if(ucCheckSum != FF_CreateChkSum(EntryBuffer)) {
01242 #ifdef FF_UNICODE_SUPPORT
01243         wcscpy(pDirent->FileName, ShortName);
01244 #else
01245         strcpy(pDirent->FileName, ShortName);
01246 #endif
01247     }
01248 
01249     // Finally fill in the other details
01250     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH));
01251     pDirent->ObjectCluster = (FF_T_UINT32) (myShort << 16);
01252     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW));
01253     pDirent->ObjectCluster |= myShort;
01254 
01255 #ifdef FF_TIME_SUPPORT
01256     // Get the creation Time & Date
01257     FF_GetTime(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_CREATE_TIME);
01258     FF_GetDate(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_CREATE_DATE);
01259     // Get the modified Time & Date
01260     FF_GetTime(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME);
01261     FF_GetDate(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE);
01262     // Get the last accessed Date.
01263     FF_GetDate(&pDirent->AccessedTime, EntryBuffer, FF_FAT_DIRENT_LASTACC_DATE);
01264     pDirent->AccessedTime.Hour      = 0;
01265     pDirent->AccessedTime.Minute    = 0;
01266     pDirent->AccessedTime.Second    = 0;
01267 #endif
01268 
01269     // Get the filesize.
01270     pDirent->Filesize = FF_getLong(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE));
01271     // Get the attribute.
01272     pDirent->Attrib = FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB));
01273     
01274     pDirent->CurrentItem = nEntry;
01275     //return x;
01276     return FF_ERR_NONE;
01277 }
01278 
01279 /*
01280 FF_ERROR FF_PopulateLongDirent(FF_IOMAN *pIoman, FF_DIRENT *pDirent, FF_T_UINT16 nEntry, FF_FETCH_CONTEXT *pFetchContext) {
01281     FF_T_UINT8  EntryBuffer[32];
01282 #ifdef FF_UNICODE_SUPPORT
01283     FF_T_WCHAR  UTF16EntryBuffer[32];
01284     FF_T_WCHAR  ShortName[13];
01285 #if WCHAR_MAX > 0xFFFF
01286     FF_T_UINT16 i,y;
01287 #endif
01288 #else
01289     FF_T_INT8   ShortName[13];
01290 #ifdef FF_UNICODE_UTF8_SUPPORT
01291     FF_T_SINT32 i, y;
01292 #else
01293     FF_T_UINT16 i, y;
01294 #endif
01295 #endif
01296 
01297 #ifdef FF_UNICODE_UTF8_SUPPORT
01298     FF_T_UINT16 UTF16Name[FF_MAX_FILENAME]; // Read in the entire UTF-16 name into this buffer.
01299     FF_T_UINT16 *UTF16cptr;
01300 #endif
01301     FF_T_UINT8 numLFNs;
01302     FF_T_UINT8 x;
01303     FF_T_UINT8 CheckSum = 0;
01304 
01305     FF_T_UINT16 lenlfn = 0;
01306     FF_T_UINT16 myShort;
01307     FF_ERROR    Error;
01308     
01309     Error = FF_FetchEntryWithContext(pIoman, nEntry++, pFetchContext, EntryBuffer);
01310     if(Error) {
01311         return Error;
01312     }
01313 
01314     numLFNs = (FF_T_UINT8)(EntryBuffer[0] & ~0x40);
01315     // Handle the name
01316     CheckSum = FF_getChar(EntryBuffer, FF_FAT_LFN_CHECKSUM);
01317 
01318     x = numLFNs;
01319     while(numLFNs) {
01320         if(numLFNs > 1) {
01321             numLFNs = numLFNs;
01322         }
01323 
01324 #ifdef FF_UNICODE_SUPPORT
01325         // Simply fill the FileName buffer with UTF-16 Filename!
01326 #if WCHAR_MAX <= 0xFFFF // System works in UTF-16 so we can trust it if we just copy the UTF-16 strings directly.
01327         memcpy(pDirent->FileName + ((numLFNs - 1) * 13) + 0,    &EntryBuffer[FF_FAT_LFN_NAME_1], (5 * 2));
01328         memcpy(pDirent->FileName + ((numLFNs - 1) * 13) + 5,    &EntryBuffer[FF_FAT_LFN_NAME_2], (6 * 2));
01329         memcpy(pDirent->FileName + ((numLFNs - 1) * 13) + 11,   &EntryBuffer[FF_FAT_LFN_NAME_3], (2 * 2));
01330         lenlfn += 13;
01331 #else
01332         for(i = 0, y = 0; i < 5; i++, y += 2) {
01333             FF_Utf16ctoUtf32c((FF_T_UINT32 *)&pDirent->FileName[i + ((numLFNs - 1) * 13)], (FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_1 + y]);
01334             //pDirent->FileName[i + ((numLFNs - 1) * 13)] = (FF_T_WCHAR) ((FF_T_WCHAR) EntryBuffer[FF_FAT_LFN_NAME_1 + y] | ((FF_T_WCHAR) EntryBuffer[FF_FAT_LFN_NAME_1 + y + 1] >> 8));
01335             lenlfn++;
01336         }
01337         for(i = 0, y = 0; i < 6; i++, y += 2) {
01338             FF_Utf16ctoUtf32c((FF_T_UINT32 *)&pDirent->FileName[i + ((numLFNs - 1) * 13) + 5], (FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_2 + y]);
01339             //pDirent->FileName[i + ((numLFNs - 1) * 13) + 5] = (FF_T_WCHAR) ((FF_T_WCHAR) EntryBuffer[FF_FAT_LFN_NAME_2 + y] | ((FF_T_WCHAR) EntryBuffer[FF_FAT_LFN_NAME_2 + y + 1] >> 8));
01340             lenlfn++;
01341         }
01342         for(i = 0, y = 0; i < 2; i++, y += 2) {
01343             FF_Utf16ctoUtf32c((FF_T_UINT32 *)&pDirent->FileName[i + ((numLFNs - 1) * 13) + 11], (FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_3 + y]);
01344             //pDirent->FileName[i + ((numLFNs - 1) * 13) + 11] = (FF_T_WCHAR) ((FF_T_WCHAR) EntryBuffer[FF_FAT_LFN_NAME_3 + y] | ((FF_T_WCHAR)EntryBuffer[FF_FAT_LFN_NAME_3 + y + 1] >> 8));
01345             lenlfn++;
01346         }
01347 #endif
01348         // Copy each part of the LFNS
01349 #else
01350 #ifdef FF_UNICODE_UTF8_SUPPORT
01351         memcpy(UTF16Name + ((numLFNs - 1) * 13) + 0,    &EntryBuffer[FF_FAT_LFN_NAME_1], (5 * 2));
01352         memcpy(UTF16Name + ((numLFNs - 1) * 13) + 5,    &EntryBuffer[FF_FAT_LFN_NAME_2], (6 * 2));
01353         memcpy(UTF16Name + ((numLFNs - 1) * 13) + 11,   &EntryBuffer[FF_FAT_LFN_NAME_3], (2 * 2));
01354         lenlfn += 13;
01355 #else
01356         // Attempts to pull ASCII from UTF-8 encoding. 
01357         for(i = 0, y = 0; i < 5; i++, y += 2) {
01358             pDirent->FileName[i + ((numLFNs - 1) * 13)] = EntryBuffer[FF_FAT_LFN_NAME_1 + y];
01359             lenlfn++;
01360         }
01361 
01362         for(i = 0, y = 0; i < 6; i++, y += 2) {
01363             pDirent->FileName[i + ((numLFNs - 1) * 13) + 5] = EntryBuffer[FF_FAT_LFN_NAME_2 + y];
01364             lenlfn++;
01365         }
01366 
01367         for(i = 0, y = 0; i < 2; i++, y += 2) {
01368             pDirent->FileName[i + ((numLFNs - 1) * 13) + 11] = EntryBuffer[FF_FAT_LFN_NAME_3 + y];
01369             lenlfn++;
01370         }
01371 #endif
01372 #endif
01373 
01374         Error = FF_FetchEntryWithContext(pIoman, nEntry++, pFetchContext, EntryBuffer);
01375         if(Error) {
01376             return Error;
01377         }
01378         numLFNs--;
01379     }
01380 
01381 #ifdef FF_UNICODE_UTF8_SUPPORT
01382     UTF16cptr = UTF16Name;
01383     UTF16Name[lenlfn] = '\0';
01384     i = 0;  // Keep tabs of the current char position in the UTF-8 sequence.
01385     while(*UTF16cptr) {
01386         y = FF_Utf16ctoUtf8c((FF_T_UINT8 *)&pDirent->FileName[i], UTF16cptr, (FF_MAX_FILENAME - i));
01387         i += y;
01388         if(FF_GetUtf16SequenceLen(*UTF16cptr++) == 2) { // IF this is a surrogate, then bump the UTF16 Pointer.
01389             UTF16cptr++;
01390         }
01391     }
01392     pDirent->FileName[i] = '\0';
01393 #else
01394     pDirent->FileName[lenlfn] = '\0';
01395 #endif
01396     
01397     // Process the ShortName Entry
01398 #ifdef FF_UNICODE_SUPPORT
01399     FF_cstrntowcs(UTF16EntryBuffer, (FF_T_INT8 *) EntryBuffer, 32);
01400     memcpy(ShortName, UTF16EntryBuffer, 11 * sizeof(FF_T_WCHAR));
01401 #else
01402     memcpy(ShortName, EntryBuffer, 11);
01403 #endif
01404     if(CheckSum != FF_CreateChkSum(EntryBuffer)) {
01405         FF_ProcessShortName(ShortName);
01406 #ifdef FF_UNICODE_SUPPORT
01407         wcscpy(pDirent->FileName, ShortName);
01408 #else
01409         strcpy(pDirent->FileName, ShortName);
01410 #endif
01411     } else {
01412         FF_ProcessShortName(ShortName);
01413     }
01414 
01415 #ifdef FF_HASH_TABLE_SUPPORT*/
01416 /*#if FF_HASH_FUNCTION == CRC16
01417     FF_AddDirentHash(pIoman, pFetchContext->ulDirCluster, (FF_T_UINT32)FF_GetCRC16((FF_T_UINT8 *) ShortName, strlen(ShortName)));
01418 #elif FF_HASH_FUNCTION == CRC8
01419     FF_AddDirentHash(pIoman, DirCluster, (FF_T_UINT32)FF_GetCRC8((FF_T_UINT8 *) ShortName, strlen(ShortName)));
01420 #endif*//*
01421 #endif
01422     
01423     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH));
01424     pDirent->ObjectCluster = (FF_T_UINT32) (myShort << 16);
01425     myShort = FF_getShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW));
01426     pDirent->ObjectCluster |= myShort;
01427 
01428 #ifdef FF_TIME_SUPPORT
01429     // Get the creation Time & Date
01430     FF_GetTime(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_CREATE_TIME);
01431     FF_GetDate(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_CREATE_DATE);
01432     // Get the modified Time & Date
01433     FF_GetTime(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME);
01434     FF_GetDate(&pDirent->CreateTime, EntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE);
01435     // Get the last accessed Date.
01436     FF_GetDate(&pDirent->AccessedTime, EntryBuffer, FF_FAT_DIRENT_LASTACC_DATE);
01437     pDirent->AccessedTime.Hour      = 0;
01438     pDirent->AccessedTime.Minute    = 0;
01439     pDirent->AccessedTime.Second    = 0;
01440 #endif
01441 
01442     // Get the filesize.
01443     pDirent->Filesize = FF_getLong(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE));
01444     // Get the attribute.
01445     pDirent->Attrib = FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB));
01446     
01447     pDirent->CurrentItem = nEntry;
01448     //return x;
01449     return FF_ERR_NONE;
01450 }
01451 */
01484 #ifdef FF_UNICODE_SUPPORT
01485 FF_ERROR FF_FindFirst(FF_IOMAN *pIoman, FF_DIRENT *pDirent, const FF_T_WCHAR *path) {
01486 #else
01487 FF_ERROR FF_FindFirst(FF_IOMAN *pIoman, FF_DIRENT *pDirent, const FF_T_INT8 *path) {
01488 #endif
01489 #ifdef FF_UNICODE_SUPPORT
01490     FF_T_UINT16 PathLen = (FF_T_UINT16) wcslen(path);
01491 #else
01492     FF_T_UINT16 PathLen = (FF_T_UINT16) strlen(path);
01493 #endif
01494     FF_ERROR    Error;
01495 
01496 #ifdef FF_FINDAPI_ALLOW_WILDCARDS   
01497     FF_T_UINT16 i = 0;
01498 #ifdef FF_UNICODE_SUPPORT
01499     const FF_T_WCHAR *szWildCard;   // Check for a Wild-card.
01500 #else
01501     const FF_T_INT8 *szWildCard;    // Check for a Wild-card.
01502 #endif
01503 #endif
01504 
01505     if(!pIoman) {
01506         return FF_ERR_NULL_POINTER;
01507     }
01508 
01509     // Detect a Wild-Card on the End, or Filename, as apposed to a complete path.
01510 #ifndef FF_FINDAPI_ALLOW_WILDCARDS
01511     pDirent->DirCluster = FF_FindDir(pIoman, path, PathLen);    // Get the directory cluster, if it exists.
01512 #endif
01513 
01514 #ifdef FF_FINDAPI_ALLOW_WILDCARDS
01515     pDirent->szWildCard[0] = '\0';  // WildCard blank if its not a wildCard.
01516 
01517     szWildCard = &path[PathLen - 1];
01518 
01519     if(PathLen) {
01520         while(*szWildCard != '\\' && *szWildCard != '/') {  // Open the dir of the last token.
01521             i++;
01522             szWildCard--;
01523             if(!(PathLen - i)) {
01524                 break;
01525             }
01526         }
01527     }
01528             
01529     pDirent->DirCluster = FF_FindDir(pIoman, path, PathLen - i, &Error);
01530     if(Error) {
01531         return Error;
01532     }
01533     if(pDirent->DirCluster) {
01534         // Valid Dir found, copy the wildCard to filename!
01535 #ifdef FF_UNICODE_SUPPORT
01536         wcsncpy(pDirent->szWildCard, ++szWildCard, FF_MAX_FILENAME);
01537 #else
01538         strncpy(pDirent->szWildCard, ++szWildCard, FF_MAX_FILENAME);
01539 #endif
01540     }
01541 #endif
01542 
01543     if(pDirent->DirCluster == 0) {
01544         return FF_ERR_DIR_INVALID_PATH;
01545     }
01546 
01547     // Initialise the Fetch Context
01548     Error = FF_InitEntryFetch(pIoman, pDirent->DirCluster, &pDirent->FetchContext);
01549     if(Error) {
01550         return Error;
01551     }
01552     
01553     pDirent->CurrentItem = 0;
01554 
01555     return FF_FindNext(pIoman, pDirent);
01556 }
01557 
01571 FF_ERROR FF_FindNext(FF_IOMAN *pIoman, FF_DIRENT *pDirent) {
01572     
01573     FF_ERROR    Error;
01574     FF_T_UINT8  numLFNs;
01575     FF_T_UINT8  EntryBuffer[32];
01576 
01577     if(!pIoman) {
01578         return FF_ERR_NULL_POINTER;
01579     }
01580     
01581     for(; pDirent->CurrentItem < 0xFFFF; pDirent->CurrentItem += 1) {
01582         Error = FF_FetchEntryWithContext(pIoman, pDirent->CurrentItem, &pDirent->FetchContext, EntryBuffer);
01583         if(Error) {
01584             FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01585             return Error;
01586         }
01587         if(EntryBuffer[0] != FF_FAT_DELETED) {
01588             if(FF_isEndOfDir(EntryBuffer)){
01589                 FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01590                 return FF_ERR_DIR_END_OF_DIR;
01591             }
01592             pDirent->Attrib = FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB));
01593             if((pDirent->Attrib & FF_FAT_ATTR_LFN) == FF_FAT_ATTR_LFN) {
01594                 // LFN Processing
01595                 numLFNs = (FF_T_UINT8)(EntryBuffer[0] & ~0x40);
01596                 // Get the shortname and check if it is marked deleted.
01597 #ifdef FF_LFN_SUPPORT
01598                 // Fetch the shortname, and get it's checksum, or for a deleted item with
01599                 // orphaned LFN entries.
01600                 Error = FF_FetchEntryWithContext(pIoman, (pDirent->CurrentItem + numLFNs), &pDirent->FetchContext, EntryBuffer);
01601                 if(Error) {
01602                     FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01603                     return Error;
01604                 }
01605                 
01606                 if(EntryBuffer[0] != FF_FAT_DELETED) {
01607                     Error = FF_PopulateLongDirent(pIoman, pDirent, pDirent->CurrentItem, &pDirent->FetchContext);
01608                     if(Error) {
01609                         FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01610                         return Error;
01611                     }
01612 #ifdef FF_INCLUDE_SHORT_NAME
01613                     pDirent->Attrib |= FF_FAT_ATTR_IS_LFN;
01614 #endif
01615 
01616 #ifdef FF_FINDAPI_ALLOW_WILDCARDS
01617 #ifdef FF_UNICODE_SUPPORT
01618                     if(wcscmp(pDirent->szWildCard, L"")) {
01619 #else
01620                     if(strcmp(pDirent->szWildCard, "")) {
01621 #endif
01622                         if(FF_wildcompare(pDirent->szWildCard, pDirent->FileName)) {
01623                             FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01624                             return FF_ERR_NONE;                         
01625                         }
01626                         pDirent->CurrentItem -= 1;
01627                     } else {
01628                         FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01629                         return FF_ERR_NONE;
01630                     }
01631 #else
01632                     FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01633                     return FF_ERR_NONE;
01634 #endif
01635                 }
01636 #else 
01637                 pDirent->CurrentItem += (numLFNs - 1);
01638 #endif
01639             } else if((pDirent->Attrib & FF_FAT_ATTR_VOLID) == FF_FAT_ATTR_VOLID) {
01640                 // Do Nothing
01641             
01642             } else {
01643                 FF_PopulateShortDirent(pIoman, pDirent, EntryBuffer);
01644 #if defined(FF_SHORTNAME_CASE)
01645                 // Apply NT/XP+ bits to get correct case
01646                 FF_CaseShortName(pDirent->FileName, FF_getChar(EntryBuffer, FF_FAT_CASE_OFFS));
01647 #endif
01648 #ifdef FF_FINDAPI_ALLOW_WILDCARDS
01649 #ifdef FF_UNICODE_SUPPORT
01650                 if(wcscmp(pDirent->szWildCard, L"")) {
01651 #else
01652                 if(strcmp(pDirent->szWildCard, "")) {
01653 #endif
01654                     if(FF_wildcompare(pDirent->szWildCard, pDirent->FileName)) {
01655                         FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01656                         pDirent->CurrentItem += 1;
01657                         return FF_ERR_NONE;
01658                     }
01659                 } else {
01660                     FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01661                     pDirent->CurrentItem += 1;
01662                     return FF_ERR_NONE;
01663                 }
01664 #else
01665 
01666                 FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01667                 pDirent->CurrentItem += 1;
01668                 return FF_ERR_NONE;
01669 #endif
01670             }
01671         }
01672     }
01673 
01674     FF_CleanupEntryFetch(pIoman, &pDirent->FetchContext);
01675     
01676     return FF_ERR_DIR_END_OF_DIR;
01677 }
01678 
01679 
01680 FF_T_SINT8 FF_RewindFind(FF_IOMAN *pIoman, FF_DIRENT *pDirent) {
01681     if(!pIoman) {
01682         return FF_ERR_NULL_POINTER;
01683     }
01684     pDirent->CurrentItem = 0;
01685     return 0;
01686 }
01687 
01688 /*
01689     Returns >= 0 for a free dirent entry.
01690     Returns <  0 with and Error code if anything goes wrong.
01691 */
01692 static FF_T_SINT32 FF_FindFreeDirent(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_UINT16 Sequential) {
01693 
01694     FF_T_UINT8          EntryBuffer[32];
01695     FF_T_UINT16         i = 0;
01696     FF_T_UINT16         nEntry;
01697     FF_ERROR            Error;
01698     FF_T_UINT32         DirLength;
01699     FF_FETCH_CONTEXT    FetchContext;
01700 
01701     Error = FF_InitEntryFetch(pIoman, DirCluster, &FetchContext);
01702     if(Error) {
01703         return Error;
01704     }
01705     
01706     for(nEntry = 0; nEntry < 0xFFFF; nEntry++) {
01707         Error = FF_FetchEntryWithContext(pIoman, nEntry, &FetchContext, EntryBuffer);
01708         if(Error == FF_ERR_DIR_END_OF_DIR) {
01709             
01710             Error = FF_ExtendDirectory(pIoman, DirCluster);
01711             FF_CleanupEntryFetch(pIoman, &FetchContext);
01712 
01713             if(Error) {
01714                 return Error;
01715             }
01716 
01717             return nEntry;
01718         } else {
01719             if(Error) {
01720                 FF_CleanupEntryFetch(pIoman, &FetchContext);
01721                 return Error;
01722             }
01723         }
01724         if(FF_isEndOfDir(EntryBuffer)) {    // If its the end of the Dir, then FreeDirents from here.
01725             // Check Dir is long enough!
01726             DirLength = FetchContext.ulChainLength;//FF_GetChainLength(pIoman, DirCluster, &iEndOfChain);
01727             if((nEntry + Sequential) > (FF_T_UINT16)(((pIoman->pPartition->SectorsPerCluster * pIoman->pPartition->BlkSize) * DirLength) / 32)) {
01728                 Error = FF_ExtendDirectory(pIoman, DirCluster);
01729             }
01730 
01731             FF_CleanupEntryFetch(pIoman, &FetchContext);
01732 
01733             if(Error) {
01734                 return Error;
01735             }
01736 
01737             return nEntry;
01738         }
01739         if(EntryBuffer[0] == 0xE5) {
01740             i++;
01741         } else {
01742             i = 0;
01743         }
01744 
01745         if(i == Sequential) {
01746             FF_CleanupEntryFetch(pIoman, &FetchContext);
01747             return (nEntry - (Sequential - 1));// Return the beginning entry in the sequential sequence.
01748         }
01749     }
01750     
01751     FF_CleanupEntryFetch(pIoman, &FetchContext);
01752 
01753     return FF_ERR_DIR_DIRECTORY_FULL;
01754 }
01755 
01756 
01757 
01758 
01759 FF_ERROR FF_PutEntry(FF_IOMAN *pIoman, FF_T_UINT16 Entry, FF_T_UINT32 DirCluster, FF_DIRENT *pDirent) {
01760     FF_BUFFER *pBuffer;
01761     FF_ERROR    Error;
01762     FF_T_UINT32 itemLBA;
01763     FF_T_UINT32 clusterNum      = FF_getClusterChainNumber  (pIoman, Entry, (FF_T_UINT16)32);
01764     FF_T_UINT32 relItem         = FF_getMinorBlockEntry     (pIoman, Entry, (FF_T_UINT16)32);
01765     FF_T_UINT32 clusterAddress  = FF_TraverseFAT(pIoman, DirCluster, clusterNum, &Error);
01766 
01767     if(Error) {
01768         return Error;
01769     }
01770 
01771     itemLBA = FF_Cluster2LBA(pIoman, clusterAddress)    + FF_getMajorBlockNumber(pIoman, Entry, (FF_T_UINT16)32);
01772     itemLBA = FF_getRealLBA (pIoman, itemLBA)           + FF_getMinorBlockNumber(pIoman, relItem, (FF_T_UINT16)32);
01773     
01774     pBuffer = FF_GetBuffer(pIoman, itemLBA, FF_MODE_WRITE);
01775     {
01776         if(!pBuffer) {
01777             return FF_ERR_DEVICE_DRIVER_FAILED;
01778         }
01779         // Modify the Entry!
01780         //memcpy((pBuffer->pBuffer + (32*relItem)), pDirent->FileName, 11);
01781         relItem *= 32;
01782         FF_putChar(pBuffer->pBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB + relItem), pDirent->Attrib);
01783         FF_putShort(pBuffer->pBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH + relItem), (FF_T_UINT16)(pDirent->ObjectCluster >> 16));
01784         FF_putShort(pBuffer->pBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW  + relItem), (FF_T_UINT16)(pDirent->ObjectCluster));
01785         FF_putLong(pBuffer->pBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE  + relItem), pDirent->Filesize);
01786 #ifdef FF_TIME_SUPPORT
01787     FF_PlaceDate((pBuffer->pBuffer + relItem), FF_FAT_DIRENT_LASTACC_DATE); // Last accessed date.
01788 #endif
01789     }
01790     FF_ReleaseBuffer(pIoman, pBuffer);
01791  
01792     return 0;
01793 }
01794 
01795 FF_T_BOOL FF_ValidShortChar (FF_T_INT8 Chr)
01796 {
01797     return (Chr >= 'A' && Chr <= 'Z') ||
01798 #if defined(FF_SHORTNAME_CASE)
01799         (Chr >= 'a' && Chr <= 'z') ||   // lower-case can be stored using NT/XP attribute
01800 #endif
01801         (Chr >= '0' && Chr <= '9') ||
01802         strchr ("$%-_@~`!(){}^#&", Chr) != NULL;
01803 }
01804 
01805 FF_T_BOOL FF_ValidLongChar (FF_T_INT8 Chr)
01806 {
01807     return Chr >= 0x20 && strchr ("/\\:*?\"<>|", Chr) == NULL;
01808 }
01809 
01810 #ifdef FF_UNICODE_SUPPORT
01811 FF_T_SINT8 FF_CreateShortName(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_WCHAR *ShortName, FF_T_WCHAR *LongName) {
01812 #else
01813 FF_T_SINT8 FF_CreateShortName(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_INT8 *ShortName, FF_T_INT8 *LongName) {
01814 #endif
01815     FF_T_UINT8 caseAttrib = 0;
01816 #if defined(FF_SHORTNAME_CASE)
01817     FF_T_UINT8 testAttrib = FF_FAT_CASE_ATTR_BASE;
01818 #endif
01819 
01820     FF_T_UINT16 i,x,y,last_dot;
01821     FF_T_UINT16 first_tilde = 6;
01822 #ifdef FF_UNICODE_SUPPORT
01823     FF_T_WCHAR  MyShortName[13];
01824 #else
01825     FF_T_INT8   MyShortName[13];
01826 #endif
01827     FF_T_UINT16 NameLen;
01828     FF_T_BOOL   FitsShort = FF_TRUE;
01829     FF_DIRENT   MyDir;
01830     FF_T_BOOL   found;
01831     //FF_T_SINT8    RetVal = 0;
01832     FF_T_INT8   NumberBuf[6];
01833     FF_ERROR    Error;
01834 
01835 #ifdef FF_UNICODE_SUPPORT
01836     NameLen = (FF_T_UINT16) wcslen(LongName);
01837 #else
01838     NameLen = (FF_T_UINT16) strlen(LongName);
01839 #endif
01840 
01841     // Does LongName fit a shortname?
01842 
01843     for(i = 0, x = 0, last_dot = NameLen; i < NameLen; i++) {
01844         if(LongName[i] != '.') {
01845             x++;
01846         } else {
01847             last_dot = i;
01848         }
01849     }
01850 
01851     if (NameLen > 12 || NameLen-x > 1 || NameLen-last_dot > 4 || last_dot > 8) {
01852         FitsShort = FF_FALSE;
01853     }
01854 
01855     for(i = 0, x = 0; i < 11; x++) {
01856         FF_T_INT8 ch = (FF_T_INT8) LongName[x];
01857         if (!ch)
01858             break;
01859         if (x == last_dot) {
01860             while (i < 8)
01861                 ShortName[i++] = 0x20;
01862 #if defined(FF_SHORTNAME_CASE)
01863             testAttrib = FF_FAT_CASE_ATTR_EXT;
01864 #endif
01865         } else {
01866             if (i == 8) {
01867                 x = last_dot;
01868                 ch = (FF_T_INT8) LongName[x];
01869                 if (ch)
01870                     ch = (FF_T_INT8) LongName[++x];
01871 #if defined(FF_SHORTNAME_CASE)
01872                 testAttrib = FF_FAT_CASE_ATTR_EXT;
01873 #endif
01874             }
01875             if (!FF_ValidShortChar (ch)) {
01876                 FitsShort = FF_FALSE;
01877                 continue;
01878             }
01879             if (ch >= 'a' && ch <= 'z') {
01880                 ch -= 0x20;
01881 #if defined(FF_SHORTNAME_CASE)
01882                 if (testAttrib)
01883                     caseAttrib |= testAttrib;
01884                 else
01885                     FitsShort = FF_FALSE;   // We had capital: does not fit
01886             } else if (ch >= 'A' && ch <= 'Z') {
01887                 if (caseAttrib & testAttrib)
01888                     FitsShort = FF_FALSE;   // We had lower-case: does not fit
01889                 testAttrib = 0;
01890 #endif
01891             }
01892             ShortName[i++] = ch;
01893         }
01894     }
01895     while (i < 11)
01896         ShortName[i++] = 0x20;
01897     if (last_dot < first_tilde)
01898         first_tilde = last_dot;
01899     if (NameLen < first_tilde)  // Names like "Abc" will become "~Abc"
01900         first_tilde = NameLen;
01901 
01902     // Tail :
01903     memcpy(MyShortName, ShortName, 11);
01904     FF_ProcessShortName(MyShortName);
01905     found = (FF_T_BOOL) FF_FindEntryInDir(pIoman, DirCluster, MyShortName, 0x00, &MyDir, &Error);
01906 #ifdef Hein_Tibosch
01907     if (verboseLevel >= 1) logPrintf ("Long Name: %-14.14s Short '%s' (%s) Fit '%d' Found %d\n", LongName, ShortName, MyShortName, FitsShort, found);
01908 #endif
01909     if(FitsShort && !found) {
01910         return caseAttrib | 0x01;
01911     }
01912     if(FitsShort) {
01913         return FF_ERR_DIR_OBJECT_EXISTS;
01914     }
01915     for(i = 1; i < 0x0000FFFF; i++) { // Max Number of Entries in a DIR!
01916         sprintf(NumberBuf, "%d", i);
01917         NameLen = (FF_T_UINT16) strlen(NumberBuf);
01918         x = 7 - NameLen;
01919         if (x > first_tilde)
01920             x = first_tilde;
01921         ShortName[x++] = '~';
01922         for(y = 0; y < NameLen; y++) {
01923             ShortName[x+y] = NumberBuf[y];
01924         }
01925         memcpy(MyShortName, ShortName, 11);
01926         FF_ProcessShortName(MyShortName);
01927         found = FF_ShortNameExists(pIoman, DirCluster, MyShortName, &Error);
01928 #ifdef Hein_Tibosch
01929         if (verboseLevel >= 1) logPrintf ("Long Name: %-14.14s Short '%s' (%s) Fit '%d' Found %d\n", LongName, ShortName, MyShortName, FitsShort, found);
01930 #endif
01931         if(!found) {
01932 #ifdef FF_HASH_CACHE
01933 #if FF_HASH_FUNCTION == CRC16
01934             FF_AddDirentHash(pIoman, DirCluster, (FF_T_UINT32) FF_GetCRC16((FF_T_UINT8*)MyShortName, strlen(MyShortName)));
01935 #elif FF_HASH_FUNCTION == CRC8
01936             FF_AddDirentHash(pIoman, DirCluster, (FF_T_UINT32) FF_GetCRC8((FF_T_UINT8*)MyShortName, strlen(MyShortName)));
01937 #endif
01938 #endif
01939             return 0;
01940         }
01941     }
01942     // Add a tail and special number until we're happy :D
01943 
01944     return FF_ERR_DIR_DIRECTORY_FULL;
01945 }
01946 
01947 
01948 #ifdef FF_LFN_SUPPORT
01949 static FF_T_SINT8 FF_CreateLFNEntry(FF_T_UINT8 *EntryBuffer, FF_T_UINT16 *Name, FF_T_UINT uiNameLen, FF_T_UINT uiLFN, FF_T_UINT8 CheckSum) {
01950     
01951     FF_T_UINT i, x;
01952     
01953     memset(EntryBuffer, 0, 32);
01954 
01955     FF_putChar(EntryBuffer, FF_FAT_LFN_ORD,         (FF_T_UINT8) ((uiLFN & ~0x40)));
01956     FF_putChar(EntryBuffer, FF_FAT_DIRENT_ATTRIB,   (FF_T_UINT8) FF_FAT_ATTR_LFN);
01957     FF_putChar(EntryBuffer, FF_FAT_LFN_CHECKSUM,    (FF_T_UINT8) CheckSum);
01958 
01959     // Name_1
01960     for(i = 0, x = 0; i < 5; i++, x += 2) {
01961         if(i < uiNameLen)
01962                 {                  
01963                   memcpy(&EntryBuffer[FF_FAT_LFN_NAME_1 + x], &Name[i], sizeof(FF_T_UINT16));
01964                   //bobtntfullfat *((FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_1 + x]) = Name[i];
01965         }
01966                 else
01967                   if (i == uiNameLen)
01968                   {
01969             EntryBuffer[FF_FAT_LFN_NAME_1 + x]      = '\0';
01970             EntryBuffer[FF_FAT_LFN_NAME_1 + x + 1]  = '\0';
01971                   }
01972                   else
01973                   {
01974                           EntryBuffer[FF_FAT_LFN_NAME_1 + x]        = 0xFF;
01975                           EntryBuffer[FF_FAT_LFN_NAME_1 + x + 1]    = 0xFF;
01976                   }
01977     }
01978 
01979     // Name_2
01980     for(i = 0, x = 0; i < 6; i++, x += 2) {
01981         if((i + 5) < uiNameLen)
01982                 {
01983                   memcpy(&EntryBuffer[FF_FAT_LFN_NAME_2 + x], &Name[i+5], sizeof(FF_T_UINT16));
01984                   //EntryBuffer[FF_FAT_LFN_NAME_2 + x] = Name[i+5];
01985                   //bobtntfullfat *((FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_2 + x]) = Name[i+5];
01986         } else if ((i + 5) == uiNameLen) {
01987             EntryBuffer[FF_FAT_LFN_NAME_2 + x]      = '\0';
01988             EntryBuffer[FF_FAT_LFN_NAME_2 + x + 1]  = '\0';
01989         }else {
01990             EntryBuffer[FF_FAT_LFN_NAME_2 + x]      = 0xFF;
01991             EntryBuffer[FF_FAT_LFN_NAME_2 + x + 1]  = 0xFF;
01992         }
01993     }
01994 
01995     // Name_3
01996     for(i = 0, x = 0; i < 2; i++, x += 2) {
01997         if((i + 11) < uiNameLen)
01998                 {
01999                   memcpy(&EntryBuffer[FF_FAT_LFN_NAME_3 + x], &Name[i+11], sizeof(FF_T_UINT16));
02000                   //EntryBuffer[FF_FAT_LFN_NAME_3 + x] = Name[i+11];                  
02001                   //bobtntfullfat *((FF_T_UINT16 *) &EntryBuffer[FF_FAT_LFN_NAME_3 + x]) = Name[i+11];
02002         } else if ((i + 11) == uiNameLen) {
02003             EntryBuffer[FF_FAT_LFN_NAME_3 + x]      = '\0';
02004             EntryBuffer[FF_FAT_LFN_NAME_3 + x + 1]  = '\0';
02005         }else {
02006             EntryBuffer[FF_FAT_LFN_NAME_3 + x]      = 0xFF;
02007             EntryBuffer[FF_FAT_LFN_NAME_3 + x + 1]  = 0xFF;
02008         }
02009     }
02010     
02011     return FF_ERR_NONE;
02012 }
02013 #endif
02014 
02015 /*
02016 #ifdef FF_UNICODE_SUPPORT
02017 static FF_ERROR FF_CreateLFNs(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_WCHAR *Name, FF_T_UINT8 CheckSum, FF_T_UINT16 nEntry) {
02018 #else
02019 static FF_ERROR FF_CreateLFNs(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_INT8 *Name, FF_T_UINT8 CheckSum, FF_T_UINT16 nEntry) {
02020 #endif
02021     FF_T_UINT8  EntryBuffer[32];
02022 #ifdef FF_UNICODE_SUPPORT
02023     FF_T_UINT16 NameLen = (FF_T_UINT16) wcslen(Name);
02024 #else
02025     FF_T_UINT16 NameLen = (FF_T_UINT16) strlen(Name);
02026 #endif
02027     FF_T_UINT8  NumLFNs = (FF_T_UINT8)  (NameLen / 13);
02028     FF_T_UINT8  i;
02029     FF_T_UINT8  EndPos = (NameLen % 13);
02030     FF_ERROR    Error;
02031 
02032     FF_FETCH_CONTEXT FetchContext;
02033 
02034     if(EndPos) {
02035         NumLFNs ++;
02036     } else {
02037         EndPos = 13;
02038     }
02039 
02040     Error = FF_InitEntryFetch(pIoman, DirCluster, &FetchContext);
02041     if(Error) {
02042         return Error;
02043     }
02044 
02045     for(i = NumLFNs; i > 0; i--) {
02046         if(i == NumLFNs) {
02047             FF_CreateLFNEntry(EntryBuffer, (Name + (13 * (i - 1))), EndPos, i, CheckSum);
02048             EntryBuffer[0] |= 0x40;
02049         } else {
02050             FF_CreateLFNEntry(EntryBuffer, (Name + (13 * (i - 1))), 13, i, CheckSum);
02051         }
02052         
02053         Error = FF_PushEntryWithContext(pIoman, nEntry + (NumLFNs - i), &FetchContext, EntryBuffer);
02054         if(Error) {
02055             FF_CleanupEntryFetch(pIoman, &FetchContext);
02056             return Error;
02057         }
02058     }
02059 
02060     FF_CleanupEntryFetch(pIoman, &FetchContext);
02061 
02062     return FF_ERR_NONE;
02063 }
02064 #endif
02065 */
02066 
02067 
02068 #ifdef FF_UNICODE_SUPPORT
02069 static FF_ERROR FF_CreateLFNs(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_WCHAR *Name, FF_T_UINT8 CheckSum, FF_T_UINT16 nEntry) {
02070 #else
02071 static FF_ERROR FF_CreateLFNs(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_INT8 *Name, FF_T_UINT8 CheckSum, FF_T_UINT16 nEntry) {
02072 #endif
02073     FF_ERROR            Error;
02074     FF_T_UINT           uiNumLFNs;
02075     FF_T_UINT           uiEndPos;
02076     FF_T_UINT           i,y;
02077 
02078 #ifdef FF_UNICODE_UTF8_SUPPORT
02079     FF_T_SINT32         slRetVal;
02080 #endif
02081 
02082 #ifndef FF_UNICODE_SUPPORT
02083 #ifndef FF_UNICODE_UTF8_SUPPORT
02084     FF_T_UINT16         *pUtf16;
02085 #endif
02086 #endif
02087 
02088     FF_FETCH_CONTEXT    FetchContext;
02089 
02090     FF_T_UINT8          EntryBuffer[32];
02091     FF_T_UINT16         usUtf16Name[FF_MAX_FILENAME + 1];
02092     
02093 
02094 #ifdef FF_UNICODE_SUPPORT
02095 #if WCHAR_MAX <= 0xFFFF
02096     y = wcslen(Name);
02097     if(y > FF_MAX_FILENAME) {
02098         return FF_ERR_DIR_NAME_TOO_LONG;
02099     }
02100     wcsncpy(usUtf16Name, Name, FF_MAX_FILENAME);
02101 #else
02102     i = 0;
02103     y = 0;
02104     while(Name[i]) {
02105         FF_Utf32ctoUtf16c(&usUtf16Name[y], (FF_T_UINT32) Name[i], FF_MAX_FILENAME - i);
02106         y += FF_GetUtf16SequenceLen(usUtf16Name[y]);
02107         i++;
02108         if(y > FF_MAX_FILENAME) {
02109             return FF_ERR_DIR_NAME_TOO_LONG;
02110         }
02111     }
02112 #endif
02113 #endif
02114 
02115     // Convert the name into UTF-16 format.
02116 #ifdef FF_UNICODE_UTF8_SUPPORT
02117     // Simply convert the UTF8 to UTF16 and be done with it.
02118     i = 0;
02119     y = 0;
02120     while(Name[i]) {
02121         slRetVal = FF_Utf8ctoUtf16c(&usUtf16Name[y], (FF_T_UINT8 *)&Name[i], FF_MAX_FILENAME - i);
02122         if(slRetVal > 0) {
02123             i += slRetVal;
02124         } else {
02125             break;  // No more space in the UTF-16 buffer, simply truncate for safety.
02126         }
02127         y += FF_GetUtf16SequenceLen(usUtf16Name[y]);
02128         if(y > FF_MAX_FILENAME) {
02129             return FF_ERR_DIR_NAME_TOO_LONG;
02130         }
02131     }
02132 #else
02133 #ifndef FF_UNICODE_SUPPORT
02134     i = 0;
02135     y = strlen(Name);
02136     if(y > FF_MAX_FILENAME) {
02137         return FF_ERR_DIR_NAME_TOO_LONG;
02138     }
02139     pUtf16 = usUtf16Name;
02140     while(Name[i]) {
02141         usUtf16Name[i] = (FF_T_UINT16) Name[i];
02142         i++;
02143     }
02144 #endif
02145 #endif
02146 
02147     // Whole name is now in a valid UTF-16 format. Lets go make thos LFN's.
02148     // i should at this point be the length of the name.
02149 
02150     uiNumLFNs   = y / 13;   // Number of LFNs is the total number of UTF-16 units, divided by 13 (13 units per LFN).
02151     uiEndPos    = y % 13;   // The ending position in an LFN, of the last LFN UTF-16 charachter.
02152 
02153     if(uiEndPos) {
02154         uiNumLFNs++;
02155     } else {
02156         uiEndPos = 13;
02157     }
02158 
02159     Error = FF_InitEntryFetch(pIoman, DirCluster, &FetchContext);
02160     if(Error) {
02161         return Error;
02162     }
02163 
02164     // After this point, i is no longer the length of the Filename in UTF-16 units.
02165     for(i = uiNumLFNs; i > 0; i--) {
02166         if(i == uiNumLFNs) {
02167             FF_CreateLFNEntry(EntryBuffer, (usUtf16Name + (13 * (i - 1))), uiEndPos, i, CheckSum);
02168             EntryBuffer[0] |= 0x40;
02169         } else {
02170             FF_CreateLFNEntry(EntryBuffer, (usUtf16Name + (13 * (i - 1))), 13, i, CheckSum);
02171         }
02172         
02173         Error = FF_PushEntryWithContext(pIoman, nEntry + (uiNumLFNs - i), &FetchContext, EntryBuffer);
02174         if(Error) {
02175             FF_CleanupEntryFetch(pIoman, &FetchContext);
02176             return Error;
02177         }
02178     }
02179 
02180     FF_CleanupEntryFetch(pIoman, &FetchContext);
02181 
02182     return FF_ERR_NONE;
02183 }
02184 
02185 FF_ERROR FF_ExtendDirectory(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster) {
02186     FF_T_UINT32 CurrentCluster;
02187     FF_T_UINT32 NextCluster;
02188     FF_ERROR Error;
02189 
02190     if(pIoman->pPartition->Type != FF_T_FAT32) {
02191         if(DirCluster == pIoman->pPartition->RootDirCluster) {
02192             return FF_ERR_DIR_CANT_EXTEND_ROOT_DIR;
02193         }
02194     }
02195 
02196     if(!pIoman->pPartition->FreeClusterCount) {
02197         pIoman->pPartition->FreeClusterCount = FF_CountFreeClusters(pIoman, &Error);
02198         if(Error) {
02199             return Error;
02200         }
02201         if(pIoman->pPartition->FreeClusterCount == 0) {
02202             return FF_ERR_FAT_NO_FREE_CLUSTERS;
02203         }
02204     }
02205     
02206     FF_lockFAT(pIoman);
02207     {
02208         CurrentCluster = FF_FindEndOfChain(pIoman, DirCluster, &Error);
02209         if(Error) {
02210             FF_unlockFAT(pIoman);
02211             return Error;
02212         }
02213 
02214         NextCluster = FF_FindFreeCluster(pIoman, &Error);
02215         if(Error) {
02216             FF_unlockFAT(pIoman);
02217             return Error;
02218         }
02219 
02220         Error = FF_putFatEntry(pIoman, CurrentCluster, NextCluster);
02221         if(Error) {
02222             FF_unlockFAT(pIoman);
02223             return Error;
02224         }
02225 
02226         Error = FF_putFatEntry(pIoman, NextCluster, 0xFFFFFFFF);
02227         if(Error) {
02228             FF_unlockFAT(pIoman);
02229             return Error;
02230         }
02231     }
02232     FF_unlockFAT(pIoman);
02233 
02234     Error = FF_ClearCluster(pIoman, NextCluster);
02235     if(Error) {
02236         FF_unlockFAT(pIoman);
02237         return Error;
02238     }
02239     
02240     Error = FF_DecreaseFreeClusters(pIoman, 1);
02241     if(Error) {
02242         FF_unlockFAT(pIoman);
02243         return Error;
02244     }
02245 
02246     return FF_ERR_NONE;
02247 }
02248 
02249 #ifdef FF_UNICODE_SUPPORT
02250 static void FF_MakeNameCompliant(FF_T_WCHAR *Name) {
02251 #else
02252 static void FF_MakeNameCompliant(FF_T_UINT8 *Name) {
02253 #endif
02254     
02255     if((FF_T_UINT8) Name[0] == 0xE5) {  // Support Japanese KANJI symbol.
02256         Name[0] = 0x05;
02257     }
02258     
02259     while(*Name) {
02260         if(*Name < 0x20 || *Name == 0x7F || *Name == 0x22 || *Name == 0x7C) {   // Leave all extended chars as they are.
02261             *Name = '_';
02262         }
02263         if(*Name >= 0x2A && *Name <= 0x2F && *Name != 0x2B && *Name != 0x2E && *Name != 0x2D) {
02264             *Name = '_';
02265         }
02266         if(*Name >= 0x3A && *Name <= 0x3F) {
02267             *Name = '_';
02268         }
02269         if(*Name >= 0x5B && *Name <= 0x5C) {
02270             *Name = '_';
02271         }
02272         Name++;
02273     }
02274 }
02275 
02276 FF_ERROR FF_CreateDirent(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_DIRENT *pDirent) {
02277     
02278     FF_T_UINT8  EntryBuffer[32];
02279 #ifdef FF_UNICODE_SUPPORT
02280     FF_T_UINT16 NameLen = (FF_T_UINT16) wcslen(pDirent->FileName);
02281 #else
02282     FF_T_UINT16 NameLen = (FF_T_UINT16) strlen(pDirent->FileName);
02283 #endif
02284     FF_T_UINT8  numLFNs = (FF_T_UINT8) (NameLen / 13);
02285     FF_T_SINT32 FreeEntry;
02286     FF_ERROR    RetVal = FF_ERR_NONE;
02287     FF_T_UINT8  Entries;
02288 
02289     FF_FETCH_CONTEXT FetchContext;
02290 
02291 #ifdef FF_LFN_SUPPORT
02292     FF_T_UINT8  CheckSum;
02293 #endif
02294 
02295 #ifdef FF_UNICODE_SUPPORT
02296     FF_T_WCHAR  UTF16EntryBuffer[32];
02297 #if WCHAR_MAX > 0xFFFF
02298     // Check that the filename won't exceed the max LFN length if converted to UTF-16.
02299     /*if(FF_Utf32GetUtf16Len((FF_T_UINT32 *) pDirent->FileName) > FF_MAX_FILENAME) {
02300         return FF_ERR_UNICODE_CONVERSION_EXCEEDED; 
02301     }*/
02302 #endif
02303 
02304 #endif
02305 
02306 #ifdef FF_UNICODE_SUPPORT
02307     FF_MakeNameCompliant(pDirent->FileName);    // Ensure we don't break the Dir tables.
02308 #else
02309     FF_MakeNameCompliant((FF_T_UINT8 *)pDirent->FileName);  // Ensure we don't break the Dir tables.
02310 #endif
02311     memset(EntryBuffer, 0, 32);
02312 
02313     if(NameLen % 13) {
02314         numLFNs ++;
02315     }
02316 
02317 #ifdef FF_LFN_SUPPORT
02318     // Create and push the LFN's
02319     Entries = numLFNs + 1;  // Find enough places for the LFNs and the ShortName    
02320 #else
02321     Entries = 1;
02322 #endif
02323 
02324     // Create the ShortName
02325     FF_lockDIR(pIoman);
02326     {
02327         if((FreeEntry = FF_FindFreeDirent(pIoman, DirCluster, Entries)) >= 0) {
02328 #ifdef FF_UNICODE_SUPPORT
02329             //FF_cstrntowcs(UTF16EntryBuffer, (FF_T_INT8 *) EntryBuffer, 32);
02330             RetVal = FF_CreateShortName(pIoman, DirCluster, UTF16EntryBuffer, pDirent->FileName);
02331 #else
02332             RetVal = FF_CreateShortName(pIoman, DirCluster, (FF_T_INT8 *) EntryBuffer, pDirent->FileName);
02333 #endif
02334             
02335             //if(!RetVal) {
02336 #ifdef FF_LFN_SUPPORT
02337 #ifdef FF_UNICODE_SUPPORT
02338                 FF_wcsntocstr((FF_T_INT8 *) EntryBuffer, UTF16EntryBuffer, 11);
02339 #endif
02340                 CheckSum = FF_CreateChkSum(EntryBuffer);
02341                 FF_CreateLFNs(pIoman, DirCluster, pDirent->FileName, CheckSum, (FF_T_UINT16) FreeEntry);
02342 #else
02343                 numLFNs = 0;
02344 #endif              
02345                 
02346 #ifdef FF_TIME_SUPPORT
02347                 FF_PlaceTime(EntryBuffer, FF_FAT_DIRENT_CREATE_TIME);
02348                 FF_PlaceDate(EntryBuffer, FF_FAT_DIRENT_CREATE_DATE);
02349                 FF_PlaceTime(EntryBuffer, FF_FAT_DIRENT_LASTMOD_TIME);
02350                 FF_PlaceDate(EntryBuffer, FF_FAT_DIRENT_LASTMOD_DATE);
02351 #endif
02352 
02353                 FF_putChar(EntryBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB), pDirent->Attrib);
02354                 FF_putShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH), (FF_T_UINT16)(pDirent->ObjectCluster >> 16));
02355                 FF_putShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW), (FF_T_UINT16)(pDirent->ObjectCluster));
02356                 FF_putLong(EntryBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE), pDirent->Filesize);
02357 
02358                 RetVal = FF_InitEntryFetch(pIoman, DirCluster, &FetchContext);
02359                 if(RetVal) {
02360                     FF_unlockDIR(pIoman);
02361                     return RetVal;
02362                 }
02363                 RetVal = FF_PushEntryWithContext(pIoman, (FF_T_UINT16) (FreeEntry + numLFNs), &FetchContext, EntryBuffer);
02364                 FF_CleanupEntryFetch(pIoman, &FetchContext);
02365                 if(RetVal) {
02366                     FF_unlockDIR(pIoman);
02367                     return RetVal;
02368                 }
02369             /*} else {
02370                 FF_unlockDIR(pIoman);
02371                 return RetVal;
02372             }*/
02373         }else {
02374             FF_unlockDIR(pIoman);
02375             return FreeEntry;
02376         }
02377     }
02378     FF_unlockDIR(pIoman);
02379 
02380     if(RetVal) {
02381         return RetVal;
02382     }
02383 
02384     if(pDirent) {
02385         pDirent->CurrentItem = (FF_T_UINT16) (FreeEntry + numLFNs);
02386     }
02387     
02388     return FF_ERR_NONE;
02389 }
02390 
02391 
02392 #ifdef FF_UNICODE_SUPPORT
02393 FF_T_UINT32 FF_CreateFile(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_WCHAR *FileName, FF_DIRENT *pDirent, FF_ERROR *pError) {
02394 #else
02395 FF_T_UINT32 FF_CreateFile(FF_IOMAN *pIoman, FF_T_UINT32 DirCluster, FF_T_INT8 *FileName, FF_DIRENT *pDirent, FF_ERROR *pError) {
02396 #endif
02397     FF_DIRENT   MyFile;
02398     *pError = FF_ERR_NONE;
02399 #ifdef FF_UNICODE_SUPPORT
02400     wcsncpy(MyFile.FileName, FileName, FF_MAX_FILENAME);
02401 #else
02402     strncpy(MyFile.FileName, FileName, FF_MAX_FILENAME);
02403 #endif
02404 
02405     MyFile.Attrib = 0x00;
02406     MyFile.Filesize = 0;
02407     MyFile.ObjectCluster = FF_CreateClusterChain(pIoman, pError);
02408     if(*pError) {
02409         FF_UnlinkClusterChain(pIoman, MyFile.ObjectCluster, 0);
02410         FF_FlushCache(pIoman);
02411         return 0;
02412     }
02413     MyFile.CurrentItem = 0;
02414 
02415     *pError = FF_CreateDirent(pIoman, DirCluster, &MyFile);
02416 
02417     if(*pError) {
02418         FF_UnlinkClusterChain(pIoman, MyFile.ObjectCluster, 0);
02419         FF_FlushCache(pIoman);
02420         return 0;
02421     }
02422 
02423     FF_FlushCache(pIoman);
02424 
02425     if(pDirent) {
02426         memcpy(pDirent, &MyFile, sizeof(FF_DIRENT));
02427     }
02428 
02429     return MyFile.ObjectCluster;
02430 }
02431 
02432 
02444 #ifdef FF_UNICODE_SUPPORT
02445 FF_ERROR FF_MkDir(FF_IOMAN *pIoman, const FF_T_WCHAR *Path) {
02446 #else
02447 FF_ERROR FF_MkDir(FF_IOMAN *pIoman, const FF_T_INT8 *Path) {
02448 #endif
02449     FF_DIRENT   MyDir;
02450     FF_T_UINT32 DirCluster;
02451 #ifdef FF_UNICODE_SUPPORT
02452     FF_T_WCHAR  DirName[FF_MAX_FILENAME];
02453 #else
02454     FF_T_INT8   DirName[FF_MAX_FILENAME];
02455 #endif
02456     FF_T_UINT8  EntryBuffer[32];
02457     FF_T_UINT32 DotDotCluster;
02458     FF_T_UINT16 i;
02459     FF_ERROR    Error = FF_ERR_NONE;
02460 
02461     FF_FETCH_CONTEXT FetchContext;
02462 
02463     if(!pIoman) {
02464         return FF_ERR_NULL_POINTER;
02465     }
02466 
02467 #ifdef FF_UNICODE_SUPPORT
02468     i = (FF_T_UINT16) wcslen(Path);
02469 #else
02470     i = (FF_T_UINT16) strlen(Path);
02471 #endif
02472 
02473     while(i != 0) {
02474         if(Path[i] == '\\' || Path[i] == '/') {
02475             break;
02476         }
02477         i--;
02478     }
02479 
02480 #ifdef FF_UNICODE_SUPPORT
02481     wcsncpy(DirName, (Path + i + 1), FF_MAX_FILENAME);
02482 #else
02483     strncpy(DirName, (Path + i + 1), FF_MAX_FILENAME);
02484 #endif
02485 
02486     if(i == 0) {
02487         i = 1;
02488     }
02489 
02490     DirCluster = FF_FindDir(pIoman, Path, i, &Error);
02491 
02492     if(Error) {
02493         return Error;
02494     }
02495 
02496     if(DirCluster) {
02497         if(FF_FindEntryInDir(pIoman, DirCluster, DirName, 0x00, &MyDir, &Error)) {
02498             return FF_ERR_DIR_OBJECT_EXISTS;
02499         }
02500 
02501         if(Error && Error != FF_ERR_DIR_END_OF_DIR) {
02502             return Error;   
02503         }
02504 
02505 #ifdef FF_UNICODE_SUPPORT
02506         wcsncpy(MyDir.FileName, DirName, FF_MAX_FILENAME);
02507 #else
02508         strncpy(MyDir.FileName, DirName, FF_MAX_FILENAME);
02509 #endif
02510         MyDir.Filesize      = 0;
02511         MyDir.Attrib        = FF_FAT_ATTR_DIR;
02512         MyDir.ObjectCluster = FF_CreateClusterChain(pIoman, &Error);
02513         if(Error) {
02514             return Error;
02515         }
02516         if(MyDir.ObjectCluster) {
02517             Error = FF_ClearCluster(pIoman, MyDir.ObjectCluster);
02518             if(Error) {
02519                 FF_UnlinkClusterChain(pIoman, MyDir.ObjectCluster, 0);
02520                 FF_FlushCache(pIoman);
02521                 return Error;
02522             }
02523         } else {
02524             // Couldn't allocate any space for the dir!
02525             return FF_ERR_DIR_EXTEND_FAILED;
02526         }
02527 
02528         Error = FF_CreateDirent(pIoman, DirCluster, &MyDir);
02529 
02530         if(Error) {
02531             FF_UnlinkClusterChain(pIoman, MyDir.ObjectCluster, 0);
02532             FF_FlushCache(pIoman);
02533             return Error;
02534         }
02535         
02536         memset(EntryBuffer, 0, 32);
02537         EntryBuffer[0] = '.';
02538         for(i = 1; i < 11; i++) {
02539             EntryBuffer[i] = 0x20;
02540         }
02541         FF_putChar(EntryBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB), FF_FAT_ATTR_DIR);
02542         FF_putShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH), (FF_T_UINT16)(MyDir.ObjectCluster >> 16));
02543         FF_putShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW), (FF_T_UINT16) MyDir.ObjectCluster);
02544         FF_putLong(EntryBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE), 0);
02545 
02546         Error = FF_InitEntryFetch(pIoman, MyDir.ObjectCluster, &FetchContext);
02547         if(Error) {
02548             FF_UnlinkClusterChain(pIoman, MyDir.ObjectCluster, 0);
02549             FF_FlushCache(pIoman);
02550             return Error;
02551         }
02552         
02553         Error = FF_PushEntryWithContext(pIoman, 0, &FetchContext, EntryBuffer);
02554         if(Error) {
02555             FF_UnlinkClusterChain(pIoman, MyDir.ObjectCluster, 0);
02556             FF_FlushCache(pIoman);
02557             FF_CleanupEntryFetch(pIoman, &FetchContext);
02558             return Error;
02559         }
02560 
02561         memset(EntryBuffer, 0, 32);
02562         EntryBuffer[0] = '.';
02563         EntryBuffer[1] = '.';
02564         for(i = 2; i < 11; i++) {
02565             EntryBuffer[i] = 0x20;
02566         }
02567         
02568         if(DirCluster == pIoman->pPartition->RootDirCluster) {
02569             DotDotCluster = 0;
02570         } else {
02571             DotDotCluster = DirCluster;
02572         }
02573 
02574         FF_putChar(EntryBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB), FF_FAT_ATTR_DIR);
02575         FF_putShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_HIGH), (FF_T_UINT16)(DotDotCluster >> 16));
02576         FF_putShort(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_CLUS_LOW), (FF_T_UINT16) DotDotCluster);
02577         FF_putLong(EntryBuffer,  (FF_T_UINT16)(FF_FAT_DIRENT_FILESIZE), 0);
02578         
02579         //FF_PushEntry(pIoman, MyDir.ObjectCluster, 1, EntryBuffer);
02580         Error = FF_PushEntryWithContext(pIoman, 1, &FetchContext, EntryBuffer);
02581         if(Error) {
02582             FF_UnlinkClusterChain(pIoman, MyDir.ObjectCluster, 0);
02583             FF_FlushCache(pIoman);
02584             FF_CleanupEntryFetch(pIoman, &FetchContext);
02585             return Error;
02586         }
02587         FF_CleanupEntryFetch(pIoman, &FetchContext);
02588 
02589         FF_FlushCache(pIoman);  // Ensure dir was flushed to the disk!
02590 
02591         return FF_ERR_NONE;
02592     }
02593     
02594     return FF_ERR_DIR_INVALID_PATH;
02595 }
02596 
02597 
02598 
02599 FF_ERROR FF_RmLFNs(FF_IOMAN *pIoman, FF_T_UINT16 usDirEntry, FF_FETCH_CONTEXT *pContext) {
02600 
02601     FF_ERROR    Error;
02602     FF_T_UINT8  EntryBuffer[32];
02603 
02604     usDirEntry--;
02605 
02606     do {
02607         Error = FF_FetchEntryWithContext(pIoman, usDirEntry, pContext, EntryBuffer);
02608         if(Error) {
02609             return Error;
02610         }
02611         
02612         if(FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB)) == FF_FAT_ATTR_LFN) {
02613             FF_putChar(EntryBuffer, (FF_T_UINT16) 0, (FF_T_UINT8) 0xE5);
02614             Error = FF_PushEntryWithContext(pIoman, usDirEntry, pContext, EntryBuffer);
02615             if(Error) {
02616                 return Error;
02617             }
02618         }
02619 
02620         if(usDirEntry == 0) {
02621             break;
02622         }
02623         usDirEntry--;
02624     }while(FF_getChar(EntryBuffer, (FF_T_UINT16)(FF_FAT_DIRENT_ATTRIB)) == FF_FAT_ATTR_LFN);
02625 
02626     return FF_ERR_NONE;
02627 }

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.