|
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 the License "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 // f32\sfile\sf_disk.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "sf_std.h" |
|
19 |
|
20 #if defined(_LOCKABLE_MEDIA) |
|
21 |
|
22 LOCAL_C TInt DelayedWriter(TAny *aPtr); |
|
23 LOCAL_C void DelayedWriterL(const TDelayedWriter *aDW); |
|
24 |
|
25 |
|
26 EXPORT_C void WriteToDisk(const TDesC& aFileName, const TDesC8& aBuf) |
|
27 // |
|
28 // Launches as separate thread that writes the contents of the pbus pswd |
|
29 // store to disk. It is possible that this function will be called again |
|
30 // before the thread has finished writing. In that case, a new thread |
|
31 // will be created and it will wait on the global DelayedWriteSem semaphore. |
|
32 // |
|
33 { |
|
34 static TInt32 ctr = 0x00000000; // ctr to create unique thd names |
|
35 |
|
36 __PRINT(_L("WriteToDisk")); |
|
37 __PRINT1(_L("wtd:afn%S"), &aFileName); |
|
38 |
|
39 TDelayedWriterInit dwi; |
|
40 dwi.iFileName = &aFileName; |
|
41 dwi.iData = &aBuf; |
|
42 |
|
43 // Create local semaphore this thread can wait on until the child thread has |
|
44 // made copies of the file name and the store data. |
|
45 |
|
46 __PRINT(_L("wtd:cr sem")); |
|
47 TBuf<3 + 8> semName; |
|
48 semName.Format(_L("dws%08x"), ctr++); |
|
49 dwi.iSemName = &semName; |
|
50 RSemaphore svrSem; |
|
51 if (svrSem.CreateGlobal(semName, 0) != KErrNone) |
|
52 return; |
|
53 |
|
54 // Spin off a thread with a unique name. |
|
55 |
|
56 __PRINT(_L("wtd:cr thd")); |
|
57 TName nm; |
|
58 nm.Format(_L("dw%08x"), ctr); |
|
59 RThread t; |
|
60 TInt hminsz = Max(KHeapMinSize, aFileName.Length() + aBuf.Length() + 1024); |
|
61 if (t.Create( |
|
62 nm, DelayedWriter, KDefaultStackSize, |
|
63 hminsz /* aHeapMinSize */, hminsz /* aHeapMaxSize */, &dwi) == KErrNone) |
|
64 { |
|
65 __PRINT(_L("wtd:set pri")); |
|
66 t.SetPriority(EPriorityMuchLess); // run as low priority task |
|
67 __PRINT(_L("wtd:res")); |
|
68 t.Resume(); |
|
69 __PRINT(_L("wtd:wait")); |
|
70 svrSem.Wait(); |
|
71 __PRINT(_L("wtd:cls thd")); |
|
72 t.Close(); // get rid of our handle |
|
73 } |
|
74 |
|
75 __PRINT(_L("wtd:cls sem")); |
|
76 svrSem.Close(); |
|
77 } |
|
78 |
|
79 |
|
80 LOCAL_D TInt DelayedWriter(TAny *aPtr) |
|
81 // |
|
82 // Main thread function for thread that is spun off from WriteToDisk(). |
|
83 // After local copies of the data have been allocated (or failed), tell |
|
84 // the server to continue. |
|
85 // |
|
86 { |
|
87 __PRINT(_L("DelayedWriter")); |
|
88 |
|
89 User::SetCritical(User::ESystemCritical); |
|
90 |
|
91 TInt r; |
|
92 |
|
93 TDelayedWriterInit *dwi = (TDelayedWriterInit *) aPtr; |
|
94 RSemaphore svrSem; // signal svr when data copied |
|
95 CTrapCleanup *th = NULL; // thread trap handler |
|
96 TDelayedWriter *dw = NULL; // thread copy of data |
|
97 RSemaphore queueSem; // queued delayed write threads |
|
98 |
|
99 // Allocate a trap handler. |
|
100 __PRINT(_L("dlw:alc tp")); |
|
101 if ((th = CTrapCleanup::New()) == NULL) |
|
102 { |
|
103 r = KErrNoMemory; |
|
104 goto cleanup; |
|
105 } |
|
106 |
|
107 // Make copies of the filename and store data. |
|
108 __PRINT(_L("dlw:cp dat")); |
|
109 TRAP(r, dw = TDelayedWriter::NewL(dwi)); |
|
110 if (r != KErrNone) |
|
111 goto cleanup; |
|
112 |
|
113 // Tell file server made local copies of data and so can continue. |
|
114 __PRINT(_L("dlw:sg cp dat")); |
|
115 if ((r = svrSem.OpenGlobal(*dwi->iSemName)) != KErrNone) |
|
116 goto cleanup; |
|
117 svrSem.Signal(); |
|
118 |
|
119 // Wait for the other store threads to finish. |
|
120 __PRINT(_L("dlw:wait")); |
|
121 if ((r = queueSem.OpenGlobal(_L("dwsem"))) != KErrNone) |
|
122 goto cleanup; |
|
123 queueSem.Wait(); |
|
124 |
|
125 // Write the data and signal the global semaphore so follow up threads can run. |
|
126 __PRINT(_L("dlw:wrt")); |
|
127 TRAP(r, DelayedWriterL(dw)); |
|
128 __PRINT1(_L("dlw:wrt r = %d"), r); |
|
129 queueSem.Signal(); |
|
130 |
|
131 cleanup: // free any opened resources |
|
132 __PRINT(_L("dlw:cln")); |
|
133 svrSem.Close(); |
|
134 delete th; |
|
135 delete dw; |
|
136 queueSem.Close(); |
|
137 |
|
138 return KErrNone; |
|
139 } |
|
140 |
|
141 |
|
142 LOCAL_D void DelayedWriterL(const TDelayedWriter *aDW) |
|
143 // |
|
144 // Replace any existing store file; write data and set file as hidden and system. |
|
145 // |
|
146 { |
|
147 __PRINT(_L("DelayedWriterL")); |
|
148 |
|
149 RFs fs; // connect to the file server |
|
150 CleanupClosePushL(fs); |
|
151 User::LeaveIfError(fs.Connect()); |
|
152 |
|
153 RFile f; // replace any existing file |
|
154 CleanupClosePushL(f); |
|
155 |
|
156 __PRINT(_L("dlw: opn")); |
|
157 |
|
158 // Create the directory if it doesn't already exist |
|
159 TInt r; |
|
160 r = fs.MkDirAll(*aDW->iFileName); |
|
161 if (r != KErrNone && r != KErrAlreadyExists) |
|
162 { |
|
163 __PRINT(_L("dlw: MkDirAll err")); |
|
164 User::Leave(r); |
|
165 } |
|
166 |
|
167 User::LeaveIfError(f.Replace(fs, *aDW->iFileName, EFileShareExclusive | EFileStream | EFileWrite)); |
|
168 __PRINT(_L("dlw: wrt")); |
|
169 User::LeaveIfError(f.Write(*aDW->iData)); |
|
170 __PRINT(_L("dlw: sat")); |
|
171 #ifndef __WINS__ // cannot replace hidden | system file in WINS. |
|
172 User::LeaveIfError(f.SetAtt(KEntryAttHidden | KEntryAttSystem, 0x00000000)); |
|
173 #endif |
|
174 __PRINT(_L("dlw: dst")); |
|
175 CleanupStack::PopAndDestroy(2); // f, fs |
|
176 } |
|
177 |
|
178 // |
|
179 // TDelayedWriter |
|
180 // |
|
181 |
|
182 TDelayedWriter *TDelayedWriter::NewL(const TDelayedWriterInit *dwi) |
|
183 // |
|
184 // static |
|
185 // Allocates a TDelayedWriter structure on the thread's heap that is used to |
|
186 // persist the data that the writer thread will need during its lifetime. |
|
187 // |
|
188 { |
|
189 __PRINT(_L("TDelayedWriter::NewL")); |
|
190 |
|
191 TDelayedWriter *self = new(ELeave) TDelayedWriter(); |
|
192 CleanupStack::PushL(self); |
|
193 self->ConstructL(dwi); |
|
194 CleanupStack::Pop(); // self |
|
195 return self; |
|
196 } |
|
197 |
|
198 |
|
199 TDelayedWriter::TDelayedWriter() |
|
200 { |
|
201 __PRINT(_L("TDelayedWriter::TDelayedWriter")); |
|
202 |
|
203 // empty. |
|
204 } |
|
205 |
|
206 |
|
207 void TDelayedWriter::ConstructL(const TDelayedWriterInit *dwi) |
|
208 // |
|
209 // 2y initialisation. Makes own copy of filename and data. |
|
210 // Fields are not popped onto CleanupStack because will be deleted in dtor |
|
211 // |
|
212 { |
|
213 __PRINT(_L("TDelayedWriter::ConstructL")); |
|
214 |
|
215 iFileName = dwi->iFileName->AllocL(); |
|
216 iData = dwi->iData->AllocL(); |
|
217 } |
|
218 |
|
219 TDelayedWriter::~TDelayedWriter() |
|
220 // |
|
221 // dtor - frees filename and store data that was allocated in ConstructL(). |
|
222 // |
|
223 { |
|
224 __PRINT(_L("TDelayedWriter::~TDelayedWriter")); |
|
225 |
|
226 delete iFileName; // alloc in ConstructL() |
|
227 delete iData; // alloc in server |
|
228 } |
|
229 |
|
230 #else |
|
231 |
|
232 EXPORT_C void WriteToDisk(const TDesC& /*aFileName*/, const TDesC8& /*aBuf*/) |
|
233 // |
|
234 // |
|
235 // |
|
236 {} |
|
237 |
|
238 #endif |