1052 TFileName fileName; |
1061 TFileName fileName; |
1053 iFileCreationHelper.InitialiseL(ptrNewName); |
1062 iFileCreationHelper.InitialiseL(ptrNewName); |
1054 TFatDirEntry startEntry; |
1063 TFatDirEntry startEntry; |
1055 |
1064 |
1056 TRAP(nRes, DoFindL(ptrNewName, KEntryAttMaskSupported, |
1065 TRAP(nRes, DoFindL(ptrNewName, KEntryAttMaskSupported, |
1057 newName_VFatEntryPos, startEntry, aNewName_DosEntryPos, newName_DosEntry, |
1066 newName_VFatEntryPos, startEntry, aNewName_DosEntryPos, newName_DosEntry, |
1058 fileName, KErrNotFound, |
1067 fileName, KErrNotFound, |
1059 &iFileCreationHelper, |
1068 &iFileCreationHelper, |
1060 leafDir)); |
1069 leafDir)); |
1061 |
1070 |
1062 if (nRes!=KErrNone && nRes!=KErrNotFound) |
1071 if (nRes!=KErrNone && nRes!=KErrNotFound) |
1063 User::Leave(nRes); |
1072 User::Leave(nRes); |
1064 |
1073 |
1065 const TBool newFileExists = (nRes == KErrNone); //-- ETrue if 'aNewName' file exists. |
1074 const TBool newFileExists = (nRes == KErrNone); //-- ETrue if 'aNewName' file exists. |
1066 const TBool bNewNameIsVFAT = !IsLegalDosName(ptrNewName, EFalse, EFalse, EFalse, EFalse, ETrue); |
1075 const TBool bNewNameIsVFAT = !IsLegalDosName(ptrNewName, EFalse, EFalse, EFalse, EFalse, ETrue); |
1067 |
1076 |
1068 if(renameMode && newFileExists) |
1077 if(renameMode && newFileExists) |
1069 { |
1078 { |
1070 if(!namesAreIdentical) |
1079 if(!namesAreIdentical) |
1071 { |
1080 { |
1072 if ((newName_DosEntry.Attributes()&KEntryAttDir) != (oldName_DosEntry.Attributes()&KEntryAttDir)) |
1081 if ((newName_DosEntry.Attributes()&KEntryAttDir) != (oldName_DosEntry.Attributes()&KEntryAttDir)) |
1073 { |
1082 { |
1074 User::Leave(KErrAccessDenied); //-- leave with KErrAccessDenied if it is trying to rename a file |
1083 User::Leave(KErrAccessDenied); //-- leave with KErrAccessDenied if it is trying to rename a file |
1075 // to a dir or vice versa. |
1084 // to a dir or vice versa. |
1076 } |
1085 } |
1077 User::Leave(KErrAlreadyExists); //-- can't rename file if the file with 'aNewName' already exists |
1086 User::Leave(KErrAlreadyExists); //-- can't rename file if the file with 'aNewName' already exists |
1078 } |
1087 } |
1079 else |
1088 else |
1080 { |
1089 { |
1081 if(!bNewNameIsVFAT && !bOldNameIsVFAT) |
1090 if(!bNewNameIsVFAT && !bOldNameIsVFAT) |
1082 return; //-- renaming DOS name to itself |
1091 return; //-- renaming DOS name to itself |
1083 } |
1092 } |
1084 //-- allow renaming entry to itself. "namesAreIdentical" is case-insensitive. use case: "FILE" -> "File" |
1093 //-- allow renaming entry to itself. "namesAreIdentical" is case-insensitive. use case: "FILE" -> "File" |
1085 } |
1094 } |
1086 |
1095 |
1087 //--------------------------------------------------------------------------------------------------------------------------- |
1096 //--------------------------------------------------------------------------------------------------------------------------- |
1088 |
1097 |
1089 if(replaceMode && newFileExists) |
1098 if(replaceMode && newFileExists) |
1090 { |
1099 { |
1091 //--------------------------------------------------------------------------------------------------------------------------- |
1100 //--------------------------------------------------------------------------------------------------------------------------- |
1092 //-- replace contents of the 'aNewName' with 'aOldName' and remove 'aOldName' entries. |
1101 //-- replace contents of the 'aNewName' with 'aOldName' and remove 'aOldName' entries. |
1093 |
1102 |
1094 //-- check if we are still trying to replace the file with itself, probably using short name alias |
1103 //-- check if we are still trying to replace the file with itself, probably using short name alias |
1095 if(aNewName_DosEntryPos == oldName_DosEntryPos) |
1104 if(aNewName_DosEntryPos == oldName_DosEntryPos) |
1128 FAT().FreeClusterListL(newNameStartCluster); |
1137 FAT().FreeClusterListL(newNameStartCluster); |
1129 |
1138 |
1130 if(IsRuggedFSys()) |
1139 if(IsRuggedFSys()) |
1131 FAT().FlushL(); |
1140 FAT().FlushL(); |
1132 |
1141 |
1133 } |
1142 } |
1134 else //if(replaceMode && newFileExists) |
1143 else //if(replaceMode && newFileExists) |
1135 { |
1144 { |
1136 //--------------------------------------------------------------------------------------------------------------------------- |
1145 //--------------------------------------------------------------------------------------------------------------------------- |
1137 //-- Renaming 'aOldName' to 'aNewName': add 'aNewName' entry set and remove 'aOldName' entryset |
1146 //-- Renaming 'aOldName' to 'aNewName': add 'aNewName' entry set and remove 'aOldName' entryset |
1138 |
1147 |
1139 TFatDirEntry newDosEntry = oldName_DosEntry; |
1148 TFatDirEntry newDosEntry = oldName_DosEntry; |
1140 //-- generate short name for the 'aNewName' entryset and make new DOS entry |
1149 //-- generate short name for the 'aNewName' entryset and make new DOS entry |
1141 if(bNewNameIsVFAT) |
1150 if(bNewNameIsVFAT) |
1142 {//-- need to generate a short name for VFAT entryset DOS entry |
1151 {//-- need to generate a short name for VFAT entryset DOS entry |
1143 TShortName shortName; |
1152 TShortName shortName; |
1144 |
1153 |
1145 if (iFileCreationHelper.GetValidatedShortName(shortName) == KErrNotFound) |
1154 if (iFileCreationHelper.GetValidatedShortName(shortName) == KErrNotFound) |
1146 { |
1155 { |
1147 GenerateShortNameL(aNewName_DosEntryPos.Cluster(), ptrNewName, shortName, ETrue); |
1156 GenerateShortNameL(aNewName_DosEntryPos.Cluster(), ptrNewName, shortName, ETrue); |
1148 } |
1157 } |
1149 |
1158 |
1150 newDosEntry.SetName(shortName); |
1159 newDosEntry.SetName(shortName); |
1151 } |
1160 } |
1152 else |
1161 else |
1153 {//-- just use 'aNewName' as DOS name. |
1162 {//-- just use 'aNewName' as DOS name. |
1154 TBuf8<KFatDirNameSize+1> tmp; //-- the name may be "XXXXXXXX.YYY" |
1163 TBuf8<KFatDirNameSize+1> tmp; //-- the name may be "XXXXXXXX.YYY" |
1155 tmp.Copy(ptrNewName); |
1164 tmp.Copy(ptrNewName); |
1156 newDosEntry.SetName(DosNameToStdFormat(tmp)); |
1165 newDosEntry.SetName(DosNameToStdFormat(tmp)); |
1157 } |
1166 } |
1158 |
1167 |
1159 if(IsRuggedFSys()) |
1168 if(IsRuggedFSys()) |
1160 {//-- the the note(1) above |
1169 {//-- the the note(1) above |
1161 newDosEntry.SetRuggedFatEntryId(KReservedIdNewEntry); |
1170 newDosEntry.SetRuggedFatEntryId(KReservedIdNewEntry); |
1162 oldName_DosEntry.SetRuggedFatEntryId(KReservedIdOldEntry); |
1171 oldName_DosEntry.SetRuggedFatEntryId(KReservedIdOldEntry); |
1163 WriteDirEntryL(oldName_DosEntryPos, oldName_DosEntry); |
1172 WriteDirEntryL(oldName_DosEntryPos, oldName_DosEntry); |
1164 } |
1173 } |
1165 |
1174 |
1166 //-- add new entryset to the directory |
1175 //-- add new entryset to the directory |
1167 aNewName_DosEntryPos.iPos = 0; |
1176 aNewName_DosEntryPos.iPos = 0; |
1168 aNewName_DosEntryPos.iCluster = aNewName_ParentDirPos.Cluster(); |
1177 aNewName_DosEntryPos.iCluster = aNewName_ParentDirPos.Cluster(); |
1169 |
1178 |
1170 if (iFileCreationHelper.IsNewEntryPosFound()) |
1179 if (iFileCreationHelper.IsNewEntryPosFound()) |
1171 { |
1180 { |
1172 aNewName_DosEntryPos = iFileCreationHelper.EntryAddingPos(); |
1181 aNewName_DosEntryPos = iFileCreationHelper.EntryAddingPos(); |
1173 } |
1182 } |
1174 |
1183 |
1175 if(bNewNameIsVFAT) |
1184 if(bNewNameIsVFAT) |
1176 { |
1185 { |
1177 const TInt numEntries = NumberOfVFatEntries(ptrNewName.Length()); |
1186 const TInt numEntries = NumberOfVFatEntries(ptrNewName.Length()); |
1178 AddDirEntryL(aNewName_DosEntryPos, numEntries); |
1187 AddDirEntryL(aNewName_DosEntryPos, numEntries); |
1179 WriteDirEntryL(aNewName_DosEntryPos, newDosEntry, ptrNewName); |
1188 WriteDirEntryL(aNewName_DosEntryPos, newDosEntry, ptrNewName); |
1180 } |
1189 } |
1181 else |
1190 else |
1976 |
1985 |
1977 const TUint32 clSize = 1 << ClusterSizeLog2(); //-- media cluster size |
1986 const TUint32 clSize = 1 << ClusterSizeLog2(); //-- media cluster size |
1978 const TUint32 cacheSz = pDirCache->CacheSizeInBytes(); //-- cache size in bytes |
1987 const TUint32 cacheSz = pDirCache->CacheSizeInBytes(); //-- cache size in bytes |
1979 const TUint32 maxDirEntries = cacheSz >> KSizeOfFatDirEntryLog2; //-- maximal number of dir entries that can be in the cache |
1988 const TUint32 maxDirEntries = cacheSz >> KSizeOfFatDirEntryLog2; //-- maximal number of dir entries that can be in the cache |
1980 |
1989 |
1981 const TUint pageSzLog2 = pDirCache->PageSizeInBytesLog2(); |
1990 const TUint pageSzLog2 = pDirCache->PageSizeInBytesLog2(); |
1982 TBool ScanMRUPageFirst = EFalse; |
1991 TBool ScanMRUPageFirst = EFalse; |
1983 TBool MRUPageScanned = EFalse; |
1992 TBool MRUPageScanned = EFalse; |
1984 |
1993 |
1985 // if MRU pos is availale, start with MRU page |
1994 // if MRU pos is availale, start with MRU page |
1986 if (aLeafDir.iMRUPos.Cluster()) |
1995 if (aLeafDir.iMRUPos.Cluster()) |
1987 { |
1996 { |
1988 ScanMRUPageFirst = ETrue; |
1997 ScanMRUPageFirst = ETrue; |
1989 DosEntryPos1 = aLeafDir.iMRUPos; |
1998 DosEntryPos1 = aLeafDir.iMRUPos; |
1990 } |
1999 } |
1991 |
2000 |
1992 TInt numFound = 0; |
2001 TInt numFound = 0; |
1993 TEntryPos startPos = DosEntryPos1; |
2002 TEntryPos startPos = DosEntryPos1; |
1994 TInt clusterNum = DosEntryPos1.iCluster; |
2003 TInt clusterNum = DosEntryPos1.iCluster; |
1995 |
2004 |
1996 for(TUint32 entryCnt=0; entryCnt < maxDirEntries; ++entryCnt) |
2005 for(TUint32 entryCnt=0; entryCnt < maxDirEntries; ++entryCnt) |
1997 {//-- walk through directory cluster list. The loop is limited by maximal number of dir entries |
2006 {//-- walk through directory cluster list. The loop is limited by maximal number of dir entries |
1998 //-- that can be cached. Helps to avoid problems with infinite (looped) directories |
2007 //-- that can be cached. Helps to avoid problems with infinite (looped) directories |
1999 |
2008 |
2000 if (IsEndOfClusterCh(DosEntryPos1.iCluster)) |
2009 if (IsEndOfClusterCh(DosEntryPos1.iCluster)) |
2001 { |
2010 { |
2002 // refer back to the last stored cluster position |
2011 // refer back to the last stored cluster position |
2003 // note aFileCreationHelper may not be initialised for file opening operations |
2012 // note aFileCreationHelper may not be initialised for file opening operations |
2004 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && clusterNum != DosEntryPos1.iCluster) |
2013 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && clusterNum != DosEntryPos1.iCluster) |
2005 { |
2014 { |
2006 TEntryPos dummyPos(clusterNum, clSize - KSizeOfFatDirEntry); |
2015 TEntryPos dummyPos(clusterNum, clSize - KSizeOfFatDirEntry); |
2007 aFileCreationHelper->SetEntryAddingPos(dummyPos); |
2016 aFileCreationHelper->SetEntryAddingPos(dummyPos); |
2008 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2017 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2009 } |
2018 } |
2010 |
2019 |
2011 if (ScanMRUPageFirst && !MRUPageScanned) |
2020 if (ScanMRUPageFirst && !MRUPageScanned) |
2012 { |
2021 { |
2013 DosEntryPos1 = aDosEntryPos; |
2022 DosEntryPos1 = aDosEntryPos; |
2014 MRUPageScanned = ETrue; |
2023 MRUPageScanned = ETrue; |
2015 continue; |
2024 continue; |
2016 } |
2025 } |
2017 break; //-- this was the last cluster in this directory |
2026 break; //-- this was the last cluster in this directory |
2018 } |
2027 } |
2019 |
2028 |
2020 const TUint32 pageStartPos = CalculatePageOffsetInCluster(DosEntryPos1.iPos, pageSzLog2); |
2029 const TUint32 pageStartPos = CalculatePageOffsetInCluster(DosEntryPos1.iPos, pageSzLog2); |
2021 DosEntryPos1.iPos = pageStartPos; |
2030 DosEntryPos1.iPos = pageStartPos; |
2022 TBool PassedPageBoundary = EFalse; |
2031 TBool PassedPageBoundary = EFalse; |
2023 |
2032 |
2024 const TInt64 entryLinPos = MakeLinAddrL(DosEntryPos1); //-- linear media position of the cluster for this directory |
2033 const TInt64 entryLinPos = MakeLinAddrL(DosEntryPos1); //-- linear media position of the cluster for this directory |
2025 const TUint32 cachePageSz = pDirCache->PosCached(entryLinPos, nCachedLinPos); //-- indicates if entryLinPos is cached |
2034 const TUint32 cachePageSz = pDirCache->PosCached(entryLinPos, nCachedLinPos); //-- indicates if entryLinPos is cached |
2026 if(cachePageSz) |
2035 if(cachePageSz) |
2027 {//-- current page is in the directory cache |
2036 {//-- current page is in the directory cache |
2043 nErr = GetDirEntry(DosEntryPos1, DosEntry1, StartEntry1, aFileName); |
2052 nErr = GetDirEntry(DosEntryPos1, DosEntry1, StartEntry1, aFileName); |
2044 if(nErr != KErrNone) |
2053 if(nErr != KErrNone) |
2045 break; |
2054 break; |
2046 |
2055 |
2047 if(DosEntry1.IsEndOfDirectory()) |
2056 if(DosEntry1.IsEndOfDirectory()) |
2048 { |
2057 { |
2049 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2058 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2050 { |
2059 { |
2051 // note it is impossible to be at the end of the cluster chain here. |
2060 // note it is impossible to be at the end of the cluster chain here. |
2052 aFileCreationHelper->SetEntryAddingPos(DosEntryPos1); |
2061 aFileCreationHelper->SetEntryAddingPos(DosEntryPos1); |
2053 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2062 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2054 } |
2063 } |
2055 |
2064 |
2056 if (ScanMRUPageFirst && !MRUPageScanned) |
2065 if (ScanMRUPageFirst && !MRUPageScanned) |
2057 { |
2066 { |
2058 break; |
2067 break; |
2059 } |
2068 } |
2060 |
2069 |
2061 // if (!ScanMRUPageFirst || ScanMRUPageFirst && MRUPageScanned) |
2070 // if (!ScanMRUPageFirst || ScanMRUPageFirst && MRUPageScanned) |
2062 goto Exit; //-- this was the last entry in this directory, no reason to look further |
2071 goto Exit; //-- this was the last entry in this directory, no reason to look further |
2063 } |
2072 } |
2064 |
2073 |
2065 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2074 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2066 { |
2075 { |
2067 if (!DosEntry1.IsErased() && !DosEntry1.IsGarbage()) |
2076 if (!DosEntry1.IsErased() && !DosEntry1.IsGarbage()) |
2068 { |
2077 { |
2069 numFound = 0; |
2078 numFound = 0; |
2070 } |
2079 } |
2071 else |
2080 else |
2072 { |
2081 { |
2073 if (numFound == 0) |
2082 if (numFound == 0) |
2074 { |
2083 { |
2075 startPos = DosEntryPos1; |
2084 startPos = DosEntryPos1; |
2076 } |
2085 } |
2077 numFound++; |
2086 numFound++; |
2078 if (numFound == aFileCreationHelper->NumOfAddingEntries()) |
2087 if (numFound == aFileCreationHelper->NumOfAddingEntries()) |
2079 { |
2088 { |
2080 aFileCreationHelper->SetEntryAddingPos(startPos); |
2089 aFileCreationHelper->SetEntryAddingPos(startPos); |
2081 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2090 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2082 } |
2091 } |
2083 } |
2092 } |
2084 } |
2093 } |
2085 if(MatchEntryAtt(DosEntry1.Attributes(),anAtt)) |
2094 if(MatchEntryAtt(DosEntry1.Attributes(),anAtt)) |
2086 {//-- FAT or VFAT dir entry is extracted and attributes match. Compare names then. |
2095 {//-- FAT or VFAT dir entry is extracted and attributes match. Compare names then. |
2087 |
2096 |
2088 if(StartEntry1.IsVFatEntry()) |
2097 if(StartEntry1.IsVFatEntry()) |
2089 {//-- extracted entry is VFAT one, name can be in UNICODE |
2098 {//-- extracted entry is VFAT one, name can be in UNICODE |
2090 |
2099 |
2091 // we only check short name candidates for long file names with VFAT entries, |
2100 // we only check short name candidates for long file names with VFAT entries, |
2092 // if it is a valid dos name, it will be checked by default |
2101 // if it is a valid dos name, it will be checked by default |
2093 // note here target name is always fully specified |
2102 // note here target name is always fully specified |
2094 if (aFileCreationHelper && aFileCreationHelper->IsInitialised()) |
2103 if (aFileCreationHelper && aFileCreationHelper->IsInitialised()) |
2095 { |
2104 { |
2096 aFileCreationHelper->CheckShortNameCandidates(DosEntry1.Name().Ptr()); |
2105 aFileCreationHelper->CheckShortNameCandidates(DosEntry1.Name().Ptr()); |
2097 } |
2106 } |
2098 |
2107 |
2099 TPtrC ptrAssembledName = RemoveTrailingDots(aFileName); |
2108 TPtrC ptrAssembledName = RemoveTrailingDots(aFileName); |
2100 |
2109 |
2101 if(ptrAssembledName.MatchF(aAuxParam.iTargetName) != KErrNotFound) |
2110 if(ptrAssembledName.MatchF(aAuxParam.iTargetName) != KErrNotFound) |
2102 {//-- found match in cache |
2111 {//-- found match in cache |
2306 const TInt KShortNameCandidatesNum = 4; |
2315 const TInt KShortNameCandidatesNum = 4; |
2307 /** |
2316 /** |
2308 Constructor of XFileCreationHelper class |
2317 Constructor of XFileCreationHelper class |
2309 */ |
2318 */ |
2310 CFatMountCB::XFileCreationHelper::XFileCreationHelper() |
2319 CFatMountCB::XFileCreationHelper::XFileCreationHelper() |
2311 { |
2320 { |
2312 isInitialised = EFalse; |
2321 isInitialised = EFalse; |
2313 } |
2322 } |
2314 |
2323 |
2315 /** |
2324 /** |
2316 Destructor of XFileCreationHelper class |
2325 Destructor of XFileCreationHelper class |
2317 */ |
2326 */ |
2318 CFatMountCB::XFileCreationHelper::~XFileCreationHelper() |
2327 CFatMountCB::XFileCreationHelper::~XFileCreationHelper() |
2319 { |
2328 { |
2320 Close(); |
2329 Close(); |
2321 } |
2330 } |
2322 |
2331 |
2323 /** |
2332 /** |
2324 Initialises a TFileCreationHelper object, generate a short name candidate pool. |
2333 Initialises a TFileCreationHelper object, generate a short name candidate pool. |
2325 |
2334 |
2326 @param aTargetName Target file name for the potential new file. |
2335 @param aTargetName Target file name for the potential new file. |
2327 @post TFileCreationHelper is fully initialised. |
2336 @post TFileCreationHelper is fully initialised. |
2328 */ |
2337 */ |
2329 void CFatMountCB::XFileCreationHelper::InitialiseL(const TDesC& aTargetName) |
2338 void CFatMountCB::XFileCreationHelper::InitialiseL(const TDesC& aTargetName) |
2330 { |
2339 { |
2331 // close before use, to avoid memory leak |
2340 // close before use, to avoid memory leak |
2332 Close(); |
2341 Close(); |
2333 |
2342 |
2334 iTargetName.Set(aTargetName); |
2343 iTargetName.Set(aTargetName); |
2335 // generates short name candidate(s) |
2344 // generates short name candidate(s) |
2336 TInt count = 1; |
2345 TInt count = 1; |
2337 while (count <= KShortNameCandidatesNum) |
2346 while (count <= KShortNameCandidatesNum) |
2338 { |
2347 { |
2339 TShortName shortNameCandidate = DoGenerateShortNameL(aTargetName, count, ETrue); |
2348 TShortName shortNameCandidate = DoGenerateShortNameL(aTargetName, count, ETrue); |
2340 TInt err = iShortNameCandidates.Append(shortNameCandidate); |
2349 TInt err = iShortNameCandidates.Append(shortNameCandidate); |
2341 User::LeaveIfError(err); |
2350 User::LeaveIfError(err); |
2342 |
2351 |
2343 if (count == -1) // No tilde and number is needed |
2352 if (count == -1) // No tilde and number is needed |
2344 { |
2353 { |
2345 break; |
2354 break; |
2346 } |
2355 } |
2347 else |
2356 else |
2348 count++; |
2357 count++; |
2349 } |
2358 } |
2350 |
2359 |
2351 // calculate number of new entries needed |
2360 // calculate number of new entries needed |
2352 iNumOfAddingEntries = 1; |
2361 iNumOfAddingEntries = 1; |
2353 isTrgNameLegalDosName = IsLegalDosName(aTargetName, EFalse, EFalse, EFalse, EFalse, ETrue); |
2362 isTrgNameLegalDosName = IsLegalDosName(aTargetName, EFalse, EFalse, EFalse, EFalse, ETrue); |
2354 if (!isTrgNameLegalDosName) |
2363 if (!isTrgNameLegalDosName) |
2355 iNumOfAddingEntries = (TUint16) NumberOfVFatEntries(iTargetName.Length()); |
2364 iNumOfAddingEntries = (TUint16) NumberOfVFatEntries(iTargetName.Length()); |
2356 |
2365 |
2357 isNewEntryPosFound = EFalse; |
2366 isNewEntryPosFound = EFalse; |
2358 isInitialised = ETrue; |
2367 isInitialised = ETrue; |
2359 } |
2368 } |
2360 |
2369 |
2361 /** |
2370 /** |
2362 Close function of XFileCreationHelper class |
2371 Close function of XFileCreationHelper class |
2363 */ |
2372 */ |
2364 void CFatMountCB::XFileCreationHelper::Close() |
2373 void CFatMountCB::XFileCreationHelper::Close() |
2365 { |
2374 { |
2366 iShortNameCandidates.Close(); |
2375 iShortNameCandidates.Close(); |
2367 isInitialised = EFalse; |
2376 isInitialised = EFalse; |
2368 } |
2377 } |
2369 |
2378 |
2370 /** |
2379 /** |
2371 Validates short name candidates. If the input dos entry name is found in the short name |
2380 Validates short name candidates. If the input dos entry name is found in the short name |
2372 candidate pool, the corresponding short name candidate will be removed from the pool. |
2381 candidate pool, the corresponding short name candidate will be removed from the pool. |
2373 |
2382 |
2374 @param apDosEntryName An existing short name, to compare with the candidates. |
2383 @param apDosEntryName An existing short name, to compare with the candidates. |
2375 @pre Object should be initialised |
2384 @pre Object should be initialised |
2376 */ |
2385 */ |
2377 void CFatMountCB::XFileCreationHelper::CheckShortNameCandidates(const TUint8* apDosEntryName) |
2386 void CFatMountCB::XFileCreationHelper::CheckShortNameCandidates(const TUint8* apDosEntryName) |
2378 { |
2387 { |
2379 ASSERT(isInitialised); |
2388 ASSERT(isInitialised); |
2380 if (!isInitialised) |
2389 if (!isInitialised) |
2381 return; |
2390 return; |
2382 |
2391 |
2383 if (iShortNameCandidates.Count() > 0) |
2392 if (iShortNameCandidates.Count() > 0) |
2384 { |
2393 { |
2385 for (TInt i = 0; i < iShortNameCandidates.Count(); i++) |
2394 for (TInt i = 0; i < iShortNameCandidates.Count(); i++) |
2386 { |
2395 { |
2387 if (Mem::Compare(iShortNameCandidates[i].Ptr(), KFatDirNameSize, apDosEntryName, KFatDirNameSize) == 0) |
2396 if (Mem::Compare(iShortNameCandidates[i].Ptr(), KFatDirNameSize, apDosEntryName, KFatDirNameSize) == 0) |
2388 { |
2397 { |
2389 iShortNameCandidates.Remove(i); |
2398 iShortNameCandidates.Remove(i); |
2390 break; |
2399 break; |
2391 } |
2400 } |
2392 } |
2401 } |
2393 } |
2402 } |
2394 } |
2403 } |
2395 |
2404 |
2396 /** |
2405 /** |
2397 Gets a validated short name from the short name candidate pool. |
2406 Gets a validated short name from the short name candidate pool. |
2398 |
2407 |
2399 @param aShortName On return, contains a validated short name if found, otherwise zeroed. |
2408 @param aShortName On return, contains a validated short name if found, otherwise zeroed. |
2400 @return TInt Returns KErrNone if a validated short name found successfully, |
2409 @return TInt Returns KErrNone if a validated short name found successfully, |
2401 else KErrNotFound is returned. |
2410 else KErrNotFound is returned. |
2402 Returns KErrNotReady if object is not initialised. |
2411 Returns KErrNotReady if object is not initialised. |
2403 @pre Object should be initialised |
2412 @pre Object should be initialised |
2404 */ |
2413 */ |
2405 TInt CFatMountCB::XFileCreationHelper::GetValidatedShortName(TShortName& aShortName) const |
2414 TInt CFatMountCB::XFileCreationHelper::GetValidatedShortName(TShortName& aShortName) const |
2406 { |
2415 { |
2407 aShortName.Zero(); |
2416 aShortName.Zero(); |
2408 |
2417 |
2409 ASSERT(isInitialised); |
2418 ASSERT(isInitialised); |
2410 if (!isInitialised) |
2419 if (!isInitialised) |
2411 return KErrNotReady; |
2420 return KErrNotReady; |
2412 |
2421 |
2413 if (iShortNameCandidates.Count() > 0) |
2422 if (iShortNameCandidates.Count() > 0) |
2414 { |
2423 { |
2415 aShortName.Copy(iShortNameCandidates[0]); |
2424 aShortName.Copy(iShortNameCandidates[0]); |
2416 return KErrNone; |
2425 return KErrNone; |
2417 } |
2426 } |
2418 |
2427 |
2419 return KErrNotFound; |
2428 return KErrNotFound; |
2420 } |
2429 } |
2421 |
2430 |
2422 //----------------------------------------------------------------------------------------- |
2431 //----------------------------------------------------------------------------------------- |
2423 |
2432 |
2424 |
2433 |
2425 /** |
2434 /** |
2517 // we need to scan ahead from the mru pos then come back to beginning, if startcluster is provided |
2526 // we need to scan ahead from the mru pos then come back to beginning, if startcluster is provided |
2518 TBool scanAhead = EFalse; |
2527 TBool scanAhead = EFalse; |
2519 // if we have a starting cluster number (and it's not root directory in FAT16/12 case)&& |
2528 // if we have a starting cluster number (and it's not root directory in FAT16/12 case)&& |
2520 // we found a lastScanned entry's cluster (and it's not root directory in FAT16/12 case)&& |
2529 // we found a lastScanned entry's cluster (and it's not root directory in FAT16/12 case)&& |
2521 // if we don't have a starting cluster number, we draw back to original scanning algorithm |
2530 // if we don't have a starting cluster number, we draw back to original scanning algorithm |
2522 if (!IsRootDir(aDosEntryPos) // we don't do forward scanning for root dir & |
2531 if (!IsRootDir(aDosEntryPos) // we don't do forward scanning for root dir & |
2523 && aLeafDirData.iClusterNum != 0 // if we have a starting cluster number & |
2532 && aLeafDirData.iClusterNum != 0 // if we have a starting cluster number & |
2524 && aLeafDirData.iMRUPos.Cluster() != 0) // if we have a starting cluster number & |
2533 && aLeafDirData.iMRUPos.Cluster() != 0) // if we have a starting cluster number & |
2525 { |
2534 { |
2526 scanAhead = ETrue; |
2535 scanAhead = ETrue; |
2527 aDosEntryPos = aLeafDirData.iMRUPos; |
2536 aDosEntryPos = aLeafDirData.iMRUPos; |
2528 } |
2537 } |
2529 |
2538 |
2530 TInt numFound = 0; |
2539 TInt numFound = 0; |
2531 TEntryPos startPos = aDosEntryPos; |
2540 TEntryPos startPos = aDosEntryPos; |
2532 TInt clustNum = aDosEntryPos.Cluster(); |
2541 TInt clustNum = aDosEntryPos.Cluster(); |
2533 |
2542 |
2534 for (TInt scanCnt = 1; scanCnt <= 2; ++scanCnt) |
2543 for (TInt scanCnt = 1; scanCnt <= 2; ++scanCnt) |
2535 { |
2544 { |
2536 // if we are not scanning ahead, we don't need this outer for loop |
2545 // if we are not scanning ahead, we don't need this outer for loop |
2537 if (!scanAhead) |
2546 if (!scanAhead) |
2538 scanCnt++; |
2547 scanCnt++; |
2539 |
2548 |
2540 TBool found = EFalse; |
2549 TBool found = EFalse; |
2541 |
2550 |
2542 FOREVER //FOREVER2 -- walk through all directory entries in the current directory until find a match or directory end |
2551 FOREVER //FOREVER2 -- walk through all directory entries in the current directory until find a match or directory end |
2543 { |
2552 { |
2544 //-- read full directory entry starting from aDosEntryPos. On return aFileName may contain assembled long filename (if the entry is VFAT) |
2553 //-- read full directory entry starting from aDosEntryPos. On return aFileName may contain assembled long filename (if the entry is VFAT) |
2545 //-- aDosEntry will contain a DOS entry of the directory entry we have read. |
2554 //-- aDosEntry will contain a DOS entry of the directory entry we have read. |
2546 aStartEntryPos=aDosEntryPos; |
2555 aStartEntryPos=aDosEntryPos; |
2547 User::LeaveIfError(GetDirEntry(aDosEntryPos, aDosEntry, aStartEntry, aFileName)); |
2556 User::LeaveIfError(GetDirEntry(aDosEntryPos, aDosEntry, aStartEntry, aFileName)); |
2548 |
2557 |
2549 if (aDosEntry.IsEndOfDirectory()) |
2558 if (aDosEntry.IsEndOfDirectory()) |
2550 {//-- the end of directory reached. |
2559 {//-- the end of directory reached. |
2551 |
2560 |
2552 // if new entry position for adding has not been found yet. |
2561 // if new entry position for adding has not been found yet. |
2553 // note aFileCreationHelper may not be initialised for pure file opening operations |
2562 // note aFileCreationHelper may not be initialised for pure file opening operations |
2554 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2563 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2555 { |
2564 { |
2556 // if MoveToNextEntryL have gone to the next cluster which is the end of cluster chain, |
2565 // if MoveToNextEntryL have gone to the next cluster which is the end of cluster chain, |
2557 // we pass the last scanned entry position to AddDirEntryL |
2566 // we pass the last scanned entry position to AddDirEntryL |
2558 if (IsEndOfClusterCh(aDosEntryPos.iCluster)) |
2567 if (IsEndOfClusterCh(aDosEntryPos.iCluster)) |
2559 { |
2568 { |
2560 TInt clusterSize=1<<ClusterSizeLog2(); |
2569 TInt clusterSize=1<<ClusterSizeLog2(); |
2561 TEntryPos dummyPos(clustNum, clusterSize - KSizeOfFatDirEntry); |
2570 TEntryPos dummyPos(clustNum, clusterSize - KSizeOfFatDirEntry); |
2562 aFileCreationHelper->SetEntryAddingPos(dummyPos); |
2571 aFileCreationHelper->SetEntryAddingPos(dummyPos); |
2563 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2572 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2564 } |
2573 } |
2565 // or we reached the end of the directory. |
2574 // or we reached the end of the directory. |
2566 else |
2575 else |
2567 { |
2576 { |
2568 aFileCreationHelper->SetEntryAddingPos(aDosEntryPos); |
2577 aFileCreationHelper->SetEntryAddingPos(aDosEntryPos); |
2569 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2578 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2570 } |
2579 } |
2571 } |
2580 } |
2572 |
2581 |
2573 // if we are scanning ahead and this is the first scanning, we break out to restart scanning |
2582 // if we are scanning ahead and this is the first scanning, we break out to restart scanning |
2574 if (scanAhead && scanCnt == 1) |
2583 if (scanAhead && scanCnt == 1) |
2575 { |
2584 { |
2576 break; // from FOREVER, restart scanning |
2585 break; // from FOREVER, restart scanning |
2577 } |
2586 } |
2578 |
2587 |
2579 // if (!scanAhead || scanAhead && scanCnt == 2) |
2588 // if (!scanAhead || scanAhead && scanCnt == 2) |
2580 User::Leave(anError); |
2589 User::Leave(anError); |
2581 } |
2590 } |
2582 |
2591 |
2583 |
2592 |
2584 // entry space searching for potential new file/directory creation |
2593 // entry space searching for potential new file/directory creation |
2585 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2594 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && !aFileCreationHelper->IsNewEntryPosFound()) |
2586 { |
2595 { |
2587 if (!aDosEntry.IsErased() && !aDosEntry.IsGarbage()) |
2596 if (!aDosEntry.IsErased() && !aDosEntry.IsGarbage()) |
2588 { |
2597 { |
2589 numFound = 0; |
2598 numFound = 0; |
2590 } |
2599 } |
2591 else |
2600 else |
2592 { |
2601 { |
2593 if (numFound == 0) |
2602 if (numFound == 0) |
2594 { |
2603 { |
2595 startPos = aDosEntryPos; |
2604 startPos = aDosEntryPos; |
2596 } |
2605 } |
2597 numFound++; |
2606 numFound++; |
2598 if (numFound == aFileCreationHelper->NumOfAddingEntries()) |
2607 if (numFound == aFileCreationHelper->NumOfAddingEntries()) |
2599 { |
2608 { |
2600 aFileCreationHelper->SetEntryAddingPos(startPos); |
2609 aFileCreationHelper->SetEntryAddingPos(startPos); |
2601 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2610 aFileCreationHelper->SetIsNewEntryPosFound(ETrue); |
2602 } |
2611 } |
2603 } |
2612 } |
2604 } |
2613 } |
2605 |
2614 |
2606 |
2615 |
2607 if (IsRootDir(aDosEntryPos)&&(aDosEntryPos.iPos+StartOfRootDirInBytes()==(RootDirEnd()-KSizeOfFatDirEntry))) |
2616 if (IsRootDir(aDosEntryPos)&&(aDosEntryPos.iPos+StartOfRootDirInBytes()==(RootDirEnd()-KSizeOfFatDirEntry))) |
2608 if (aDosEntry.IsErased()) |
2617 if (aDosEntry.IsErased()) |
2609 { |
2618 { |
2610 User::Leave(anError);//Allows maximum number of entries in root directory |
2619 User::Leave(anError);//Allows maximum number of entries in root directory |
2611 } |
2620 } |
2612 |
2621 |
2613 |
2622 |
2614 const TBool bFileNameEntry = !aDosEntry.IsCurrentDirectory() && !aDosEntry.IsParentDirectory() && !aDosEntry.IsErased() && !aDosEntry.IsGarbage(); |
2623 const TBool bFileNameEntry = !aDosEntry.IsCurrentDirectory() && !aDosEntry.IsParentDirectory() && !aDosEntry.IsErased() && !aDosEntry.IsGarbage(); |
2615 |
2624 |
2616 if (bFileNameEntry && MatchEntryAtt(aDosEntry.Attributes(), anAtt)) |
2625 if (bFileNameEntry && MatchEntryAtt(aDosEntry.Attributes(), anAtt)) |
2617 {//-- we have read a filename entry and entry's attributes match required; compare names then. |
2626 {//-- we have read a filename entry and entry's attributes match required; compare names then. |
2618 |
2627 |
2619 if (trgNameIsWildCard) |
2628 if (trgNameIsWildCard) |
2620 { |
2629 { |
2621 found = ETrue; |
2630 found = ETrue; |
2622 break; //-- we were looking for '*' or '*.*', so will be satisfied with any current file name. |
2631 break; //-- we were looking for '*' or '*.*', so will be satisfied with any current file name. |
2623 } |
2632 } |
2624 |
2633 |
2625 |
2634 |
2626 if (aStartEntry.IsVFatEntry()) |
2635 if (aStartEntry.IsVFatEntry()) |
2627 {//-- we've read a VFAT entry, aFileName is supposed to contain long filename, aDosEntry - DOS entry for this name. |
2636 {//-- we've read a VFAT entry, aFileName is supposed to contain long filename, aDosEntry - DOS entry for this name. |
2628 //-- note: aFileName.Length() may be 0, while DOS entry (short name is OK) in the case of orphaned VFAT entries |
2637 //-- note: aFileName.Length() may be 0, while DOS entry (short name is OK) in the case of orphaned VFAT entries |
2629 |
2638 |
2630 |
2639 |
2631 // we only check short name candidates for long file names with VFAT entries, |
2640 // we only check short name candidates for long file names with VFAT entries, |
2632 // if it is a valid dos name, it will be checked by default |
2641 // if it is a valid dos name, it will be checked by default |
2633 // note, for file creation cases, target name will be always fully specified |
2642 // note, for file creation cases, target name will be always fully specified |
2634 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && trgNameFullySpecified) |
2643 if (aFileCreationHelper && aFileCreationHelper->IsInitialised() && trgNameFullySpecified) |
2635 { |
2644 { |
2636 aFileCreationHelper->CheckShortNameCandidates(aDosEntry.Name().Ptr()); |
2645 aFileCreationHelper->CheckShortNameCandidates(aDosEntry.Name().Ptr()); |
2637 } |
2646 } |
2638 |
2647 |
2639 //-- discard trailing dots from aFileName if present |
2648 //-- discard trailing dots from aFileName if present |
2640 TPtrC ptrAssembledName = RemoveTrailingDots(aFileName); |
2649 TPtrC ptrAssembledName = RemoveTrailingDots(aFileName); |
2641 |
2650 |
2642 if(ptrAssembledName.MatchF(trgtNameNoDot) != KErrNotFound) |
2651 if(ptrAssembledName.MatchF(trgtNameNoDot) != KErrNotFound) |
2643 { |
2652 { |
2644 found = ETrue; |
2653 found = ETrue; |
2645 break; //-- OK, found a match. |
2654 break; //-- OK, found a match. |
2646 } |
2655 } |
2647 else if (trgNameFullySpecified) |
2656 else if (trgNameFullySpecified) |
2648 { |
2657 { |
2649 //-- long name assembled by GetDirEntry() doesn't match the target. But if he target name is fully specified, |
2658 //-- long name assembled by GetDirEntry() doesn't match the target. But if he target name is fully specified, |
2650 //-- we need to compare corresponding DOS entries, because VFAT entries may be damaged, while DOS ones are OK. |
2659 //-- we need to compare corresponding DOS entries, because VFAT entries may be damaged, while DOS ones are OK. |
2651 findHelper.InitialiseL(trgtNameNoDot); |
2660 findHelper.InitialiseL(trgtNameNoDot); |
2652 |
2661 |
2653 if(findHelper.MatchDosEntryName(aDosEntry.Name().Ptr())) |
2662 if(findHelper.MatchDosEntryName(aDosEntry.Name().Ptr())) |
2654 { |
2663 { |
2655 found = ETrue; |
2664 found = ETrue; |
2656 break; //-- DOS entries match, success. |
2665 break; //-- DOS entries match, success. |
2657 } |
2666 } |
2658 } |
2667 } |
2659 else if (!trgNameFullySpecified) |
2668 else if (!trgNameFullySpecified) |
2660 {//-- target name contains wildcards, we need to use MatchF with dos name |
2669 {//-- target name contains wildcards, we need to use MatchF with dos name |
2661 TBuf8<0x20> dosName8(DosNameFromStdFormat(aDosEntry.Name())); |
2670 TBuf8<0x20> dosName8(DosNameFromStdFormat(aDosEntry.Name())); |
2662 TBuf<0x20> dosName; |
2671 TBuf<0x20> dosName; |
2663 LocaleUtils::ConvertToUnicodeL(dosName, dosName8); //-- convert DOS name to unicode (implies locale settings) |
2672 LocaleUtils::ConvertToUnicodeL(dosName, dosName8); //-- convert DOS name to unicode (implies locale settings) |
2664 if (dosName.MatchF(trgtNameNoDot)!=KErrNotFound) |
2673 if (dosName.MatchF(trgtNameNoDot)!=KErrNotFound) |
2665 { |
2674 { |
2666 found = ETrue; |
2675 found = ETrue; |
2667 break; |
2676 break; |
2668 } |
2677 } |
2669 } |
2678 } |
2670 |
2679 |
2671 |
2680 |
2672 } |
2681 } |
2673 else //if (aStartEntry.IsVFatEntry()) |
2682 else //if (aStartEntry.IsVFatEntry()) |
2674 {//-- we've read a legacy FAT entry, so compare DOS entries |
2683 {//-- we've read a legacy FAT entry, so compare DOS entries |
2675 findHelper.InitialiseL(trgtNameNoDot); |
2684 findHelper.InitialiseL(trgtNameNoDot); |
2676 |
2685 |
2677 if(findHelper.TrgtNameIsLegalDos()) |
2686 if(findHelper.TrgtNameIsLegalDos()) |
2678 {//-- we are looking for a legal DOS name |
2687 {//-- we are looking for a legal DOS name |
2679 if(trgNameFullySpecified) |
2688 if(trgNameFullySpecified) |
2680 {//-- if the target name is fully specified, we can yse binary comparison of the DOS entries |
2689 {//-- if the target name is fully specified, we can yse binary comparison of the DOS entries |
2681 if(findHelper.MatchDosEntryName(aDosEntry.Name().Ptr())) |
2690 if(findHelper.MatchDosEntryName(aDosEntry.Name().Ptr())) |
2682 { |
2691 { |
2683 found = ETrue; |
2692 found = ETrue; |
2684 break; |
2693 break; |
2685 } |
2694 } |
2686 } |
2695 } |
2687 else |
2696 else |
2688 {//-- target name contains wildcards, we neeed to use MatchF |
2697 {//-- target name contains wildcards, we neeed to use MatchF |
2689 TBuf8<0x20> dosName8(DosNameFromStdFormat(aDosEntry.Name())); |
2698 TBuf8<0x20> dosName8(DosNameFromStdFormat(aDosEntry.Name())); |
2690 TBuf<0x20> dosName; |
2699 TBuf<0x20> dosName; |
2691 LocaleUtils::ConvertToUnicodeL(dosName, dosName8); //-- convert DOS name to unicode (implies locale settings) |
2700 LocaleUtils::ConvertToUnicodeL(dosName, dosName8); //-- convert DOS name to unicode (implies locale settings) |
2692 if (dosName.MatchF(trgtNameNoDot)!=KErrNotFound) |
2701 if (dosName.MatchF(trgtNameNoDot)!=KErrNotFound) |
2693 { |
2702 { |
2694 found = ETrue; |
2703 found = ETrue; |
2695 break; |
2704 break; |
2696 } |
2705 } |
2697 |
2706 |
2698 } |
2707 } |
2699 } //if(findHelper.TrgtNameIsLegalDos()) |
2708 } //if(findHelper.TrgtNameIsLegalDos()) |
2700 |
2709 |
2701 } //else if (aStartEntry.IsVFatEntry()) |
2710 } //else if (aStartEntry.IsVFatEntry()) |
2702 |
2711 |
2703 } //if (bFileNameEntry && MatchEntryAtt(aDosEntry.Attributes(),anAtt)) |
2712 } //if (bFileNameEntry && MatchEntryAtt(aDosEntry.Attributes(),anAtt)) |
2704 |
2713 |
2705 |
2714 |
2706 // record previous cluster number |
2715 // record previous cluster number |
2707 clustNum = aDosEntryPos.iCluster; |
2716 clustNum = aDosEntryPos.iCluster; |
2708 |
2717 |
2709 // this is the 2nd scanning and we have just passed the pos we started. |
2718 // this is the 2nd scanning and we have just passed the pos we started. |
2710 if (scanAhead && scanCnt == 2) |
2719 if (scanAhead && scanCnt == 2) |
2711 { |
2720 { |
2712 if (aDosEntryPos.Cluster() == aLeafDirData.iMRUPos.Cluster() |
2721 if (aDosEntryPos.Cluster() == aLeafDirData.iMRUPos.Cluster() |
2713 && aDosEntryPos.Pos() >= aLeafDirData.iMRUPos.Pos()) |
2722 && aDosEntryPos.Pos() >= aLeafDirData.iMRUPos.Pos()) |
2714 { |
2723 { |
2715 User::Leave(anError); |
2724 User::Leave(anError); |
2716 } |
2725 } |
2717 } |
2726 } |
2718 |
2727 |
2719 |
2728 |
2720 MoveToNextEntryL(aDosEntryPos); //-- goto the next entry in the directory |
2729 MoveToNextEntryL(aDosEntryPos); //-- goto the next entry in the directory |
2721 |
2730 |
2722 if (IsRootDir(aDosEntryPos)&&(aDosEntryPos.iPos+StartOfRootDirInBytes()>=RootDirEnd())) |
2731 if (IsRootDir(aDosEntryPos)&&(aDosEntryPos.iPos+StartOfRootDirInBytes()>=RootDirEnd())) |
2723 { |
2732 { |
2724 User::Leave(anError);//Allows maximum number of entries in root directory |
2733 User::Leave(anError);//Allows maximum number of entries in root directory |
2725 } |
2734 } |
2726 |
2735 |
2727 |
2736 |
2728 if (!scanAhead || scanCnt == 2) |
2737 if (!scanAhead || scanCnt == 2) |
2729 { |
2738 { |
2730 if (aDosEntryPos.iCluster && (aDosEntryPos.iPos <= previousPosition)) |
2739 if (aDosEntryPos.iCluster && (aDosEntryPos.iPos <= previousPosition)) |
2731 DoCheckFatForLoopsL(aDosEntryPos.iCluster,previousCluster,changePreviousCluster,count); |
2740 DoCheckFatForLoopsL(aDosEntryPos.iCluster,previousCluster,changePreviousCluster,count); |
2732 |
2741 |
2733 previousPosition=aDosEntryPos.iPos; |
2742 previousPosition=aDosEntryPos.iPos; |
2734 } |
2743 } |
2735 } // FOREVER -- the actual scanning is done inside this loop |
2744 } // FOREVER -- the actual scanning is done inside this loop |
2736 |
2745 |
2737 |
2746 |
2738 if (found) |
2747 if (found) |
2739 { |
2748 { |
2740 break; |
2749 break; |
2741 } |
2750 } |
2742 |
2751 |
2743 // if not found: |
2752 // if not found: |
2744 // if we have not found in the first scanning and we are doing scanning ahead, |
2753 // if we have not found in the first scanning and we are doing scanning ahead, |
2745 // we need to go back to the starting pos of this dir and scan from start until |
2754 // we need to go back to the starting pos of this dir and scan from start until |
2746 // we reach lastscannedPos |
2755 // we reach lastscannedPos |
2747 if (scanAhead && scanCnt == 1) |
2756 if (scanAhead && scanCnt == 1) |
2748 { |
2757 { |
2749 aDosEntryPos = TEntryPos(aLeafDirData.iClusterNum, 0); |
2758 aDosEntryPos = TEntryPos(aLeafDirData.iClusterNum, 0); |
2750 continue; |
2759 continue; |
2751 } |
2760 } |
2752 else |
2761 else |
2753 { |
2762 { |
2754 // there are only two exits: either found or reached end of dir in the 1st scanning |
2763 // there are only two exits: either found or reached end of dir in the 1st scanning |
2755 ASSERT(0); |
2764 ASSERT(0); |
2756 break; |
2765 break; |
2757 } |
2766 } |
2758 } // for (TInt scanCnt = 1; scanCnt <= 2; ++scanCnt) |
2767 } // for (TInt scanCnt = 1; scanCnt <= 2; ++scanCnt) |
2759 |
2768 |
2760 //--------------------------------------------------- |
2769 //--------------------------------------------------- |
2761 if (iRawDisk->DirCacheInterface() && aDosEntryPos.Cluster()) |
2770 if (iRawDisk->DirCacheInterface() && aDosEntryPos.Cluster()) |
2762 { |
2771 { |
2763 TInt64 mruPos = MakeLinAddrL(aDosEntryPos); |
2772 TInt64 mruPos = MakeLinAddrL(aDosEntryPos); |
2764 iRawDisk->DirCacheInterface()->MakePageMRU(mruPos); |
2773 iRawDisk->DirCacheInterface()->MakePageMRU(mruPos); |
2765 |
2774 |
2766 // only update the leaf dir cache when the original cache index is provided |
2775 // only update the leaf dir cache when the original cache index is provided |
2767 if (aLeafDirData.iClusterNum) |
2776 if (aLeafDirData.iClusterNum) |
2768 { |
2777 { |
2769 iLeafDirCache->UpdateMRUPos(TLeafDirData(aLeafDirData.iClusterNum, aDosEntryPos)); |
2778 iLeafDirCache->UpdateMRUPos(TLeafDirData(aLeafDirData.iClusterNum, aDosEntryPos)); |
2770 } |
2779 } |
2771 } |
2780 } |
2772 |
2781 |
2773 return (aStartEntry.IsVFatEntry()); |
2782 return (aStartEntry.IsVFatEntry()); |
2774 } |
2783 } |
2775 |
2784 |
2776 //----------------------------------------------------------------------------------------- |
2785 //----------------------------------------------------------------------------------------- |
3189 dosEntryPos.iCluster=FindLeafDirL(RemoveTrailingDots(aName).Left(namePos), leafDir); |
3198 dosEntryPos.iCluster=FindLeafDirL(RemoveTrailingDots(aName).Left(namePos), leafDir); |
3190 dosEntryPos.iPos=0; |
3199 dosEntryPos.iPos=0; |
3191 TEntryPos startPos; |
3200 TEntryPos startPos; |
3192 TFatDirEntry startEntry; |
3201 TFatDirEntry startEntry; |
3193 DoFindL(RemoveTrailingDots(aName).Mid(namePos),KEntryAttMaskSupported, |
3202 DoFindL(RemoveTrailingDots(aName).Mid(namePos),KEntryAttMaskSupported, |
3194 startPos,startEntry,dosEntryPos,dosEntry, |
3203 startPos,startEntry,dosEntryPos,dosEntry, |
3195 fileName,KErrNotFound, |
3204 fileName,KErrNotFound, |
3196 NULL, |
3205 NULL, |
3197 leafDir); |
3206 leafDir); |
3198 |
3207 |
3199 // Check that reading from aPos for aLength lies within the file |
3208 // Check that reading from aPos for aLength lies within the file |
3200 // if aPos is within the file, and aLength is too long, read up to EOF |
3209 // if aPos is within the file, and aLength is too long, read up to EOF |
3201 // If aPos is beyond the end of the file, return a zero length descriptor |
3210 // If aPos is beyond the end of the file, return a zero length descriptor |
3202 |
3211 |
3203 TUint32 fileSize = dosEntry.Size(); |
3212 TUint32 fileSize = dosEntry.Size(); |
3204 if ((TUint)aPos>=fileSize) |
3213 if ((TUint)aPos>=fileSize) |
3205 User::Leave(KErrEof); |
3214 User::Leave(KErrEof); |
3206 |
3215 |
3207 if ((TUint)(aPos+aLength)>fileSize) |
3216 if ((TUint)(aPos+aLength)>fileSize) |
3208 aLength=fileSize-aPos; |
3217 aLength=fileSize-aPos; |
3209 |
3218 |
3210 TInt cluster=StartCluster(dosEntry); |
3219 TInt cluster=StartCluster(dosEntry); |
3211 TInt pos = aPos; |
3220 TInt pos = aPos; |
3212 |
3221 |
3213 TInt endCluster; |
3222 TInt endCluster; |
3214 TInt clusterSize=1<<ClusterSizeLog2(); // Size of file clusters |
3223 TInt clusterSize=1<<ClusterSizeLog2(); // Size of file clusters |
3215 TInt readTotal = 0; |
3224 TInt readTotal = 0; |
3216 |
3225 |
3217 // Total number of clusters in file |
3226 // Total number of clusters in file |
3218 TInt maxClusters=((fileSize+clusterSize-1)>>ClusterSizeLog2()); |
3227 TInt maxClusters=((fileSize+clusterSize-1)>>ClusterSizeLog2()); |
3219 |
3228 |
3220 // Read data |
3229 // Read data |
3221 FOREVER |
3230 FOREVER |
3222 { |
3231 { |
3223 // Get the maximum number of clusters that can be read contiguously |
3232 // Get the maximum number of clusters that can be read contiguously |
3224 TInt clusterListLen=FAT().CountContiguousClustersL(cluster,endCluster,maxClusters); |
3233 TInt clusterListLen=FAT().CountContiguousClustersL(cluster,endCluster,maxClusters); |
3225 __ASSERT_DEBUG(clusterListLen>0,Fault(EReadFileSectionFailed)); |
3234 __ASSERT_DEBUG(clusterListLen>0,Fault(EReadFileSectionFailed)); |
3226 |
3235 |
3227 // If start position within this block, then read some data |
3236 // If start position within this block, then read some data |
3228 if (pos<(clusterListLen<<ClusterSizeLog2())) |
3237 if (pos<(clusterListLen<<ClusterSizeLog2())) |
3229 { |
3238 { |
3230 // Read the remaining length or the entire cluster block whichever is smaller |
3239 // Read the remaining length or the entire cluster block whichever is smaller |
3231 TInt readLength = Min(aLength-readTotal,(clusterListLen<<ClusterSizeLog2())-pos); |
3240 TInt readLength = Min(aLength-readTotal,(clusterListLen<<ClusterSizeLog2())-pos); |
3232 __ASSERT_DEBUG(readLength>0,Fault(EReadFileSectionFailed)); |
3241 __ASSERT_DEBUG(readLength>0,Fault(EReadFileSectionFailed)); |
3233 TInt64 dataAddress=(FAT().DataPositionInBytes(cluster))+pos; |
3242 TInt64 dataAddress=(FAT().DataPositionInBytes(cluster))+pos; |
3234 iRawDisk->ReadL(dataAddress,readLength,aTrg,aMessage,readTotal); |
3243 iRawDisk->ReadL(dataAddress,readLength,aTrg,aMessage,readTotal); |
3235 readTotal += readLength; |
3244 readTotal += readLength; |
3236 |
3245 |
3237 if (readTotal == aLength) |
3246 if (readTotal == aLength) |
3238 return; |
3247 return; |
3239 |
3248 |
3240 pos += readLength; |
3249 pos += readLength; |
3241 } |
3250 } |
3242 |
3251 |
3243 // Get the next cluster in file |
3252 // Get the next cluster in file |
3244 pos-=(clusterListLen<<ClusterSizeLog2()); |
3253 pos-=(clusterListLen<<ClusterSizeLog2()); |
3245 #if defined(_DEBUG) |
3254 #if defined(_DEBUG) |
3246 TBool remainingClusters= |
3255 TBool remainingClusters= |
3247 #endif |
3256 #endif |
3248 ((CFatMountCB*)this)->FAT().GetNextClusterL(endCluster); |
3257 ((CFatMountCB*)this)->FAT().GetNextClusterL(endCluster); |
3249 __ASSERT_DEBUG(remainingClusters,Fault(EReadFileSectionFailed)); |
3258 __ASSERT_DEBUG(remainingClusters,Fault(EReadFileSectionFailed)); |
3250 cluster=endCluster; |
3259 cluster=endCluster; |
3251 } |
3260 } |
3252 } |
3261 } |
3253 |
3262 |
3254 |
3263 |
3255 //----------------------------------------------------------------------------------------- |
3264 //----------------------------------------------------------------------------------------- |
3256 |
3265 |
3571 TRAP(r,aMessage.WriteL(2,pVal,0)); |
3580 TRAP(r,aMessage.WriteL(2,pVal,0)); |
3572 if(r!=KErrNone) |
3581 if(r!=KErrNone) |
3573 return(r); |
3582 return(r); |
3574 break; |
3583 break; |
3575 } |
3584 } |
3576 case ELocalTimeForRemovableMediaOn: |
3585 case ELocalTimeForRemovableMediaOn: |
3577 { |
3586 { |
3578 FatFileSystem().SetUseLocalTime(ETrue); |
3587 FatFileSystem().SetUseLocalTime(ETrue); |
3579 break; |
3588 break; |
3580 } |
3589 } |
3581 case ELocalTimeForRemovableMediaOff: |
3590 case ELocalTimeForRemovableMediaOff: |
3582 { |
3591 { |
3583 FatFileSystem().SetUseLocalTime(EFalse); |
3592 FatFileSystem().SetUseLocalTime(EFalse); |
3584 break; |
3593 break; |
3585 } |
3594 } |
3586 case ELocalTimeUsedOnRemovableMedia: |
3595 case ELocalTimeUsedOnRemovableMedia: |
3587 { |
3596 { |
3588 TBool flag = FatFileSystem().GetUseLocalTime(); |
3597 TBool flag = FatFileSystem().GetUseLocalTime(); |
3589 TPckgC<TBool> flagPckg(flag); |
3598 TPckgC<TBool> flagPckg(flag); |
3590 TInt r = aMessage.Write(2, flagPckg); |
3599 TInt r = aMessage.Write(2, flagPckg); |
3591 if(r!=KErrNone) |
3600 if(r!=KErrNone) |
3592 return r; |
3601 return r; |
3593 break; |
3602 break; |
3594 } |
3603 } |
3595 case ECreationTime: |
3604 case ECreationTime: |
3596 { |
3605 { |
3597 CheckStateConsistentL(); |
3606 CheckStateConsistentL(); |
3598 |
3607 |
3599 TEntryPos firstEntryPos(RootIndicator(),0); |
3608 TEntryPos firstEntryPos(RootIndicator(),0); |
3600 TFatDirEntry firstEntry; |
3609 TFatDirEntry firstEntry; |
3601 //RFs::ControlIO restricts you to use narrow descriptors |
3610 //RFs::ControlIO restricts you to use narrow descriptors |
3602 //so convert narrow back to wide. |
3611 //so convert narrow back to wide. |
3603 TBuf8<KMaxPath> fileNameNarrow; |
3612 TBuf8<KMaxPath> fileNameNarrow; |
3604 aMessage.Read(2, fileNameNarrow); |
3613 aMessage.Read(2, fileNameNarrow); |
3605 |
3614 |
3606 TFileName fileNameWide; |
3615 TFileName fileNameWide; |
3607 fileNameWide.Copy(fileNameNarrow); |
3616 fileNameWide.Copy(fileNameNarrow); |
3608 |
3617 |
3609 //find the long file name entry |
3618 //find the long file name entry |
3610 TRAPD(r, FindEntryStartL(fileNameWide,KEntryAttMaskSupported,firstEntry,firstEntryPos) ); |
3619 TRAPD(r, FindEntryStartL(fileNameWide,KEntryAttMaskSupported,firstEntry,firstEntryPos) ); |
3611 if(r!=KErrNone) |
3620 if(r!=KErrNone) |
3612 return(r); |
3621 return(r); |
3613 //Find the corresponding 8.3 short name entry, for metadata |
3622 //Find the corresponding 8.3 short name entry, for metadata |
3614 MoveToDosEntryL(firstEntryPos,firstEntry); |
3623 MoveToDosEntryL(firstEntryPos,firstEntry); |
3615 TTime creationTime=0; |
3624 TTime creationTime=0; |
3616 TPckg<TTime> timePckg(creationTime); |
3625 TPckg<TTime> timePckg(creationTime); |
3617 SFatDirEntry* sEntry = reinterpret_cast<SFatDirEntry*>(firstEntry.iData); |
3626 SFatDirEntry* sEntry = reinterpret_cast<SFatDirEntry*>(firstEntry.iData); |
3618 creationTime = DosTimeToTTime(sEntry->iTimeC, sEntry->iDateC); |
3627 creationTime = DosTimeToTTime(sEntry->iTimeC, sEntry->iDateC); |
3619 r = aMessage.Write(3, timePckg); |
3628 r = aMessage.Write(3, timePckg); |
3620 if(r!=KErrNone) |
3629 if(r!=KErrNone) |
3621 return r; |
3630 return r; |
3622 break; |
3631 break; |
3623 } |
3632 } |
3624 case EDisableFATDirCache: |
3633 case EDisableFATDirCache: |
3625 { |
3634 { |
3626 MWTCacheInterface* pDirCache = iRawDisk->DirCacheInterface(); |
3635 MWTCacheInterface* pDirCache = iRawDisk->DirCacheInterface(); |
3627 TUint32 KEDisableFATDirCache = CDynamicDirCache::EDisableCache; |
3636 TUint32 KEDisableFATDirCache = CDynamicDirCache::EDisableCache; |
3628 pDirCache->Control(KEDisableFATDirCache, (TUint32) aParam1, NULL); |
3637 pDirCache->Control(KEDisableFATDirCache, (TUint32) aParam1, NULL); |
3629 break; |
3638 break; |
3630 } |
3639 } |
3631 case EDumpFATDirCache: |
3640 case EDumpFATDirCache: |
3632 { |
3641 { |
3633 MWTCacheInterface* pDirCache = iRawDisk->DirCacheInterface(); |
3642 MWTCacheInterface* pDirCache = iRawDisk->DirCacheInterface(); |
3634 TUint32 KEDumpFATDirCache = CDynamicDirCache::EDumpCache; |
3643 TUint32 KEDumpFATDirCache = CDynamicDirCache::EDumpCache; |
3635 pDirCache->Control(KEDumpFATDirCache, 0, NULL); |
3644 pDirCache->Control(KEDumpFATDirCache, 0, NULL); |
3636 break; |
3645 break; |
3637 } |
3646 } |
3638 case EFATDirCacheInfo: |
3647 case EFATDirCacheInfo: |
3639 { |
3648 { |
3640 MWTCacheInterface* pDirCache = iRawDisk->DirCacheInterface(); |
3649 MWTCacheInterface* pDirCache = iRawDisk->DirCacheInterface(); |
3641 TUint32 KEFATDirCacheInfo = CDynamicDirCache::ECacheInfo; |
3650 TUint32 KEFATDirCacheInfo = CDynamicDirCache::ECacheInfo; |
3642 pDirCache->Control(KEFATDirCacheInfo, 0, NULL); |
3651 pDirCache->Control(KEFATDirCacheInfo, 0, NULL); |
3643 break; |
3652 break; |
3644 } |
3653 } |
3645 |
3654 |
3646 |
3655 |
3647 default: return(KErrNotSupported); |
3656 default: return(KErrNotSupported); |
3648 } |
3657 } |
3649 return(KErrNone); |
3658 return(KErrNone); |