70 void CScanDrive::ConstructL(CFatMountCB* aMount) |
70 void CScanDrive::ConstructL(CFatMountCB* aMount) |
71 { |
71 { |
72 ASSERT(aMount); |
72 ASSERT(aMount); |
73 |
73 |
74 //--- setting up |
74 //--- setting up |
75 iMount=aMount; |
75 iMount = aMount; |
76 iGenericError = ENoErrors; |
76 iGenericError = ENoErrors; |
77 iDirError = ENoDirError; |
77 iDirError = ENoDirError; |
78 iMaxClusters = iMount->UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers |
78 iHangingClusters = 0; |
|
79 iMaxClusters = iMount->UsableClusters()+KFatFirstSearchCluster; //-- UsableClusters() doesn't count first 2 unused clusers |
79 //------------------------------ |
80 //------------------------------ |
80 |
81 |
81 //-- create bit vectors that will represent FAT on media and reconstructed by ScanDrive. Each bit in the vector represents 1 FAT cluster. |
82 //-- create bit vectors that will represent FAT on media and reconstructed by ScanDrive. Each bit in the vector represents 1 FAT cluster. |
82 const TUint32 KClustersNum = MaxClusters(); |
83 const TUint32 KClustersNum = MaxClusters(); |
83 |
84 |
92 } |
93 } |
93 |
94 |
94 //---------------------------------------------------------------------------------------------------- |
95 //---------------------------------------------------------------------------------------------------- |
95 /** |
96 /** |
96 FAT type-agnostic parser. Reads whole FAT and sets up a bit vector. |
97 FAT type-agnostic parser. Reads whole FAT and sets up a bit vector. |
97 for FAT12/16 it's OK, because the FAT12/16 is fully cached. |
98 For FAT12/16 it's OK, because the FAT12/16 is fully cached. |
98 */ |
99 */ |
99 void CScanDrive::DoParseFatL() |
100 void CScanDrive::DoParseFatL() |
100 { |
101 { |
101 const TInt KMaxClusters = MaxClusters(); |
102 const TInt KMaxClusters = MaxClusters(); |
102 |
103 |
107 for(TInt i=KFatFirstSearchCluster; i<KMaxClusters; ++i) |
108 for(TInt i=KFatFirstSearchCluster; i<KMaxClusters; ++i) |
108 { |
109 { |
109 const TUint32 nFatEntry = ReadFatL(i); |
110 const TUint32 nFatEntry = ReadFatL(i); |
110 |
111 |
111 //-- each '1' bit represents a used cluster |
112 //-- each '1' bit represents a used cluster |
112 if(nFatEntry != KSpareCluster) |
113 if(nFatEntry != KSpareCluster) |
113 iMediaFatBits.SetBit(i); |
114 iMediaFatBits.SetBit(i); |
114 } |
115 } |
115 } |
116 } |
116 |
117 |
117 //---------------------------------------------------------------------------------------------------- |
118 //---------------------------------------------------------------------------------------------------- |
123 void CScanDrive::DoParseFat32Buf(const TPtrC8& aBuf, TUint32& aCurrFatEntry) |
124 void CScanDrive::DoParseFat32Buf(const TPtrC8& aBuf, TUint32& aCurrFatEntry) |
124 { |
125 { |
125 ASSERT((aBuf.Size() & (sizeof(TFat32Entry)-1)) == 0); |
126 ASSERT((aBuf.Size() & (sizeof(TFat32Entry)-1)) == 0); |
126 |
127 |
127 const TInt KNumEntries = aBuf.Size() >> KFat32EntrySzLog2; |
128 const TInt KNumEntries = aBuf.Size() >> KFat32EntrySzLog2; |
128 const TFat32Entry* const pFatEntry = (const TFat32Entry*)(aBuf.Ptr()); |
129 const TFat32Entry* const pFatEntry = (const TFat32Entry*)(aBuf.Ptr()); |
129 |
130 |
130 for(TInt i=0; i<KNumEntries; ++i) |
131 for(TInt i=0; i<KNumEntries; ++i) |
131 { |
132 { |
132 if(aCurrFatEntry >= KFatFirstSearchCluster) |
133 if(aCurrFatEntry >= KFatFirstSearchCluster) |
133 { |
134 { |
159 |
160 |
160 const TUint32 KFatBufSz = 32*K1KiloByte; //-- buffer size for FAT reading. 32K seems to be optimal size |
161 const TUint32 KFatBufSz = 32*K1KiloByte; //-- buffer size for FAT reading. 32K seems to be optimal size |
161 |
162 |
162 iMediaFatBits.Fill(0); |
163 iMediaFatBits.Fill(0); |
163 |
164 |
164 RBuf8 buf; |
165 RBuf8 fatParseBuf; |
165 CleanupClosePushL(buf); |
166 CleanupClosePushL(fatParseBuf); |
166 |
167 |
167 //-- allocate memory for FAT parse buffer |
168 //-- allocate memory for FAT parse buffer |
168 buf.CreateMaxL(KFatBufSz); |
169 fatParseBuf.CreateMaxL(KFatBufSz); |
169 |
170 |
170 //-- read FAT directly from the media into the large buffer and parse it |
171 //-- read FAT directly from the media into the large buffer and parse it |
171 TUint32 rem = KFatSize; |
172 TUint32 rem = KFatSize; |
172 TUint32 mediaPos = KFat1StartPos; |
173 TUint32 mediaPos = KFat1StartPos; |
173 TUint32 currFatEntry = 0; |
174 TUint32 currFatEntry = 0; |
174 |
175 |
175 while(rem) |
176 while(rem) |
176 { |
177 { |
177 const TUint32 bytesToRead=Min(rem, KFatBufSz); |
178 const TUint32 bytesToRead=Min(rem, KFatBufSz); |
178 TPtrC8 ptrData(buf.Ptr(), bytesToRead); |
179 TPtrC8 ptrData(fatParseBuf.Ptr(), bytesToRead); |
179 |
180 |
180 //-- read portion of the FAT into buffer |
181 //-- read portion of the FAT into buffer |
181 User::LeaveIfError(iMount->LocalDrive()->Read(mediaPos, bytesToRead, buf)); |
182 User::LeaveIfError(iMount->LocalDrive()->Read(mediaPos, bytesToRead, fatParseBuf)); |
182 |
183 |
183 //-- parse the buffer and populate bit vector |
184 //-- parse the buffer and populate bit vector |
184 DoParseFat32Buf(ptrData, currFatEntry); |
185 DoParseFat32Buf(ptrData, currFatEntry); |
185 |
186 |
186 mediaPos += bytesToRead; |
187 mediaPos += bytesToRead; |
187 rem -= bytesToRead; |
188 rem -= bytesToRead; |
188 } |
189 } |
189 |
190 |
190 buf.Close(); |
191 fatParseBuf.Close(); |
191 CleanupStack::PopAndDestroy(&buf); |
192 CleanupStack::PopAndDestroy(&fatParseBuf); |
192 } |
193 } |
193 |
194 |
194 |
195 |
195 |
196 |
196 //---------------------------------------------------------------------------------------------------- |
197 //---------------------------------------------------------------------------------------------------- |
239 else |
240 else |
240 return iGenericError; |
241 return iGenericError; |
241 } |
242 } |
242 |
243 |
243 /** |
244 /** |
244 Sets the flag indicating than there are errors in filesystem structure |
245 Sets the flag indicating that there are errors in filesystem structure |
245 See ProblemsDiscovered() |
246 See ProblemsDiscovered() |
246 |
247 |
247 @param aError a code describing the error |
248 @param aError a code describing the error |
248 */ |
249 */ |
249 void CScanDrive::IndicateErrorsFound(TGenericError aError) |
250 void CScanDrive::IndicateErrorsFound(TGenericError aError) |
253 } |
254 } |
254 |
255 |
255 |
256 |
256 //---------------------------------------------------------------------------------------------------- |
257 //---------------------------------------------------------------------------------------------------- |
257 /** |
258 /** |
258 Start the scanner. The this calss description about what it actually does. |
259 Starts the scanner. |
259 @param aMode specifies the operational mode. |
260 |
|
261 @param aMode Specifies the operational mode. |
260 */ |
262 */ |
261 void CScanDrive::StartL(TScanDriveMode aMode) |
263 void CScanDrive::StartL(TScanDriveMode aMode) |
262 { |
264 { |
263 __PRINT2(_L("CScanDrive::StartL(%d), drive:%d"), aMode, iMount->DriveNumber()); |
265 __PRINT2(_L("CScanDrive::StartL(%d), drive:%d"), aMode, iMount->DriveNumber()); |
264 iScanDriveMode = aMode; |
266 iScanDriveMode = aMode; |
475 */ |
476 */ |
476 void CScanDrive::CheckDirStructureL() |
477 void CScanDrive::CheckDirStructureL() |
477 { |
478 { |
478 CheckDirL(iMount->RootIndicator()); |
479 CheckDirL(iMount->RootIndicator()); |
479 // Due to recursive nature of CheckDirL when a depth of |
480 // Due to recursive nature of CheckDirL when a depth of |
480 // KMaxScanDepth is reached clusters are stored in a list |
481 // KMaxScanDepth is reached, clusters are stored in a list |
481 // and passed into CheckDirL afresh |
482 // and passed into CheckDirL afresh |
482 |
483 |
483 for(TUint i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i) |
484 for(TUint i=0;i<KMaxArrayDepth && iClusterListArray[i]!=NULL;++i) |
484 { |
485 { |
485 RArray<TInt>* clusterList=iClusterListArray[i]; |
486 RArray<TInt>* clusterList=iClusterListArray[i]; |
657 |
658 |
658 while(clusterCount) |
659 while(clusterCount) |
659 { |
660 { |
660 if(IsClusterUsedL(aCluster)) |
661 if(IsClusterUsedL(aCluster)) |
661 {//-- this cluster already seems to belong to some other object; crosslinked cluster chain. Can't fix it. |
662 {//-- this cluster already seems to belong to some other object; crosslinked cluster chain. Can't fix it. |
662 __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); |
663 __PRINT1(_L("CScanDrive::RecordClusterChainL #1 %d"),aCluster); |
663 |
664 |
664 if(CheckDiskMode()) |
665 if(CheckDiskMode()) |
665 {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning |
666 {//-- in check disk mode this is an FS error; Indicate error and abort further scanning |
666 __PRINT(_L("CScanDrive::RecordClusterChainL #1.1")); |
667 __PRINT(_L("CScanDrive::RecordClusterChainL #1.1")); |
667 IndicateErrorsFound(EClusterAlreadyInUse); |
668 IndicateErrorsFound(EClusterAlreadyInUse); |
668 User::Leave(KErrCorrupt); |
669 User::Leave(KErrCorrupt); |
669 } |
670 } |
670 |
671 |
671 |
672 |
684 |
685 |
685 |
686 |
686 if(clusterCount==1) |
687 if(clusterCount==1) |
687 {//-- we have reached the end of the cluster chain |
688 {//-- we have reached the end of the cluster chain |
688 if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster))) |
689 if(!iMount->IsEndOfClusterCh(ReadFatL(aCluster))) |
689 {//-- seems to be a rugged FAT artefact; File truncation/extension had failed before and now file length is less than |
690 { |
690 //-- the corresponding cluster chain shall be. It will be truncated to the size recorded in file DOS entry. |
691 // According to the directory entry, we have reached the end of the cluster chain, |
691 iTruncationCluster = aCluster; |
692 // whereas in the media FAT, it is not. |
|
693 // This is a rugged FAT artefact; hanging cluster chain: |
|
694 // A cluster chain which is longer in the FAT table than is recorded in the corresponding directory entry |
|
695 // or not terminated by an EOC entry in FAT. |
|
696 // This is caused by: |
|
697 // - File truncation failing. |
|
698 // - OR file expanding failing during flushing to the media FAT. |
692 |
699 |
693 if(CheckDiskMode()) |
700 if(CheckDiskMode()) |
694 {//-- in check disk mode this is a FS error; Indicate error and abort furter scanning |
701 {//-- in check disk mode this is an FS error; Indicate error and abort further scanning |
695 __PRINT1(_L("CScanDrive::RecordClusterChainL #2 %d"),aCluster); |
702 __PRINT1(_L("CScanDrive::RecordClusterChainL #2 Hanging cluster=%d"),aCluster); |
696 IndicateErrorsFound(EInvalidEntrySize); |
703 IndicateErrorsFound(EInvalidEntrySize); |
697 User::Leave(KErrCorrupt); |
704 User::Leave(KErrCorrupt); |
698 } |
705 } |
|
706 |
|
707 // The chain will be truncated to the size recorded in the file's DOS entry and |
|
708 // the remaining lost cluster chain will be fixed later in CompareAndFixFatsL(). |
|
709 FixHangingClusterChainL(aCluster); |
699 } |
710 } |
700 |
711 |
701 //__PRINT1(_L("#--: %d -> EOC"), aCluster); |
712 //__PRINT1(_L("#--: %d -> EOC"), aCluster); |
702 MarkClusterUsedL(aCluster); |
713 MarkClusterUsedL(aCluster); |
703 return; |
714 return; |
760 break; |
771 break; |
761 |
772 |
762 if(!IsValidVFatEntry(aEntry,toFollow)) |
773 if(!IsValidVFatEntry(aEntry,toFollow)) |
763 return(EFalse); |
774 return(EFalse); |
764 } |
775 } |
765 |
776 // A sequence of VFat entries must end with a Dos entry to be valid. |
766 return(IsDosEntry(aEntry)); |
777 return(IsDosEntry(aEntry)); |
767 } |
778 } |
768 |
779 |
769 //---------------------------------------------------------------------------------------------------- |
780 //---------------------------------------------------------------------------------------------------- |
770 /** |
781 /** |
771 Check if an entry is valid VFat |
782 Check if an entry is valid VFat |
842 } |
853 } |
843 |
854 |
844 |
855 |
845 //---------------------------------------------------------------------------------------------------- |
856 //---------------------------------------------------------------------------------------------------- |
846 /** |
857 /** |
847 Scan for differnces in the new and old FAT table writing them to media if discovered |
858 Scan for differences in the new and old FAT table writing them to media if discovered |
848 It is supposed to be called in 'ScanDrive' mode only |
859 It is supposed to be called in 'ScanDrive' mode only |
849 |
860 |
850 @leave System wide error codes |
861 @leave System wide error codes |
851 */ |
862 */ |
852 void CScanDrive::CompareAndFixFatsL() |
863 void CScanDrive::CompareAndFixFatsL() |
882 { |
893 { |
883 ++nBadClusters; |
894 ++nBadClusters; |
884 continue; |
895 continue; |
885 } |
896 } |
886 |
897 |
887 //-- here we found a lost cluster. Its FAT entry will be replaced with KSpareCluster. In the case of multiple lost clusters FAT table will |
898 //-- Here we found a lost cluster. Its FAT entry will be replaced with KSpareCluster. |
888 //-- be flushed on media sector basis. It is much faster than flushing FAT after every write and will |
899 //-- In the case of multiple lost clusters FAT table will be flushed on media sector basis. |
889 //-- guarantee that FAT won't be corrupted if the media driver provides atomic sector write. |
900 //-- It is much faster than flushing FAT after every write and will guarantee |
|
901 //-- that FAT won't be corrupted if the media driver provides atomic sector write. |
890 if(nClustersFixed == 0) |
902 if(nClustersFixed == 0) |
891 {//-- this is the first lost cluster entry we found |
903 {//-- this is the first lost cluster entry we found |
892 |
904 |
893 //-- relative FAT media sector for the 'i' entry. The real value doesn't matter, |
905 //-- relative FAT media sector for the 'i' entry. The real value doesn't matter, |
894 //-- we will just be flushing FAT before writing to the different FAT media sector. |
906 //-- we will just be flushing FAT before writing to the different FAT media sector. |
899 else |
911 else |
900 { |
912 { |
901 const TUint32 fatSec = iMount->FAT().PosInBytes(i) >> KSectorSzLog2; |
913 const TUint32 fatSec = iMount->FAT().PosInBytes(i) >> KSectorSzLog2; |
902 |
914 |
903 if(fatSec != dirtyFatSector) |
915 if(fatSec != dirtyFatSector) |
904 {//-- we are going to write to a differrent media sector |
916 {//-- we are going to write to a different media sector |
905 iMount->FAT().FlushL(); |
917 iMount->FAT().FlushL(); |
906 iMount->FAT().WriteL(i, KSpareCluster); //-- fix lost cluster |
918 iMount->FAT().WriteL(i, KSpareCluster); //-- fix lost cluster |
907 dirtyFatSector = fatSec; |
919 dirtyFatSector = fatSec; |
908 } |
920 } |
909 else |
921 else |
925 if(nClustersFixed) |
937 if(nClustersFixed) |
926 iMount->FAT().FlushL(); |
938 iMount->FAT().FlushL(); |
927 |
939 |
928 //------ |
940 //------ |
929 |
941 |
930 if(iTruncationCluster != 0) |
942 |
931 { |
943 // Add the number of hanging clusters fixed by ScanDrive |
932 iMount->FAT().WriteFatEntryEofL(iTruncationCluster); |
944 nClustersFixed += iHangingClusters; |
933 iMount->FAT().FlushL(); |
945 |
934 |
946 __PRINT3(_L("CScanDrive::WriteNewFatsL() fixed clusters=%d,hanging clusters=%d,bad clusters=%d"),nClustersFixed,iHangingClusters,nBadClusters); |
935 //-- indicate that there are some problems in FAT. and we probably wrote something there. |
|
936 IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors |
|
937 |
|
938 ++nClustersFixed; |
|
939 } |
|
940 |
|
941 __PRINT2(_L("CScanDrive::WriteNewFatsL() fixed:%d, bad:%d"), nClustersFixed, nBadClusters); |
|
942 } |
947 } |
943 |
948 |
944 //---------------------------------------------------------------------------------------------------- |
949 //---------------------------------------------------------------------------------------------------- |
945 /** |
950 /** |
946 Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the |
951 Read the "Rugged FAT" ID, stored in reserved2 in the Dos entry or associated with the Dos entry of the |
947 Entry at the position passed in. This is used to find which version of two matching entries should be kept. |
952 Entry at the position passed in. This is used to find which version of two matching entries should be kept. |
948 |
|
949 |
953 |
950 @param aVFatPos Position of an entry to read ID from |
954 @param aVFatPos Position of an entry to read ID from |
951 @leave System wide error codes |
955 @leave System wide error codes |
952 @return The ID found in reserved2 field of dos entry |
956 @return The ID found in reserved2 field of dos entry |
953 */ |
957 */ |
1010 |
1014 |
1011 iMount->EraseDirEntryL(iMatching.iEntries[num],entry); |
1015 iMount->EraseDirEntryL(iMatching.iEntries[num],entry); |
1012 |
1016 |
1013 IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors |
1017 IndicateErrorsFound(EScanDriveDirError); //-- indicate that we have found errors |
1014 } |
1018 } |
|
1019 |
|
1020 //---------------------------------------------------------------------------------------------------- |
|
1021 /** |
|
1022 Fix a hanging cluster chain. |
|
1023 Writes EOF to the corresponding FAT entry, making this cluster chain length correspond to the |
|
1024 real file size recorded in the directory entry. |
|
1025 The remainder of the chain will be cleaned up later in CompareAndFixFatsL(). |
|
1026 |
|
1027 @leave System wide error code |
|
1028 */ |
|
1029 void CScanDrive::FixHangingClusterChainL(TUint32 aFatEofIndex) |
|
1030 { |
|
1031 __PRINT1(_L("CScanDrive::FixHangingClusterL() Hanging cluster=%d"), aFatEofIndex); |
|
1032 |
|
1033 iMount->FAT().WriteFatEntryEofL(aFatEofIndex); |
|
1034 iMount->FAT().FlushL(); |
|
1035 iHangingClusters++; |
|
1036 |
|
1037 // Indicate that we have found an error |
|
1038 IndicateErrorsFound(EScanDriveDirError); |
|
1039 } |
|
1040 |
1015 |
1041 |
1016 //---------------------------------------------------------------------------------------------------- |
1042 //---------------------------------------------------------------------------------------------------- |
1017 /** |
1043 /** |
1018 Move past specified number of entries |
1044 Move past specified number of entries |
1019 |
1045 |
1085 const TBool bNewFatEntry = iScanFatBits[i]; |
1111 const TBool bNewFatEntry = iScanFatBits[i]; |
1086 |
1112 |
1087 if(BoolXOR(bRealFatEntry, bNewFatEntry)) |
1113 if(BoolXOR(bRealFatEntry, bNewFatEntry)) |
1088 {//-- mismatch between FAT on the media and the FAT bitmap restored by walking directory structure |
1114 {//-- mismatch between FAT on the media and the FAT bitmap restored by walking directory structure |
1089 |
1115 |
1090 if(bRealFatEntry) |
1116 if(bRealFatEntry) |
1091 {//-- FAT[i] on the media is marked as occupied, but retored FAT bitmap shows that it is free |
1117 {//-- FAT[i] on the media is marked as occupied, but restored FAT bitmap shows that it is free |
1092 if(iMount->IsBadCluster(ReadFatL(i))) |
1118 if(iMount->IsBadCluster(ReadFatL(i))) |
1093 continue; //-- this is a BAD cluster it can't be occupied by the FS object, OK. |
1119 continue; //-- this is a BAD cluster it can't be occupied by the FS object, OK. |
1094 |
1120 |
1095 __PRINT2(_L("FAT[%d] = %d\n"), i, ReadFatL(i)); |
1121 __PRINT2(_L("FAT[%d] = %d\n"), i, ReadFatL(i)); |
1096 __PRINT1(_L("iTruncationCluster = %d\n"), iTruncationCluster); |
1122 |
1097 |
1123 //-- this is a Rugged FAT artefact; a lost cluster |
1098 //-- this is a lost cluster |
1124 __PRINT1(_L("Lost cluster=%d\n"),i); |
1099 if(!IsEofF(ReadFatL(i)) && (i==iTruncationCluster)) |
1125 |
1100 {//-- seems to be a Rugged FAT ertefact |
1126 IndicateErrorsFound(EBadClusterValue); |
1101 __PRINT1(_L("Hanging cluster = %d\n"),i); |
1127 } |
1102 } |
1128 else |
1103 else |
1129 {//-- FAT[i] on the media is marked as free, but restored FAT bitmap shows that it is occupied by some object |
1104 { |
1130 IndicateErrorsFound(EClusterAlreadyInUse); |
1105 __PRINT1(_L("Lost cluster=%d\n"),i); |
1131 __PRINT1(_L("Unflushed cluster = %d\n"),i); |
1106 } |
1132 } |
1107 |
1133 |
1108 |
1134 if(aStopOnFirstErrorFound) |
1109 IndicateErrorsFound(EBadClusterValue); |
1135 break; //-- not asked to check for errors further |
1110 } |
|
1111 else |
|
1112 {//-- FAT[i] on the media is marked as free, but retored FAT bitmap shows that it is occupied by some object |
|
1113 IndicateErrorsFound(EClusterAlreadyInUse); |
|
1114 __PRINT1(_L("Unflushed cluster = %d\n"),i); |
|
1115 } |
|
1116 |
|
1117 if(aStopOnFirstErrorFound) |
|
1118 break; //-- not asked to check for errors further |
|
1119 |
1136 |
1120 } |
1137 } |
1121 |
1138 |
1122 if(bRealFatEntry) |
1139 if(bRealFatEntry) |
1123 mediausedcnt++; |
1140 mediausedcnt++; |
1185 //__PRINT(_L("CScanDrive::MoveToNextEntryL")); |
1202 //__PRINT(_L("CScanDrive::MoveToNextEntryL")); |
1186 iMount->MoveToNextEntryL(aPos); |
1203 iMount->MoveToNextEntryL(aPos); |
1187 } |
1204 } |
1188 |
1205 |
1189 /** |
1206 /** |
1190 Read a cluster from the Media Fat if scan run in a seperate thread read from scan fat table |
1207 Read a cluster from the Media Fat if scan run in a separate thread read from scan Fat table |
1191 otherwise read from mount owned Fat table |
1208 otherwise read from mount owned Fat table |
1192 |
1209 |
1193 @param aClusterNum Cluster to read |
1210 @param aClusterNum Cluster to read |
1194 @return Value of cluster read from Fat |
1211 @return Value of cluster read from Fat |
1195 */ |
1212 */ |
1196 TUint32 CScanDrive::ReadFatL(TUint aClusterNum) |
1213 TUint32 CScanDrive::ReadFatL(TUint aClusterNum) |
1197 { |
1214 { |
1198 if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters()) |
1215 if(aClusterNum < KFatFirstSearchCluster || aClusterNum >= MaxClusters()) |
1199 { |
1216 { |
1200 __PRINT1(_L("CScanDrive::ReadFatL() bad cluster:%d\n"),aClusterNum); |
1217 __PRINT1(_L("CScanDrive::ReadFatL() bad cluster:%d\n"),aClusterNum); |
1201 IndicateErrorsFound(EBadClusterNumber); |
1218 IndicateErrorsFound(EBadClusterNumber); |