25 |
25 |
26 #include "sl_std.h" |
26 #include "sl_std.h" |
27 |
27 |
28 //--------------------------------------------------------------------------------------------------------------------------------- |
28 //--------------------------------------------------------------------------------------------------------------------------------- |
29 |
29 |
30 const TInt KMaxMatchingEntries = 2; ///< Maximum number of matching directory entries scan drive can fix. Any more indicates a fault in the file system |
30 const TUint KMaxMatchingEntries = 2; ///< Maximum number of matching directory entries scan drive can fix. Any more indicates a fault in the file system |
31 const TInt KMaxArrayDepth = 6; ///< Maximum array depth for cluster storage when KMaxScanDepth is reached |
31 const TUint KMaxArrayDepth = 6; ///< Maximum array depth for cluster storage when KMaxScanDepth is reached |
32 |
32 |
33 /** |
33 /** Data structure used to store the location of a partial VFat entry */ |
34 Data structure used to store the location of a partial VFat entry |
|
35 */ |
|
36 struct TPartVFatEntry |
34 struct TPartVFatEntry |
37 { |
35 { |
38 TEntryPos iEntryPos; ///< The position of the partial VFat entry |
36 TEntryPos iEntryPos; ///< The position of the partial VFat entry |
39 TFatDirEntry iEntry; ///< The Dos entry The VFat entries belong with |
37 TFatDirEntry iEntry; ///< The Dos entry The VFat entries belong with |
40 }; |
38 }; |
41 |
39 |
42 |
40 |
43 /** |
41 /** Data structure used to store the locations of entries with matching start cluster numbers. */ |
44 Data structure used to store the locations of entries with matching |
|
45 start cluster numbers. |
|
46 */ |
|
47 struct TMatchingStartCluster |
42 struct TMatchingStartCluster |
48 { |
43 { |
49 TEntryPos iEntries[KMaxMatchingEntries]; ///< The positions of the matching entries |
44 TEntryPos iEntries[KMaxMatchingEntries]; ///< The positions of the matching entries |
50 TInt iCount; ///< Count of matching entries |
45 TUint iCount; ///< Count of matching entries |
51 TInt iStartCluster; ///< The matching cluster number found in more than one entry |
46 TUint iStartCluster; ///< The matching cluster number found in more than one entry |
52 }; |
47 }; |
53 |
48 |
|
49 |
|
50 //--------------------------------------------------------------------------------------------------------------------------------- |
54 /** |
51 /** |
55 Scan drive class performs scan drive functionality on all types |
52 This class is used for checking volume for FS errors and fixing a limited set of FS artefacts introduced by Rugged FAT on write failures. |
56 of fat volume. |
53 It can operate in 2 modes: |
|
54 |
|
55 1. "ScanDrive" mode, scan whole volume for possible Rugged FAT artefacts and fix them if possible. |
|
56 1.1 If there was no problem at all, then StartL() finishes normally and ProblemsDiscovered() returns ENoErrors. |
|
57 1.2 If there was Rugged FAT artefact and it had been successfully fixed, StartL() finishes normally and ProblemsDiscovered() returns EScanDriveDirError. |
|
58 In this case the client may perform volum remounting, because FAT is very likely to have been changed. |
|
59 1.3 If there was a fatal error, like media failure or unfixable FS problem, StartL() will leave with some generic error code. |
|
60 |
|
61 2. "CheckDisk" mode. check file system for known artefacts and return an error if _any_ problem discovered. |
|
62 In this case StartL() _may_ leave with something like KErrCorrupt if there was a media failure or scan has stumbled across unknown FS error, |
|
63 ProblemsDiscovered() _may_ return some code describing the problem. If StartL() did not leave, but ProblemsDiscovered() returns a code different |
|
64 from ENoErrors, this means that there is FS corruption. |
57 */ |
65 */ |
58 class CScanDrive : public CBase |
66 class CScanDrive : public CBase |
59 { |
67 { |
60 public: |
|
61 /** |
|
62 Error type found by scan drive, only a single error should occur in |
|
63 any scan of the volume |
|
64 */ |
|
65 enum TDirError{EScanMatchingEntry=1,EScanPartEntry, ETruncation}; |
|
66 |
68 |
67 public: |
69 public: |
68 |
70 |
69 ~CScanDrive(); |
71 ~CScanDrive(); |
70 static CScanDrive* NewL(CFatMountCB* aMount); |
72 static CScanDrive* NewL(CFatMountCB* aMount); |
71 void ConstructL(CFatMountCB* aMount); |
73 void ConstructL(CFatMountCB* aMount); |
72 |
74 |
73 TInt StartL(); |
75 public: |
74 TBool ProblemsDiscovered() const; |
|
75 |
76 |
|
77 /** description of known problems that this scanned can deal with. Mostly used in "CheckDisk " mode */ |
|
78 enum TGenericError |
|
79 { |
|
80 ENoErrors = 0, ///< 0 no errors discovered |
|
81 EBadClusterNumber, ///< 1 cluster number that doesn't correspond to the max. amount of clusters on the volume |
|
82 EClusterAlreadyInUse, ///< 2 cross-linked cluster chain |
|
83 EBadClusterValue, ///< 3 also means "lost cluster" |
|
84 EInvalidEntrySize, ///< 4 size of file/directory does not correspond to the cluster chain length |
|
85 |
|
86 EUnknownError = 95, ///< unknown error |
|
87 |
|
88 EScanDriveDirError=100 ///< 100 ScanDrive error |
|
89 }; |
|
90 |
|
91 TGenericError ProblemsDiscovered() const; |
|
92 |
|
93 /** CScanDrive mode of operation */ |
|
94 enum TScanDriveMode |
|
95 { |
|
96 EScanAndFix, ///< "ScanDrive" mode, scan whole volume for possible Rugged FAT artefacts and fix them |
|
97 ECheckDisk, ///< "CheckDisk" mode. check file system for known artefacts and return an error if _any_ problem discovered |
|
98 }; |
|
99 |
|
100 void StartL(TScanDriveMode aMode); |
76 |
101 |
77 private: |
102 private: |
78 #if defined(DEBUG_SCANDRIVE) |
|
79 void PrintErrors(); |
103 void PrintErrors(); |
80 void CompareFatsL() const; |
104 void CompareFatsL(TBool aStopOnFirstErrorFound) ; |
81 #endif |
105 void CompareAndFixFatsL(); |
82 void FixupDirErrorL(); |
106 |
|
107 void FixupDirErrorL(); |
83 |
108 |
84 void ReadMediaFatL(); |
109 void ReadMediaFatL(); |
85 void DoParseFatL(); |
110 void DoParseFatL(); |
86 void DoParseFat32L(); |
111 void DoParseFat32L(); |
87 void DoParseFat32Buf(const TPtrC8& aBuf, TUint32& aCurrFatEntry); |
112 void DoParseFat32Buf(const TPtrC8& aBuf, TUint32& aCurrFatEntry); |
88 |
113 |
89 TBool AlreadyUsedL(TUint aCluster) const; |
114 TBool IsClusterUsedL(TUint aCluster); |
90 void SetUsedL(TUint aCluster); |
115 void MarkClusterUsedL(TUint aCluster); |
91 |
116 |
92 TUint32 ReadFatL(TInt aClusterNum) const; |
117 TUint32 ReadFatL(TUint aClusterNum) ; |
93 void FindSameStartClusterL(); |
118 void FindSameStartClusterL(); |
94 TInt FindStartClusterL(TInt aDirCluster); |
119 TInt FindStartClusterL(TInt aDirCluster); |
95 void CheckDirStructureL(); |
120 void CheckDirStructureL(); |
96 void CheckDirL(TInt aCluster); |
121 void CheckDirL(TUint32 aCluster); |
97 void ProcessEntryL(const TFatDirEntry& aEntry); |
122 void ProcessEntryL(const TFatDirEntry& aEntry); |
98 TInt CheckEntryClusterL(const TFatDirEntry& aEntry, const TEntryPos& aEntryPos); |
123 TInt CheckEntryClusterL(const TFatDirEntry& aEntry, const TEntryPos& aEntryPos); |
99 void WriteClusterChainL(TInt aCluster,TUint aSizeInBytes); |
124 void RecordClusterChainL(TInt aCluster,TUint aSizeInBytes); |
100 TBool MoveToVFatEndL(TEntryPos& aPos,TFatDirEntry& aEntry,TInt& aDirLength); |
125 TBool MoveToVFatEndL(TEntryPos& aPos,TFatDirEntry& aEntry,TInt& aDirLength); |
101 TBool IsValidVFatEntry(const TFatDirEntry& aEntry,TInt prevNum)const; |
126 TBool IsValidVFatEntry(const TFatDirEntry& aEntry,TInt prevNum)const; |
102 TBool IsDosEntry(const TFatDirEntry& aEntry)const; |
127 TBool IsDosEntry(const TFatDirEntry& aEntry)const; |
103 void AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry); |
128 void AddPartialVFatL(const TEntryPos& aStartPos, const TFatDirEntry& aEntry); |
104 TBool AddMatchingEntryL(const TEntryPos& aEntryPos); |
129 TBool AddMatchingEntryL(const TEntryPos& aEntryPos); |
105 TInt GetReservedidL(const TEntryPos aVFatPos); |
130 TInt GetReservedidL(const TEntryPos aVFatPos); |
106 void WriteNewFatsL(); |
131 |
107 void FixPartEntryL(); |
132 void FixPartEntryL(); |
108 void FixMatchingEntryL(); |
133 void FixMatchingEntryL(); |
109 void MovePastEntriesL(TEntryPos& aEntryPos,TFatDirEntry& aEntry,TInt aToMove,TInt& aDirEntries); |
134 void MovePastEntriesL(TEntryPos& aEntryPos,TFatDirEntry& aEntry,TInt aToMove,TInt& aDirEntries); |
110 void AddToClusterListL(TInt aCluster); |
135 void AddToClusterListL(TInt aCluster); |
111 inline TBool AlreadyExistsL(TInt aCluster)const; |
136 inline TBool AlreadyExistsL(TInt aCluster)const; |
113 inline TBool IsEofF(TInt aVal)const; |
138 inline TBool IsEofF(TInt aVal)const; |
114 inline TBool IsDirError()const; |
139 inline TBool IsDirError()const; |
115 void MoveToNextEntryL(TEntryPos& aPos); |
140 void MoveToNextEntryL(TEntryPos& aPos); |
116 void ReadDirEntryL(const TEntryPos& aPos,TFatDirEntry& aDirEntry); |
141 void ReadDirEntryL(const TEntryPos& aPos,TFatDirEntry& aDirEntry); |
117 |
142 |
118 void IndicateErrorsFound(); |
143 inline void IndicateErrorsFound(TGenericError aError); |
|
144 inline TUint32 MaxClusters() const; |
|
145 inline TBool CheckDiskMode() const; |
|
146 |
|
147 protected: |
|
148 |
|
149 /** |
|
150 Internal ScanDrive mode specific errors. In Rugged FAT mode (current implementatio) any type of error of this kind can occur only once and it will be fixed. |
|
151 Othersise the FS is considered to be corrupted |
|
152 */ |
|
153 enum TDirError |
|
154 { |
|
155 ENoDirError= 0, ///< no errors found |
|
156 EScanMatchingEntry=1, ///< Two entries pointing to the same cluster chain; Rugged FAT rename/replace artefact |
|
157 EScanPartEntry, ///< Deleted DOS entry and orphaned VFAT ones from the same entryset; Rugged FAT 'file/dir delete' artefact |
|
158 }; |
|
159 |
119 |
160 |
120 private: |
161 private: |
121 CFatMountCB* iMount; ///< The owning Fat mount |
162 CFatMountCB* iMount; ///< The owning Fat mount |
122 TPartVFatEntry iPartEntry; ///< Storage for a partial VFat entry set error |
163 |
123 TMatchingStartCluster iMatching; ///< Storage for Matching start cluster error |
164 TPartVFatEntry iPartEntry; ///< Storage for a partial VFat entry set error, see EScanPartEntry |
124 TDirError iDirError; ///< Indicates the error tpye found also used to indicate if an error has occured |
165 TMatchingStartCluster iMatching; ///< Storage for Matching start cluster error, see EScanMatchingEntry |
125 TInt iDirsChecked; ///< Count of the number of directories checked |
166 |
|
167 TDirError iDirError; ///< Indicates the error tpye found also used to indicate if an error has occured |
|
168 TInt iDirsChecked; ///< Count of the number of directories checked |
126 TInt iRecursiveDepth; ///< Depth of recursion the scan has reached |
169 TInt iRecursiveDepth; ///< Depth of recursion the scan has reached |
127 RArray<TInt>* iClusterListArray[KMaxArrayDepth]; ///< Size in bytes of the bit packed Fat Cluster list array used when maximum depth has been reached so that directory may be re-visited. Avoid stack overflow |
170 RArray<TInt>* iClusterListArray[KMaxArrayDepth]; ///< Size in bytes of the bit packed Fat Cluster list array used when maximum depth has been reached so that directory may be re-visited. Avoid stack overflow |
128 TInt iListArrayIndex; ///< Current position into cluster list array |
|
129 TInt iTruncationCluster; ///< Cluster at which cluster chain truncation should take place, used for truncation errors |
|
130 |
171 |
131 TBool iFoundProblems; ///< if ETrue after finish, it means that there where some problems FS structure and they were probably fixed; |
172 TUint iListArrayIndex; ///< Current position into cluster list array |
132 RBitVector iMediaFatBits; ///< Storage for bit packed Fat read from media |
173 TUint32 iTruncationCluster; ///< Cluster at which cluster chain truncation should take place, used for truncation errors |
133 RBitVector iScanFatBits; ///< Storage for bit packed Fat built up by the scan |
174 TUint32 iMaxClusters; ///< Max. amount of clusters on the volume |
134 |
175 |
|
176 RBitVector iMediaFatBits; ///< Storage for bit packed Fat read from media |
|
177 RBitVector iScanFatBits; ///< Storage for bit packed Fat built up by the scan |
|
178 |
|
179 TGenericError iGenericError; ///< FS error that is discovered by scanning in any mode |
|
180 TScanDriveMode iScanDriveMode; ///< mode of operation |
135 }; |
181 }; |
136 |
182 |
137 |
183 |
138 |
184 |
139 #endif //SL_SCANDRV_H |
185 #endif //SL_SCANDRV_H |