|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "UP_STD.H" |
|
17 |
|
18 #include <pbe.h> |
|
19 |
|
20 EXPORT_C void TStorePagePoolToken::ExternalizeL(RWriteStream& aStream) const |
|
21 /** Externalises a TStorePagePoolToken object to a stream. |
|
22 |
|
23 @param aStream Stream to which the object should be externalised */ |
|
24 { |
|
25 aStream<<iHead; |
|
26 aStream<<iAvail; |
|
27 } |
|
28 |
|
29 EXPORT_C void TStorePagePoolToken::InternalizeL(RReadStream& aStream) |
|
30 /** Internalises a TStorePagePoolToken object from a stream. |
|
31 |
|
32 @param aStream Stream from which the object should be internalised */ |
|
33 { |
|
34 aStream>>iHead; |
|
35 aStream>>iAvail; |
|
36 } |
|
37 |
|
38 // Class RStorePagePool |
|
39 |
|
40 EXPORT_C RStorePagePool::RStorePagePool() |
|
41 : iStore(NULL) |
|
42 /** Default constructor. */ |
|
43 {} |
|
44 |
|
45 EXPORT_C RStorePagePool::RStorePagePool(CPageCache& aCache) |
|
46 : TCachePagePool(aCache),iStore(NULL) |
|
47 /** Constructor with a page cache for the pool. |
|
48 |
|
49 @param aCache Page cache for the pool */ |
|
50 {} |
|
51 |
|
52 EXPORT_C RStorePagePool::RStorePagePool(CStreamStore& aStore) |
|
53 /** Constructor with a stream store to use for the pool. |
|
54 |
|
55 @param aStore Stream store to use for the pool */ |
|
56 { |
|
57 Create(aStore); |
|
58 } |
|
59 |
|
60 EXPORT_C RStorePagePool::RStorePagePool(CStreamStore& aStore,const TStorePagePoolToken& aToken) |
|
61 /** Constructor with a stream store and settings to use for the pool. |
|
62 |
|
63 @param aStore Stream store to use for the pool |
|
64 @param aToken Stream store pool settings */ |
|
65 { |
|
66 Open(aStore,aToken); |
|
67 } |
|
68 |
|
69 EXPORT_C void RStorePagePool::Create(CStreamStore& aStore) |
|
70 /** Creates a new pool. |
|
71 |
|
72 @param aStore Stream store to use for the pool */ |
|
73 { |
|
74 iStore=&aStore; |
|
75 iHead=KNullStreamId; |
|
76 iAvail=KNullPageRef; |
|
77 iDirty=EFalse; |
|
78 } |
|
79 |
|
80 EXPORT_C void RStorePagePool::Open(CStreamStore& aStore,const TStorePagePoolToken& aToken) |
|
81 /** Opens an existing pool. |
|
82 |
|
83 @param aStore Stream store for the pool |
|
84 @param aToken Pool settings */ |
|
85 { |
|
86 iStore=&aStore; |
|
87 iHead=aToken.iHead; |
|
88 iAvail=aToken.iAvail; |
|
89 iDirty=EFalse; |
|
90 } |
|
91 |
|
92 EXPORT_C TStorePagePoolToken RStorePagePool::Token() const |
|
93 /** Gets an object that encapsulates the page pool settings. |
|
94 |
|
95 That object can then be used to externalise the settings. |
|
96 |
|
97 @return Encapsulates the page pool settings */ |
|
98 { |
|
99 return TStorePagePoolToken(iHead,iAvail); |
|
100 } |
|
101 |
|
102 EXPORT_C void RStorePagePool::Close() |
|
103 /** Flushes and purges the page cache and stops using the stream store. */ |
|
104 { |
|
105 TCachePagePool::Flush(); |
|
106 Release(); |
|
107 } |
|
108 |
|
109 EXPORT_C TBool RStorePagePool::ReclaimL() |
|
110 /** Deletes the first stream that stores reclaimable pages in the store. |
|
111 |
|
112 @return True if there are remaining streams (pages), false if there are no |
|
113 more streams */ |
|
114 { |
|
115 __ASSERT_DEBUG(iStore!=NULL,Panic(EPageNotOpen)); |
|
116 __ASSERT_ALWAYS(iAvail==KNullPageRef,Panic(EPageReclaimAvailable)); |
|
117 if (iHead!=KNullStreamId) |
|
118 { |
|
119 RStoreReadStream out; |
|
120 out.OpenLC(*iStore,iHead); |
|
121 TStreamId next; |
|
122 out>>next; |
|
123 CleanupStack::PopAndDestroy(); |
|
124 iStore->DeleteL(iHead); |
|
125 iHead=next; |
|
126 MarkDirty(); |
|
127 if (next!=KNullStreamId) |
|
128 return ETrue; |
|
129 } |
|
130 return EFalse; |
|
131 } |
|
132 |
|
133 EXPORT_C void RStorePagePool::ReclaimAllL() |
|
134 /** Deletes all streams in the store. */ |
|
135 { |
|
136 while (ReclaimL()) |
|
137 ; |
|
138 } |
|
139 |
|
140 EXPORT_C TPageRef RStorePagePool::ExtendL(const TAny* aPage,TPageReclamation aReclamation) |
|
141 // |
|
142 // Create a new page. |
|
143 // |
|
144 { |
|
145 return StorePagePool::ExtendL(*this,aPage,aReclamation); |
|
146 } |
|
147 |
|
148 EXPORT_C void RStorePagePool::WriteL(TPageRef aRef,const TAny* aPage,TPageChange aChange) |
|
149 // |
|
150 // Write a page to the store. |
|
151 // |
|
152 { |
|
153 StorePagePool::WriteL(*this,aRef,aPage,aChange); |
|
154 } |
|
155 |
|
156 EXPORT_C void RStorePagePool::ReadL(TPageRef aRef,TAny* aPage) |
|
157 // |
|
158 // Read from the store into a page. |
|
159 // |
|
160 { |
|
161 StorePagePool::ReadL(*this,aRef,aPage); |
|
162 } |
|
163 |
|
164 EXPORT_C void RStorePagePool::DoDeleteL(TPageRef aRef) |
|
165 // |
|
166 // Delete from store. |
|
167 // |
|
168 { |
|
169 StorePagePool::DeleteL(*this,aRef); |
|
170 } |
|
171 |
|
172 // Class RSecureStorePagePool |
|
173 |
|
174 |
|
175 |
|
176 EXPORT_C RSecureStorePagePool::RSecureStorePagePool(const CPBEncryptSet& aKey) |
|
177 : iKey(aKey) |
|
178 {} |
|
179 |
|
180 EXPORT_C RSecureStorePagePool::RSecureStorePagePool(CPageCache& aCache, const CPBEncryptSet& aKey) |
|
181 : RStorePagePool(aCache), |
|
182 iKey(aKey) |
|
183 {} |
|
184 |
|
185 /** Adds a new page to the pool. |
|
186 |
|
187 @param aPage Data for the page |
|
188 @param aReclamation Flags that define how allocated pages can be reclaimed |
|
189 @return Reference to newly created page */ |
|
190 EXPORT_C TPageRef RSecureStorePagePool::ExtendL(const TAny* aPage,TPageReclamation aReclamation) |
|
191 { |
|
192 return StorePagePool::ExtendL(*this,aPage,aReclamation); |
|
193 } |
|
194 |
|
195 /** Writes data to a page in the pool. |
|
196 |
|
197 @param aRef Reference to the page to which to write |
|
198 @param aPage Data to write |
|
199 @param aChange Flags that define how a page should be treated when it is unlocked |
|
200 for writing */ |
|
201 EXPORT_C void RSecureStorePagePool::WriteL(TPageRef aRef,const TAny* aPage,TPageChange aChange) |
|
202 { |
|
203 StorePagePool::WriteL(*this,aRef,aPage,aChange); |
|
204 } |
|
205 |
|
206 /** Reads a specified page from the pool. |
|
207 |
|
208 @param aRef Reference to page to read |
|
209 @param aPage On return, the page data */ |
|
210 EXPORT_C void RSecureStorePagePool::ReadL(TPageRef aRef,TAny* aPage) |
|
211 { |
|
212 StorePagePool::ReadL(*this,aRef,aPage); |
|
213 } |
|
214 |
|
215 /** Deletes a specified page. |
|
216 |
|
217 @param aRef Reference to page to delete */ |
|
218 EXPORT_C void RSecureStorePagePool::DoDeleteL(TPageRef aRef) |
|
219 { |
|
220 StorePagePool::DeleteL(*this,aRef); |
|
221 } |
|
222 |
|
223 // Class StorePagePool |
|
224 // the implementation of the clever bits to share code between the secure and plain sotre page pools |
|
225 |
|
226 const TInt KMaxPageIndex=15; |
|
227 |
|
228 inline TInt PageSize(const CPBEncryptionBase* aKey) |
|
229 { |
|
230 return aKey ? aKey->MaxCiphertextLength(KPoolPageSize) : KPoolPageSize; |
|
231 } |
|
232 |
|
233 inline TPageRef PageRef(TStreamId anId,TInt anIndex=0) |
|
234 { |
|
235 __ASSERT_DEBUG(anIndex>=0&&anIndex<=KMaxPageIndex,User::Invariant()); |
|
236 return TPageRef((anId.Value()<<4)+anIndex); |
|
237 } |
|
238 inline TInt PageIndex(TPageRef aRef) |
|
239 {return aRef.Value()&0xf;} |
|
240 inline TStreamId StreamId(TPageRef aRef) |
|
241 {return TStreamId(aRef.Value()>>4);} |
|
242 inline TStreamPos PagePos(TInt anIndex,TInt aPageSize) |
|
243 {return TStreamPos(sizeof(TStreamId)+(anIndex-1)*aPageSize);} |
|
244 |
|
245 void StorePagePool::PadL(RWriteStream& aStream,TInt aLength) |
|
246 // |
|
247 // zero-pad a stream |
|
248 // |
|
249 { |
|
250 TUint8 zero[KPoolPageSize]; |
|
251 Mem::FillZ(zero,KPoolPageSize); |
|
252 while ((aLength-=KPoolPageSize)>0) |
|
253 aStream.WriteL(zero,KPoolPageSize); |
|
254 aStream.WriteL(zero,aLength+KPoolPageSize); |
|
255 } |
|
256 |
|
257 // |
|
258 // Encrypt the page to the stream, padding out to full page size |
|
259 void StorePagePool::EncryptL(RWriteStream& aStream,const TAny* aPage,const CPBEncryptionBase& aKey) |
|
260 { |
|
261 REncryptStream encrypt; |
|
262 encrypt.OpenLC(aStream,aKey); |
|
263 encrypt.WriteL((const TUint8*)aPage,KPoolPageSize); |
|
264 encrypt.CommitL(); |
|
265 CleanupStack::PopAndDestroy(&encrypt); |
|
266 } |
|
267 |
|
268 // |
|
269 // Encrypt the page to the stream, padding out to full page size |
|
270 // |
|
271 void StorePagePool::EncryptNewL(RWriteStream& aStream,const TAny* aPage,const CPBEncryptionBase& aKey) |
|
272 { |
|
273 TStreamPos pos=aStream.Sink()->TellL(MStreamBuf::EWrite); // remember the start of the data |
|
274 EncryptL(aStream,aPage,aKey); |
|
275 TInt pad=PageSize(&aKey)-(aStream.Sink()->TellL(MStreamBuf::EWrite)-pos); // bytes written |
|
276 __ASSERT_DEBUG(pad>=0,Panic(EPageCipherTextOverrun)); |
|
277 if (pad) |
|
278 PadL(aStream,pad); |
|
279 } |
|
280 |
|
281 // |
|
282 // Encrypt the page to the stream, padding out to full page size |
|
283 // |
|
284 void StorePagePool::DecryptL(RReadStream& aStream,TAny* aPage,const CPBEncryptionBase& aKey) |
|
285 { |
|
286 RDecryptStream decrypt; |
|
287 decrypt.OpenLC(aStream,aKey); |
|
288 decrypt.ReadL((TUint8*)aPage,KPoolPageSize); |
|
289 CleanupStack::PopAndDestroy(); |
|
290 } |
|
291 |
|
292 void StorePagePool::SeekL(MStreamBuf* aBuf,TInt aMark,TPageRef aRef,const CPBEncryptionBase* aKey) |
|
293 { |
|
294 TInt ix=PageIndex(aRef); |
|
295 if (ix) |
|
296 aBuf->SeekL(aMark,PagePos(ix,PageSize(aKey))); |
|
297 } |
|
298 |
|
299 TPageRef StorePagePool::ExtendL(RStorePagePool& aPool,const TAny* aPage,TPageReclamation aReclamation,const CPBEncryptionBase* aKey) |
|
300 { |
|
301 __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen)); |
|
302 TPageRef page; |
|
303 RStoreWriteStream out; |
|
304 if (aReclamation==EPageDeleteOnly) |
|
305 { // non-reclaimable page |
|
306 page=PageRef(out.CreateLC(*aPool.iStore)); |
|
307 } |
|
308 else if (aPool.iAvail!=KNullPageRef) |
|
309 { // use free page |
|
310 page=aPool.iAvail; |
|
311 out.OpenLC(*aPool.iStore,StreamId(page)); |
|
312 MStreamBuf* buf=out.Sink(); |
|
313 SeekL(buf,MStreamBuf::ERead|MStreamBuf::EWrite,page,aKey); |
|
314 RReadStream in(buf); |
|
315 in>>aPool.iAvail; |
|
316 aPool.MarkDirty(); |
|
317 } |
|
318 else |
|
319 { // allocate new block, and create free list |
|
320 TStreamId id=out.CreateLC(*aPool.iStore); |
|
321 out<<aPool.iHead; // block list |
|
322 const TInt pad=PageSize(aKey)-sizeof(TPageRef); |
|
323 page=KNullPageRef; // free-list terminator |
|
324 for (TInt index=0;++index<KMaxPageIndex;) |
|
325 { |
|
326 out<<page; |
|
327 PadL(out,pad); |
|
328 page=PageRef(id,index); |
|
329 } |
|
330 aPool.MarkDirty(); |
|
331 aPool.iHead=id; |
|
332 aPool.iAvail=page; |
|
333 page=PageRef(id,KMaxPageIndex); // page is written at end |
|
334 } |
|
335 if (aKey) |
|
336 EncryptNewL(out,aPage,*aKey); |
|
337 else |
|
338 out.WriteL((const TUint8*)aPage,KPoolPageSize); |
|
339 out.CommitL(); |
|
340 CleanupStack::PopAndDestroy(); |
|
341 return page; |
|
342 } |
|
343 |
|
344 void StorePagePool::WriteL(RStorePagePool& aPool,TPageRef aRef,const TAny* aPage,TPageChange aChange,const CPBEncryptionBase* aKey) |
|
345 { |
|
346 __ASSERT_DEBUG(aChange>=EPageDirty,Panic(EPageChangeInvalid)); |
|
347 __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen)); |
|
348 RStoreWriteStream out; |
|
349 if (aChange==EPageUpdate) |
|
350 { |
|
351 __ASSERT_DEBUG(PageIndex(aRef)==0,Panic(EPageChangeInvalid)); |
|
352 out.ReplaceLC(*aPool.iStore,StreamId(aRef)); |
|
353 if (aKey) |
|
354 EncryptNewL(out,aPage,*aKey); |
|
355 else |
|
356 out.WriteL((const TUint8*)aPage,KPoolPageSize); |
|
357 } |
|
358 else |
|
359 { // re-write the page, no padding req'd |
|
360 out.OpenLC(*aPool.iStore,StreamId(aRef)); |
|
361 SeekL(out.Sink(),MStreamBuf::EWrite,aRef,aKey); |
|
362 if (aKey) |
|
363 EncryptL(out,aPage,*aKey); |
|
364 else |
|
365 out.WriteL((const TUint8*)aPage,KPoolPageSize); |
|
366 } |
|
367 out.CommitL(); |
|
368 CleanupStack::PopAndDestroy(); |
|
369 } |
|
370 |
|
371 void StorePagePool::ReadL(RStorePagePool& aPool,TPageRef aRef,TAny* aPage,const CPBEncryptionBase* aKey) |
|
372 { |
|
373 __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen)); |
|
374 RStoreReadStream in; |
|
375 in.OpenLC(*aPool.iStore,StreamId(aRef)); |
|
376 SeekL(in.Source(),MStreamBuf::ERead,aRef,aKey); |
|
377 if (aKey) |
|
378 DecryptL(in,aPage,*aKey); |
|
379 else |
|
380 in.ReadL((TUint8*)aPage,KPoolPageSize); |
|
381 CleanupStack::PopAndDestroy(); // in |
|
382 } |
|
383 |
|
384 void StorePagePool::DeleteL(RStorePagePool& aPool,TPageRef aRef,const CPBEncryptionBase* aKey) |
|
385 { |
|
386 aPool.CacheDeleteL(aRef); |
|
387 __ASSERT_DEBUG(aPool.iStore!=NULL,Panic(EPageNotOpen)); |
|
388 if (PageIndex(aRef)==0) |
|
389 { //non-reclaimable |
|
390 aPool.iStore->DeleteL(StreamId(aRef)); |
|
391 return; |
|
392 } |
|
393 // add to free list |
|
394 RStoreWriteStream out; |
|
395 out.OpenLC(*aPool.iStore,StreamId(aRef)); |
|
396 SeekL(out.Sink(),MStreamBuf::EWrite,aRef,aKey); |
|
397 out<<aPool.iAvail; |
|
398 out.CommitL(); |
|
399 CleanupStack::PopAndDestroy(); |
|
400 aPool.iAvail=aRef; |
|
401 aPool.MarkDirty(); |
|
402 } |