|
1 /* |
|
2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * Definition of the Swi::Sis::CContents |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include <e32std.h> |
|
21 #include <s32mem.h> |
|
22 #include "sisinstallerrors.h" |
|
23 #include "siscontents.h" |
|
24 #include "siscrc.h" |
|
25 #include "siscompressed.h" |
|
26 #include "sisdata.h" |
|
27 #include "sisblob.h" |
|
28 |
|
29 #include "sisdataprovider.h" |
|
30 #include "compresseddataprovider.h" |
|
31 |
|
32 using namespace Swi; |
|
33 using namespace Swi::Sis; |
|
34 |
|
35 // This line is commented so that SWI does not enforce CRC |
|
36 // checking. If CRC checking was enforced existing SIS |
|
37 // files created before DEF063815 was fixed would fail |
|
38 // Uncommenting this line would cause a data compatibility break |
|
39 |
|
40 // #define SIS_CRC_CHECK_ENABLED |
|
41 |
|
42 |
|
43 /*static*/ CContents* CContents::NewL(MSisDataProvider& aDataProvider, TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) |
|
44 { |
|
45 CContents* self = new(ELeave) CContents(aDataProvider); |
|
46 CleanupStack::PushL(self); |
|
47 self->ConstructL(aBytesRead, aTypeReadBehaviour); |
|
48 CleanupStack::Pop(self); |
|
49 return self; |
|
50 } |
|
51 |
|
52 CContents::~CContents() |
|
53 { |
|
54 delete iCompressed; |
|
55 delete iData; |
|
56 delete iDataCrc; |
|
57 delete iControllerCrc; |
|
58 } |
|
59 |
|
60 CContents::CContents(MSisDataProvider& aDataProvider) : iDataProvider(aDataProvider) |
|
61 { |
|
62 } |
|
63 |
|
64 void CContents::ConstructL(TInt64& aBytesRead, TReadTypeBehaviour aTypeReadBehaviour) |
|
65 { |
|
66 |
|
67 CField::ConstructL(iDataProvider, EFieldTypeContents, aBytesRead, aTypeReadBehaviour); |
|
68 |
|
69 TFieldType fieldType; |
|
70 CField::ReadEnumL<TFieldType,TUint32>(iDataProvider, fieldType, aBytesRead); |
|
71 |
|
72 if (fieldType == EFieldTypeControllerCRC) |
|
73 { |
|
74 // Controller Checksum present |
|
75 iControllerCrc = CCrc::NewL(iDataProvider, aBytesRead, EAssumeType); |
|
76 |
|
77 CField::ReadEnumL<TFieldType,TUint32>(iDataProvider, fieldType, aBytesRead); |
|
78 } |
|
79 |
|
80 if (fieldType == EFieldTypeDataCRC) |
|
81 { |
|
82 // Data Checksum present |
|
83 iDataCrc = CCrc::NewL(iDataProvider, aBytesRead, EAssumeType); |
|
84 |
|
85 CField::ReadEnumL<TFieldType,TUint32>(iDataProvider, fieldType, aBytesRead); |
|
86 } |
|
87 |
|
88 if (fieldType != EFieldTypeCompressed) |
|
89 { |
|
90 User::Leave(KErrSISUnexpectedFieldType); |
|
91 } |
|
92 |
|
93 iCompressed = CCompressed::NewL(iDataProvider, aBytesRead, EAssumeType); |
|
94 iData = CData::NewL(iDataProvider, aBytesRead); |
|
95 |
|
96 #ifdef SIS_CRC_CHECK_ENABLED |
|
97 // This line is commented because existing SIS files had an |
|
98 // incorrect CRC so enforcing the checksum now would be a data |
|
99 // compatibility break. |
|
100 // See DEF057005 |
|
101 CheckCrcL(); |
|
102 #endif |
|
103 } |
|
104 |
|
105 EXPORT_C HBufC8* CContents::ReadControllerL() const |
|
106 { |
|
107 return iCompressed->ReadControllerDataL(); |
|
108 } |
|
109 |
|
110 EXPORT_C void CContents::ReadDataL(RFile& aFile, TInt aFileIndex, TInt aDataUnit) |
|
111 { |
|
112 iData->ReadDataL(aFile, aFileIndex, aDataUnit); |
|
113 } |
|
114 |
|
115 EXPORT_C void CContents::ReadDataL(RFile& aFile, TInt aFileIndex, TInt aDataUnit, TInt64 aLength) |
|
116 { |
|
117 iData->ReadDataL(aFile, aFileIndex, aDataUnit, aLength); |
|
118 } |
|
119 |
|
120 void CContents::WriteStubFieldsL(RFile& aFile, MSisDataProvider& aDataProvider) |
|
121 { |
|
122 // create a buffer to receive the fields of the CSisContent for the stub |
|
123 CBufFlat* buf = CBufFlat::NewL(250); |
|
124 CleanupStack::PushL(buf); |
|
125 |
|
126 // create write stream |
|
127 RBufWriteStream writeStream(*buf); |
|
128 CleanupClosePushL(writeStream); |
|
129 |
|
130 // Skip over the SisContents header |
|
131 CContents* self = new(ELeave) CContents(aDataProvider); |
|
132 CleanupStack::PushL(self); |
|
133 self->ReadHeaderL(); |
|
134 TInt64 maxLength = self->Length() + self->PaddingSize(); |
|
135 CleanupStack::PopAndDestroy(self); |
|
136 |
|
137 // Extract the relevant fields from the SISContents, write them |
|
138 // to the buffer via the stream |
|
139 ExtractSisStubFieldsL(writeStream, aDataProvider, maxLength); |
|
140 CData::AppendStubDataFieldL(writeStream); |
|
141 |
|
142 CleanupStack::PopAndDestroy(&writeStream); |
|
143 TPtr8 sisContentsBuf = buf->Ptr(0); |
|
144 |
|
145 TBuf8<3 * sizeof(TInt32)> header; |
|
146 CField::CreateHeader(EFieldTypeContents, TInt64(sisContentsBuf.Length()), header); |
|
147 // Write sis contents header |
|
148 User::LeaveIfError(aFile.Write(header)); |
|
149 // Write sis contents |
|
150 User::LeaveIfError(aFile.Write(sisContentsBuf)); |
|
151 // Write sis contents padding, |
|
152 TInt lengthMod4 = (header.Length() + sisContentsBuf.Length()) % 4; |
|
153 |
|
154 TBuf8<1> padding; |
|
155 padding.Append(0); |
|
156 while(lengthMod4 > 0) |
|
157 { |
|
158 User::LeaveIfError(aFile.Write(padding)); |
|
159 lengthMod4--; |
|
160 } |
|
161 |
|
162 // finished |
|
163 CleanupStack::PopAndDestroy(buf); |
|
164 } |
|
165 |
|
166 void CContents::ExtractSisStubFieldsL(RWriteStream& aWriteStream, MSisDataProvider& aDataProvider, TInt64& aMaxLength) |
|
167 { |
|
168 TInt64 bytesRead = 0; |
|
169 |
|
170 // write the sis file to the stream but skip the Data and DataCRC fields |
|
171 // This assumes all the other fields are correct, no checking is performed |
|
172 TFieldType fieldType(EFieldTypeContents); |
|
173 while(fieldType != EFieldTypeData) |
|
174 { |
|
175 // get field type from data provider |
|
176 CField::ReadEnumL<TFieldType,TUint32>(aDataProvider, fieldType, bytesRead); |
|
177 |
|
178 if (fieldType == EFieldTypeDataCRC) |
|
179 { |
|
180 // read data checksum in order to skip over it |
|
181 CCrc* crc = CCrc::NewL(aDataProvider, bytesRead, EAssumeType); |
|
182 delete crc; |
|
183 crc = NULL; |
|
184 } |
|
185 else if (fieldType == EFieldTypeData) |
|
186 { |
|
187 // read data field in order to skip over it |
|
188 // could be many megabytes so we don't want to create |
|
189 // it as a blob |
|
190 CData* data = CData::NewL(aDataProvider, bytesRead, EAssumeType); |
|
191 delete data; |
|
192 data = NULL; |
|
193 } |
|
194 else |
|
195 { |
|
196 // load the field as a blob, we don't care whats inside |
|
197 CBlob* blob = CBlob::NewLC(aDataProvider, bytesRead, EAssumeType); |
|
198 |
|
199 // Write the field to the output stream |
|
200 // Cant do this inside CSisBlob because it's TCB in SisController.mmp |
|
201 // and the streaming classes are not TCB |
|
202 |
|
203 // Create a header for the fieldType with a given length |
|
204 TBuf8<3 * sizeof(TInt32)> header; |
|
205 CField::CreateHeader(fieldType, TInt64(blob->Length()), header); |
|
206 aWriteStream.WriteL(header); |
|
207 aWriteStream.WriteL(blob->Data()); |
|
208 for(TInt i = 0; i < blob->PaddingSize(); i++) |
|
209 { |
|
210 // write out zero padding at the end of the SisField |
|
211 aWriteStream.WriteInt8L(0); |
|
212 } |
|
213 CleanupStack::PopAndDestroy(blob); |
|
214 } |
|
215 if(bytesRead > aMaxLength) |
|
216 { |
|
217 // we have read past the end of the SisContents field |
|
218 User::Leave(KErrCorrupt); |
|
219 } |
|
220 } |
|
221 } |
|
222 |
|
223 void CContents::ReadHeaderL() |
|
224 { |
|
225 // This just skips over the header without actually reading any of the data |
|
226 TInt64 bytesRead =0; |
|
227 CField::ConstructL(iDataProvider, EFieldTypeContents, bytesRead, EReadType); |
|
228 } |
|
229 |
|
230 EXPORT_C void CContents::CheckCrcL() |
|
231 { |
|
232 if(iControllerCrc && iControllerCrc->Checksum() != iCompressed->Crc()) |
|
233 { |
|
234 User::Leave(KErrCorrupt); |
|
235 } |
|
236 |
|
237 if(iDataCrc && iDataCrc->Checksum() != iData->Crc()) |
|
238 { |
|
239 User::Leave(KErrCorrupt); |
|
240 } |
|
241 } |