|
1 /* |
|
2 * Copyright (c) 2003-2006 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 "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: File server interface class representing a mount. |
|
15 * An instance of this object is referred to as |
|
16 * a mount control block. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 #include "rsfwfsmountcb.h" |
|
24 #include "rsfwfsfilecb.h" |
|
25 #include "rsfwfsdircb.h" |
|
26 |
|
27 |
|
28 // there is no good way to give remote storage size so just put some big numbers here |
|
29 const TInt KMountReportedSize = 999999999; |
|
30 const TInt KMountReportedFreeSize = 999999999; |
|
31 |
|
32 // ============================ MEMBER FUNCTIONS =============================== |
|
33 |
|
34 // ----------------------------------------------------------------------------- |
|
35 // CRsfwFsMountCB::NewL |
|
36 // C++ default constructor can NOT contain any code, that |
|
37 // might leave. |
|
38 // ----------------------------------------------------------------------------- |
|
39 // |
|
40 CRsfwFsMountCB* CRsfwFsMountCB::NewL() |
|
41 { |
|
42 CRsfwFsMountCB* remoteFsMntCB = new(ELeave) CRsfwFsMountCB(); |
|
43 return remoteFsMntCB; |
|
44 } |
|
45 |
|
46 // ----------------------------------------------------------------------------- |
|
47 // CRsfwFsMountCB::CRsfwFsMountCB |
|
48 // C++ default constructor can NOT contain any code, that |
|
49 // might leave. |
|
50 // ----------------------------------------------------------------------------- |
|
51 // |
|
52 CRsfwFsMountCB::CRsfwFsMountCB() |
|
53 { |
|
54 |
|
55 } |
|
56 |
|
57 // Destructor |
|
58 CRsfwFsMountCB::~CRsfwFsMountCB() |
|
59 { |
|
60 } |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // CRsfwFsMountCB::MountL |
|
64 // The function should set the volume name (iVolumeName), the unique ID |
|
65 // (iUniqueID) and the volume size (iSize) by reading and processing the current |
|
66 // mount. The function should leave, on error detection, with an appropriate error |
|
67 // code. When aForceMount is set to ETrue, the properties of a corrupt volume |
|
68 // should be forcibly stored. The classic case of when this is desirable is when a |
|
69 // corrupt volume needs to be formatted. |
|
70 // |
|
71 // We set the values (iSize to a fixed size). We also create a |
|
72 // File Server session (needed to access the local cache) and put the handle into |
|
73 // the TLS for future access. aForceMount is ignored. |
|
74 // Note that this operation does not attempt to connect to remote server. |
|
75 // |
|
76 // (other items were commented in a header). |
|
77 // ----------------------------------------------------------------------------- |
|
78 // |
|
79 void CRsfwFsMountCB::MountL( |
|
80 TBool /* aForceMount */) |
|
81 { |
|
82 |
|
83 iServerName = HBufC::NewL( KMaxVolumeNameLength); |
|
84 TPtr serverName (iServerName->Des()); |
|
85 serverName.Append(KRemoteVolumeName); |
|
86 SetVolumeName(iServerName); |
|
87 |
|
88 TTime timeID; |
|
89 timeID.HomeTime(); |
|
90 iUniqueID = I64LOW(timeID.Int64()); |
|
91 iSize = KMountReportedSize; |
|
92 |
|
93 User::LeaveIfError(iFsSession.Connect()); |
|
94 User::LeaveIfError(Dll::SetTls(&iFsSession)); |
|
95 |
|
96 iRootFid.iVolumeId = Drive().DriveNumber(); |
|
97 iRootFid.iNodeId = 1; |
|
98 } |
|
99 |
|
100 |
|
101 // ----------------------------------------------------------------------------- |
|
102 // CRsfwFsMountCB::ReMount |
|
103 // The function should check whether the mount control block represents the |
|
104 // current mount on the associated drive. The function should read mount |
|
105 // information from the current volume, and check it against the mount |
|
106 // information from this mount - typically iVolumeName and iUniqueID. If the mount |
|
107 // information matches, the function should return KErrNone, otherwise it should |
|
108 // return KErrGeneral. |
|
109 // (other items were commented in a header). |
|
110 // ----------------------------------------------------------------------------- |
|
111 // |
|
112 int CRsfwFsMountCB::ReMount() |
|
113 { |
|
114 // we assume that this operation - if called on remote drive |
|
115 // - can be succesfull |
|
116 return KErrNone; |
|
117 |
|
118 } |
|
119 |
|
120 // ----------------------------------------------------------------------------- |
|
121 // CRsfwFsMountCB::Dismounted |
|
122 // Carries out clean-up necessary for a volume dismount: |
|
123 // Closing the session to the File Server used for local cache. |
|
124 // Closing the session to Remote File Engine. |
|
125 // Dismounting a volume will always succeed, so the function does not need to |
|
126 // return an error value. |
|
127 // (other items were commented in a header). |
|
128 // ----------------------------------------------------------------------------- |
|
129 // |
|
130 void CRsfwFsMountCB::Dismounted() |
|
131 { |
|
132 |
|
133 iSession->Close(); |
|
134 iFsSession.Close(); |
|
135 |
|
136 } |
|
137 |
|
138 // ----------------------------------------------------------------------------- |
|
139 // CRsfwFsMountCB::VolumeL |
|
140 // Gets volume information. The only information that the function has to supply |
|
141 // is the free space, TVolumeInfo::iFree, since the remaining members have already |
|
142 // been set by the calling function. The function should leave, on error detection, |
|
143 // with an appropriate error code. |
|
144 // (other items were commented in a header). |
|
145 // ----------------------------------------------------------------------------- |
|
146 // |
|
147 void CRsfwFsMountCB::VolumeL( |
|
148 TVolumeInfo& aVolume) const |
|
149 { |
|
150 |
|
151 // : we should return info about free storage |
|
152 // at the remote server, if possible... |
|
153 aVolume.iFree = KMountReportedFreeSize; |
|
154 |
|
155 } |
|
156 |
|
157 // ----------------------------------------------------------------------------- |
|
158 // CRsfwFsMountCB::SetVolumeL |
|
159 // Sets the volume name for the mount, thus writing the new volume name to the |
|
160 // corresponding volume. |
|
161 // (other items were commented in a header). |
|
162 // ----------------------------------------------------------------------------- |
|
163 // |
|
164 void CRsfwFsMountCB::SetVolumeL( |
|
165 TDes& aName) |
|
166 { |
|
167 |
|
168 if (aName.Length() > KMaxVolumeNameLength) |
|
169 { |
|
170 User::Leave(KErrBadName); |
|
171 } |
|
172 if (iServerName) |
|
173 { |
|
174 delete iServerName; |
|
175 iServerName = NULL; |
|
176 } |
|
177 iServerName = HBufC::NewL( KMaxVolumeNameLength); |
|
178 TPtr serverName (iServerName->Des()); |
|
179 serverName.Append(aName); |
|
180 SetVolumeName(iServerName); |
|
181 |
|
182 } |
|
183 |
|
184 // ----------------------------------------------------------------------------- |
|
185 // CRsfwFsMountCB::MkDirL |
|
186 // Creates a new directory on the mount by figuring out the FID of the parent |
|
187 // directory and the name of the child to be created. |
|
188 // |
|
189 // The full name in aName is in the form: |
|
190 // \\dirA\\dirB\\dirC\\dirD |
|
191 // where dirD is the new directory to be created in \\dirA\\dirB\\dirC\\. |
|
192 // This means that dirC is the leaf directory in which dirD will be created. |
|
193 // |
|
194 // (other items were commented in a header). |
|
195 // ----------------------------------------------------------------------------- |
|
196 // |
|
197 void CRsfwFsMountCB::MkDirL( |
|
198 const TDesC& aName) |
|
199 { |
|
200 |
|
201 TInt delimiterPos; |
|
202 TPtrC directory, path; |
|
203 TFid theFid; |
|
204 |
|
205 delimiterPos = aName.LocateReverse(KPathDelimiter); |
|
206 directory.Set(aName.Right(aName.Length() - (delimiterPos + 1))); |
|
207 path.Set(aName.Left(delimiterPos + 1)); |
|
208 theFid = FetchFidL(path, KNodeTypeDir); |
|
209 User::LeaveIfError(RSessionL()->MakeDirectory(theFid, directory)); |
|
210 |
|
211 } |
|
212 |
|
213 |
|
214 // ----------------------------------------------------------------------------- |
|
215 // CRsfwFsMountCB::RmDirL |
|
216 // Removes the directory specified by aName by figuring out the FID of the parent |
|
217 // directory and the name of the child to be created. The function can assume |
|
218 // that the directory exists and is not read-only. |
|
219 // |
|
220 // The directory specified by aName is in the form: |
|
221 // \\dirA\\dirB\\dirC\\dirD |
|
222 // where dirD is the directory to be removed from \\dirA\\dirB\\dirC\\. |
|
223 // This means that dirC is the leaf directory from which dirD should be removed. |
|
224 // |
|
225 // (other items were commented in a header). |
|
226 // ----------------------------------------------------------------------------- |
|
227 // |
|
228 void CRsfwFsMountCB::RmDirL( |
|
229 const TDesC& aName) |
|
230 { |
|
231 |
|
232 TInt delimiterPos; |
|
233 TPtrC directory, path; |
|
234 TFid parentFid; |
|
235 |
|
236 delimiterPos = aName.LocateReverse(KPathDelimiter); |
|
237 directory.Set(aName.Right(aName.Length() - (delimiterPos + 1))); |
|
238 path.Set(aName.Left(delimiterPos + 1)); |
|
239 parentFid = FetchFidL(path, KNodeTypeDir); |
|
240 User::LeaveIfError(RSessionL()->RemoveDirectory(parentFid, directory)); |
|
241 |
|
242 } |
|
243 |
|
244 // ----------------------------------------------------------------------------- |
|
245 // CRsfwFsMountCB::DeleteL |
|
246 // Deletes the specified file from the mount by figuring out the FID of the parent |
|
247 // directory and the name of the child to be created. The function can assume that |
|
248 // the file is closed. |
|
249 // |
|
250 // The file name specified by aName is of the form: |
|
251 // \\dirA\\dirB\\dirC\\file.ext |
|
252 // The extension is optional. |
|
253 // |
|
254 // (other items were commented in a header). |
|
255 // ----------------------------------------------------------------------------- |
|
256 // |
|
257 |
|
258 void CRsfwFsMountCB::DeleteL( |
|
259 const TDesC& aName) |
|
260 { |
|
261 |
|
262 TInt delimiterPos; |
|
263 TPtrC file, path; |
|
264 TFid parentFid; |
|
265 |
|
266 delimiterPos = aName.LocateReverse(KPathDelimiter); |
|
267 file.Set(aName.Right(aName.Length() - (delimiterPos + 1))); |
|
268 path.Set(aName.Left(delimiterPos + 1)); |
|
269 parentFid = FetchFidL(path, KNodeTypeDir); |
|
270 User::LeaveIfError(RSessionL()->RemoveFile(parentFid, file)); |
|
271 |
|
272 } |
|
273 |
|
274 // ----------------------------------------------------------------------------- |
|
275 // CRsfwFsMountCB::RenameL |
|
276 // Renames or moves a single file or directory on the mount by figuring out |
|
277 // the FIDs of the parent directories and child names for both anOldName and |
|
278 // anNewName. If oldEntryName is a file, it can be assumed that it is closed. |
|
279 // If oldEntryName is a directory, it can be assumed that there are no |
|
280 // open files in this directory. Furthermore, if newEntryName specifies |
|
281 // a directory, it can be assumed that it is not a subdirectory of oldEntryName. |
|
282 // |
|
283 // anOldName and anNewName specify the respective entries with full names; |
|
284 // for example, |
|
285 // \\dirA\\dirB\\dirC\\oldEntryName |
|
286 // and |
|
287 // \\dirE\\dirF\\dirG\\newEntryName |
|
288 // |
|
289 // (other items were commented in a header). |
|
290 // ----------------------------------------------------------------------------- |
|
291 // |
|
292 void CRsfwFsMountCB::RenameL( |
|
293 const TDesC& anOldName, |
|
294 const TDesC& aNewName) |
|
295 { |
|
296 |
|
297 TInt delimiterPos; |
|
298 TPtrC sourcepath, destpath; |
|
299 TPtrC srcname, destname; |
|
300 TFid sourceFid, destFid; |
|
301 |
|
302 delimiterPos = anOldName.LocateReverse(KPathDelimiter); |
|
303 srcname.Set(anOldName.Right(anOldName.Length() - (delimiterPos + 1))); |
|
304 sourcepath.Set(anOldName.Left(delimiterPos + 1)); |
|
305 sourceFid = FetchFidL(sourcepath, KNodeTypeDir); |
|
306 |
|
307 delimiterPos = aNewName.LocateReverse(KPathDelimiter); |
|
308 destname.Set(aNewName.Right(aNewName.Length() - (delimiterPos + 1))); |
|
309 destpath.Set(aNewName.Left(delimiterPos + 1)); |
|
310 destFid = FetchFidL(destpath, KNodeTypeDir); |
|
311 |
|
312 User::LeaveIfError(RSessionL()->MoveFids(sourceFid, |
|
313 srcname, |
|
314 destFid, |
|
315 destname, |
|
316 EFalse)); |
|
317 |
|
318 |
|
319 } |
|
320 |
|
321 // ----------------------------------------------------------------------------- |
|
322 // CRsfwFsMountCB::ReplaceL |
|
323 // Replaces one file on the mount with another. The file anOldName should have |
|
324 // its contents, attributes, and the universal date and time of its last |
|
325 // modification, copied to the file aNewName, overwriting any existing contents |
|
326 // and attribute details. If the file aNewName does not exist it should be created. |
|
327 // The function can assume that both anOldName and, if it exists, anNewName |
|
328 // contain the full file names of files, and that these files are not open. |
|
329 // (other items were commented in a header). |
|
330 // ----------------------------------------------------------------------------- |
|
331 // |
|
332 void CRsfwFsMountCB::ReplaceL( |
|
333 const TDesC& anOldName, |
|
334 const TDesC& aNewName ) |
|
335 { |
|
336 |
|
337 TInt delimiterPos; |
|
338 TPtrC sourcepath, destpath; |
|
339 TPtrC srcname, destname; |
|
340 TFid sourceFid, destFid; |
|
341 |
|
342 delimiterPos = anOldName.LocateReverse(KPathDelimiter); |
|
343 srcname.Set(anOldName.Right(anOldName.Length() - (delimiterPos + 1))); |
|
344 sourcepath.Set(anOldName.Left(delimiterPos + 1)); |
|
345 sourceFid = FetchFidL(sourcepath, KNodeTypeDir); |
|
346 |
|
347 delimiterPos = aNewName.LocateReverse(KPathDelimiter); |
|
348 destname.Set(aNewName.Right(aNewName.Length() - (delimiterPos + 1))); |
|
349 destpath.Set(aNewName.Left(delimiterPos + 1)); |
|
350 destFid = FetchFidL(destpath, KNodeTypeDir); |
|
351 |
|
352 User::LeaveIfError(RSessionL()->MoveFids(sourceFid, |
|
353 srcname, |
|
354 destFid, |
|
355 destname, |
|
356 ETrue)); |
|
357 |
|
358 |
|
359 } |
|
360 |
|
361 // ----------------------------------------------------------------------------- |
|
362 // CRsfwFsMountCB::EntryL |
|
363 // Gets the entry details for the specified file or directory. |
|
364 // This function is defined as a const function in the base class CMountCB. |
|
365 // However, we need to modify the shared memory chunks used in the parameter |
|
366 // passing. That's why we need to cast away const. |
|
367 // |
|
368 // Always returns KErrPathNotFoud for certain Symbian system directories. The |
|
369 // reason for this is that scanning all drives for some system directory does |
|
370 // not always skip remote drives, but it is not feasible to start to look |
|
371 // for some library, recognizer etc. from a remote drive. |
|
372 // |
|
373 // (other items were commented in a header). |
|
374 // ----------------------------------------------------------------------------- |
|
375 // |
|
376 void CRsfwFsMountCB::EntryL( |
|
377 const TDesC& aName, |
|
378 TEntry& anEntry) const |
|
379 { |
|
380 |
|
381 if (aName.Length() > KMaxPath) |
|
382 { |
|
383 User::Leave(KErrBadName); |
|
384 } |
|
385 |
|
386 CONST_CAST(CRsfwFsMountCB*, this)->RemoteFsEntryL(aName, anEntry); |
|
387 |
|
388 } |
|
389 |
|
390 // ----------------------------------------------------------------------------- |
|
391 // CRsfwFsMountCB::RemoteFsEntryL |
|
392 // Gets the entry details for the specified file or directory by figuring out |
|
393 // the fid of the entry. |
|
394 // (other items were commented in a header). |
|
395 // ----------------------------------------------------------------------------- |
|
396 // |
|
397 void CRsfwFsMountCB::RemoteFsEntryL(const TDesC& aName, TEntry& anEntry) |
|
398 { |
|
399 |
|
400 anEntry.iName = aName; |
|
401 TFid fileFid = FetchFidL(aName, KNodeTypeUnknown); |
|
402 User::LeaveIfError(RSessionL()->GetAttributes(fileFid, anEntry)); |
|
403 |
|
404 } |
|
405 |
|
406 // ----------------------------------------------------------------------------- |
|
407 // CRsfwFsMountCB::SetEntryL |
|
408 // Sets entry details for a specified file or directory. |
|
409 // The entry identified by the full name descriptor aName should have |
|
410 // its modification time and its attributes mask updated as required. |
|
411 // We also use this function to control (using new attributes bits) the file |
|
412 // caching state (KEntryAttCachePriorityHigh) |
|
413 // |
|
414 // The entry receives a new universal modified time from aTime. |
|
415 // The entry attributes are set with aSetAttMask and cleared with aClearAttMask: |
|
416 // the bits that are set in aSetAttMask should be set in the entry attribute mask; |
|
417 // the bits that are set in aClearAttMask should be cleared from the entry |
|
418 // attribute mask. |
|
419 // |
|
420 // The function can assume that aSetAttMask and aClearAttMask do not change |
|
421 // the type of attribute (i.e. volume or directory). Furthermore, if aName |
|
422 // specifies a file, it can be assumed that this file is closed. |
|
423 // |
|
424 // (other items were commented in a header). |
|
425 // ----------------------------------------------------------------------------- |
|
426 // |
|
427 void CRsfwFsMountCB::SetEntryL( |
|
428 const TDesC& aName, |
|
429 const TTime& aTime, |
|
430 TUint aSetAttMask, |
|
431 TUint aClearAttMask) |
|
432 { |
|
433 |
|
434 TFid thisFid; |
|
435 thisFid = FetchFidL(aName, KNodeTypeUnknown); |
|
436 |
|
437 TInt result = RSessionL()->SetEntry(thisFid, aTime, aSetAttMask, aClearAttMask); |
|
438 |
|
439 // KErrNotSupported is dismissed currently |
|
440 // The reason for this is CFileMan::Copy |
|
441 // CFileMan::Copy is a composite operation which as a last step |
|
442 // calls RFs::SetAtt() for the target file. |
|
443 // If we honestly return KErrNotSupported CFileMan::Copy will now |
|
444 // return KErrNotSupported also, although it already copied the file on the server. |
|
445 // We rather have a working copy and return false information about the success of |
|
446 // SetAtt(). |
|
447 if ((result != KErrNone) && (result != KErrNotSupported)) |
|
448 { |
|
449 User::Leave(result); |
|
450 } |
|
451 |
|
452 } |
|
453 |
|
454 |
|
455 // ----------------------------------------------------------------------------- |
|
456 // CRsfwFsMountCB::FileOpenL |
|
457 // If needed creates a new file by figuring out the FID of the parent directory |
|
458 // and the name of the new file. After that opens the file. After successful |
|
459 // completion of the function, the file control block pointer will be added to the |
|
460 // file server's global files container. Adds information to the file control |
|
461 // block (e.g. path of the local cache file and pointer to this mount control block) |
|
462 // |
|
463 // If anOpen specifies EFileReplace (rather than EFileCreate or EFileOpen) then |
|
464 // the data contained in the file should be discarded, the archive attribute |
|
465 // should be set, and the size of the file should be set to zero. Note that it can |
|
466 // be assumed that if anOpen specifies EFileReplace then the file already exists. |
|
467 // |
|
468 // (other items were commented in a header). |
|
469 // ----------------------------------------------------------------------------- |
|
470 // |
|
471 void CRsfwFsMountCB::FileOpenL( |
|
472 const TDesC& aName, |
|
473 TUint aMode, |
|
474 TFileOpen anOpen, |
|
475 CFileCB* aFile) |
|
476 { |
|
477 |
|
478 TFid parentFid; |
|
479 TFid thisFid; |
|
480 TInt delimiterPos; |
|
481 TPtrC filename, path; |
|
482 delimiterPos = aName.LocateReverse(KPathDelimiter); |
|
483 filename.Set(aName.Right(aName.Length() - (delimiterPos + 1))); |
|
484 path.Set(aName.Left(delimiterPos + 1)); |
|
485 parentFid = FetchFidL(path, KNodeTypeDir); |
|
486 |
|
487 switch (anOpen) |
|
488 { |
|
489 case EFileCreate: |
|
490 // exclusive = 1 |
|
491 User::LeaveIfError(RSessionL()-> |
|
492 CreateFile(parentFid, filename, aMode, TRUE, thisFid)); |
|
493 break; |
|
494 case EFileReplace: |
|
495 // exclusive = 0 |
|
496 User::LeaveIfError(RSessionL()-> |
|
497 CreateFile(parentFid, filename, aMode, FALSE, thisFid)); |
|
498 break; |
|
499 case EFileOpen: // the file must exist |
|
500 default: |
|
501 User::LeaveIfError(RSessionL()-> |
|
502 Lookup(parentFid, filename, KNodeTypeFile, thisFid)); |
|
503 break; |
|
504 } |
|
505 |
|
506 TDirEntAttr attributes; |
|
507 HBufC* unicodepath = HBufC::NewMaxLC(KMaxPath); |
|
508 TPtr unicodepathptr(unicodepath->Des()); |
|
509 attributes.iAtt = aMode; |
|
510 User::LeaveIfError(RSessionL()-> |
|
511 OpenByPath(thisFid, unicodepathptr, &attributes, ETrue)); |
|
512 unicodepathptr.SetLength(unicodepath->Length()); |
|
513 |
|
514 ((CRsfwFsFileCB*)aFile)->iLastFlushFailed = EFalse; |
|
515 ((CRsfwFsFileCB*)aFile)->iThisFid = thisFid; |
|
516 ((CRsfwFsFileCB*)aFile)->iParentFid = parentFid; |
|
517 ((CRsfwFsFileCB*)aFile)->SetContainerFileL(unicodepathptr); |
|
518 // set size, att, modified for the file |
|
519 ((CRsfwFsFileCB*)aFile)->SetSize(attributes.iSize); |
|
520 ((CRsfwFsFileCB*)aFile)->SetAtt(attributes.iAtt); |
|
521 ((CRsfwFsFileCB*)aFile)->SetModified(attributes.iModified); |
|
522 aFile->SetMount(this); |
|
523 CleanupStack::PopAndDestroy(unicodepath); // unicodepath |
|
524 |
|
525 } |
|
526 |
|
527 // ----------------------------------------------------------------------------- |
|
528 // CRsfwFsMountCB::DirOpenL |
|
529 // Opens a directory on the mount by figuring out the FID of the parent |
|
530 // directory and the name of the directory. |
|
531 // Note that aName is of the form |
|
532 // \\dirA\\dirB\\dirC\\file.ext |
|
533 // where \\dirA\\dirB\\dirC\\ is the directory to be opened and file.ext is |
|
534 // an optional entry name and extension. The name and extension (e.g. "*" or |
|
535 // "*.txt") limit entries that reading the directory should return. |
|
536 // |
|
537 // Always returns KErrPathNotFoud for certain Symbian system directories. The |
|
538 // reason for this is that scanning all drives for some system directory does |
|
539 // not always skip remote drives, but it is not feasible to start to look |
|
540 // for some library, recognizer etc. from a remote drive. |
|
541 // |
|
542 // After successful completion of the function, the directory control block |
|
543 // pointer will be added to the file server global directories container. Adds |
|
544 // information to the directory control block (e.g. path of the local cache file |
|
545 // and possible name and extension) |
|
546 // (other items were commented in a header). |
|
547 // ----------------------------------------------------------------------------- |
|
548 // |
|
549 void CRsfwFsMountCB::DirOpenL( |
|
550 const TDesC& aName, |
|
551 CDirCB* aDir) |
|
552 { |
|
553 |
|
554 TFid fileFid; |
|
555 TInt namePos; |
|
556 namePos = aName.LocateReverse(KPathDelimiter); |
|
557 TPtrC directoryPathName(aName.Left(namePos + 1)); |
|
558 TPtrC matchName(aName.Mid(namePos + 1)); |
|
559 if (matchName.Length() == 0) |
|
560 { |
|
561 matchName.Set(KDirReadAllMask); |
|
562 } |
|
563 if (directoryPathName.Length() == 0) |
|
564 { |
|
565 fileFid = iRootFid; |
|
566 } |
|
567 else |
|
568 { |
|
569 fileFid = FetchFidL(directoryPathName, KNodeTypeDir); |
|
570 } |
|
571 |
|
572 HBufC* unicodepath = HBufC::NewMaxLC(KMaxPath); |
|
573 TPtr unicodepathptr(unicodepath->Des()); |
|
574 User::LeaveIfError(RSessionL()-> |
|
575 OpenByPath(fileFid, unicodepathptr, NULL, EFalse)); |
|
576 ((CRsfwFsDirCB*)aDir)->SetDirL(unicodepathptr, matchName); |
|
577 ((CRsfwFsDirCB*)aDir)->iThisFid = fileFid; |
|
578 ((CRsfwFsDirCB*)aDir)->SetMount(this); |
|
579 CleanupStack::PopAndDestroy(unicodepath); // unicopath |
|
580 |
|
581 } |
|
582 |
|
583 // ----------------------------------------------------------------------------- |
|
584 // CRsfwFsMountCB::RawReadL |
|
585 // Should read the specified length of data from the specified position on |
|
586 // the volume directly into the client thread. It can be assumed that if this |
|
587 // function is called, then there has been a successful mount. |
|
588 // Not supported, as "position in a volume" without files is meaningless to |
|
589 // us. |
|
590 // (other items were commented in a header). |
|
591 // ----------------------------------------------------------------------------- |
|
592 // |
|
593 void CRsfwFsMountCB::RawReadL( |
|
594 TInt64 /* aPos */, |
|
595 TInt /* aLength */ , |
|
596 const TAny* /* aTrg */, |
|
597 TInt /* anOffset */ , |
|
598 const RMessagePtr2& /* aMessage */) const |
|
599 { |
|
600 |
|
601 User::Leave(KErrNotSupported); |
|
602 |
|
603 } |
|
604 |
|
605 // ----------------------------------------------------------------------------- |
|
606 // CRsfwFsMountCB::RawWriteL |
|
607 // Should write a specified length of data from the client thread to the volume |
|
608 // at the specified position. It can be assumed that if this |
|
609 // function is called, then there has been a successful mount. |
|
610 // Not supported, as "position in a volume" without files is meaningless to |
|
611 // us. |
|
612 // (other items were commented in a header). |
|
613 // ----------------------------------------------------------------------------- |
|
614 // |
|
615 void CRsfwFsMountCB::RawWriteL( |
|
616 TInt64 /* aPos */, |
|
617 TInt /* aLength */, |
|
618 const TAny* /* aSrc */, |
|
619 TInt /* anOffset */, |
|
620 const RMessagePtr2& /* aMessage */) |
|
621 { |
|
622 |
|
623 User::Leave(KErrNotSupported); |
|
624 |
|
625 } |
|
626 |
|
627 // ----------------------------------------------------------------------------- |
|
628 // CRsfwFsMountCB::GetShortNameL |
|
629 // Should get the short name of the file or directory with the given full name. |
|
630 // This function is used in circumstances where a file system mangles |
|
631 // Symbian OS natural names, in order to be able to store them on |
|
632 // a file system that is not entirely compatible. |
|
633 // (other items were commented in a header). |
|
634 // ----------------------------------------------------------------------------- |
|
635 // |
|
636 void CRsfwFsMountCB::GetShortNameL( |
|
637 const TDesC& /* aLongName */, |
|
638 TDes& /* aShortName */) |
|
639 { |
|
640 |
|
641 User::Leave(KErrNotSupported); |
|
642 |
|
643 } |
|
644 |
|
645 // ----------------------------------------------------------------------------- |
|
646 // CRsfwFsMountCB::GetLongNameL |
|
647 // Should get the long name of the file or directory associated with the given |
|
648 // short name. This function is used in circumstances where a file system mangles |
|
649 // Symbian OS natural names in order to be able to store them on |
|
650 // a file system that is not entirely compatible. |
|
651 // (other items were commented in a header). |
|
652 // ----------------------------------------------------------------------------- |
|
653 // |
|
654 void CRsfwFsMountCB::GetLongNameL( |
|
655 const TDesC& /* aShortName */, |
|
656 TDes& /* aLongName */) |
|
657 { |
|
658 |
|
659 User::Leave(KErrNotSupported); |
|
660 |
|
661 } |
|
662 |
|
663 // ----------------------------------------------------------------------------- |
|
664 // CRsfwFsMountCB::ReadSectionL |
|
665 // Reads a specified section of the file, regardless of the file's lock state. |
|
666 // This function basically does what the chain of opening a file, creating |
|
667 // the file control block, and reading file data using CRsfwFsFile::Read() |
|
668 // does, but without creating the file control block. For us file's lock state |
|
669 // does not have meaning. |
|
670 // (other items were commented in a header). |
|
671 // ----------------------------------------------------------------------------- |
|
672 // |
|
673 void CRsfwFsMountCB::ReadSectionL( |
|
674 const TDesC& aName, |
|
675 TInt aPos, |
|
676 TAny* /*aTrg */, |
|
677 TInt aLength, |
|
678 const RMessagePtr2& aMessage) |
|
679 |
|
680 { |
|
681 |
|
682 HBufC8* data = HBufC8::NewMaxLC(aLength); |
|
683 TPtr8 buf(data->Des()); |
|
684 |
|
685 TFid parentFid; |
|
686 TFid newFid; |
|
687 TInt delimiterPos; |
|
688 TPtrC filename, path; |
|
689 HBufC* unicodepath = HBufC::NewMaxLC(KMaxPath); |
|
690 TPtr unicodepathptr(unicodepath->Des()); |
|
691 |
|
692 delimiterPos = aName.LocateReverse(KPathDelimiter); |
|
693 filename.Set(aName.Right(aName.Length() - (delimiterPos + 1))); |
|
694 path.Set(aName.Left(delimiterPos + 1)); |
|
695 parentFid = FetchFidL(path, KNodeTypeDir); |
|
696 User::LeaveIfError(RSessionL()-> |
|
697 Lookup(parentFid, filename, KNodeTypeFile, newFid)); |
|
698 User::LeaveIfError(RSessionL()-> |
|
699 OpenByPath(newFid, unicodepathptr, NULL, EFalse)); |
|
700 |
|
701 // get the size of the container file |
|
702 TEntry tentry; |
|
703 User::LeaveIfError((*(RFs* )Dll::Tls()).Entry(unicodepathptr, tentry)); |
|
704 if (aPos > tentry.iSize) |
|
705 { |
|
706 // non-sequential read |
|
707 // i.e. if 128 bytes have been cached |
|
708 // starting read from pos 128 continues to fill the cache file |
|
709 // but starting read from pos 129- is "random access" |
|
710 // that by-passes the cache */ |
|
711 RFile tempFile; |
|
712 TBool usetempCache = EFalse; |
|
713 HBufC* tmpcacheFile = HBufC::NewLC(KMaxPath); |
|
714 TPtr tmpCache(tmpcacheFile->Des()); |
|
715 User::LeaveIfError(RSessionL()->FetchData(newFid, |
|
716 aPos, |
|
717 aPos + aLength - 1, |
|
718 tmpCache, |
|
719 usetempCache)); |
|
720 // if caching mode is "Whole File Caching" this operation may fetch |
|
721 // the whole file into normal cache anyway. "tmpCache" contains |
|
722 // the right path in this case too, so in this function (where the file |
|
723 // is not open), we don't have to check "usetempCache" boolean. |
|
724 User::LeaveIfError(tempFile.Open(*(RFs* )Dll::Tls(), tmpCache, EFileRead)); |
|
725 CleanupClosePushL(tempFile); |
|
726 User::LeaveIfError(tempFile.Read(buf, aLength)); |
|
727 CleanupStack::PopAndDestroy(2, tmpcacheFile); // tempfile, tempcacheFile |
|
728 } |
|
729 else |
|
730 { |
|
731 TInt lastByte; |
|
732 User::LeaveIfError(RSessionL()->Fetch(newFid, aPos, aPos + aLength-1, lastByte)); |
|
733 User::LeaveIfError((*(RFs* )Dll::Tls()).ReadFileSection(*unicodepath, |
|
734 aPos, |
|
735 buf, |
|
736 aLength)); |
|
737 } |
|
738 CleanupStack::PopAndDestroy(unicodepath); // unicodepath |
|
739 |
|
740 // we have read the data into buf |
|
741 aMessage.WriteL(0, buf, 0); |
|
742 CleanupStack::PopAndDestroy(data); // data |
|
743 |
|
744 } |
|
745 |
|
746 |
|
747 |
|
748 // ----------------------------------------------------------------------------- |
|
749 // CRsfwFsMountCB::FetchFidL |
|
750 // Fetches fid for an entry. |
|
751 // aPath is of the form \\dirA\\dirB\\dirC\\entry |
|
752 // Goes through the path recursively. I.e. first gets the fid of dirA by |
|
753 // fid_dirA = lookup(iRootFid, dirA), then does lookup(fid_dirA, dirB) etc. |
|
754 // (other items were commented in a header). |
|
755 // ----------------------------------------------------------------------------- |
|
756 // |
|
757 TFid CRsfwFsMountCB::FetchFidL( |
|
758 const TDesC& aPath, |
|
759 TUint aNodeType) |
|
760 { |
|
761 TFid newFid; |
|
762 TInt pathlength = aPath.Length(); |
|
763 |
|
764 if (pathlength <= 1) |
|
765 { |
|
766 // '\' |
|
767 // In some rare cases called with zero length aPath, |
|
768 // it seems to be ok to return rootFid |
|
769 return iRootFid; |
|
770 } |
|
771 else |
|
772 { |
|
773 TInt delimiterPos = aPath.LocateReverse(KPathDelimiter); |
|
774 if (delimiterPos == (pathlength - 1)) |
|
775 { |
|
776 // The path ends with a slash, |
|
777 //i.e. this is a directory - continue parsing |
|
778 TPtrC nextdelimiter; |
|
779 nextdelimiter.Set(aPath.Left(delimiterPos)); |
|
780 delimiterPos = nextdelimiter.LocateReverse(KPathDelimiter); |
|
781 } |
|
782 TPtrC entry(aPath.Right(aPath.Length() - (delimiterPos + 1))); |
|
783 TPtrC path(aPath.Left(delimiterPos + 1)); |
|
784 // fetch recursively TFid of path |
|
785 User::LeaveIfError(RSessionL()-> |
|
786 Lookup(FetchFidL(path, KNodeTypeDir), entry, aNodeType, newFid)); |
|
787 return newFid; |
|
788 } |
|
789 |
|
790 } |
|
791 |
|
792 // ----------------------------------------------------------------------------- |
|
793 // CRsfwFsMountCB::RenameFidL |
|
794 // Renames a file |
|
795 // (other items were commented in a header). |
|
796 // ----------------------------------------------------------------------------- |
|
797 // |
|
798 void CRsfwFsMountCB::RenameFidL( |
|
799 TFid aDirFid, |
|
800 const TDesC& aSourceName, |
|
801 const TDesC& aNewName ) |
|
802 { |
|
803 |
|
804 TInt delimiterPos; |
|
805 TPtrC destpath, srcname, destname; |
|
806 TFid destFid; |
|
807 |
|
808 delimiterPos = aSourceName.LocateReverse(KPathDelimiter); |
|
809 srcname.Set(aSourceName.Right(aSourceName.Length() - (delimiterPos + 1))); |
|
810 |
|
811 delimiterPos = aNewName.LocateReverse(KPathDelimiter); |
|
812 destname.Set(aNewName.Right(aNewName.Length() - (delimiterPos + 1))); |
|
813 destpath.Set(aNewName.Left(delimiterPos + 1)); |
|
814 destFid = FetchFidL(destpath, KNodeTypeDir); |
|
815 |
|
816 User::LeaveIfError(RSessionL()->MoveFids(aDirFid, |
|
817 srcname, |
|
818 destFid, |
|
819 destname, |
|
820 EFalse)); |
|
821 |
|
822 } |
|
823 |
|
824 // ----------------------------------------------------------------------------- |
|
825 // CRsfwFsMountCB::CheckDisk |
|
826 // Checks the integrity of the disk on the specified drive |
|
827 // temporarily return KErrNone as a workaround for CommonDialogs |
|
828 // should return KErrNotSupported for remote drives |
|
829 // (other items were commented in a header). |
|
830 // ----------------------------------------------------------------------------- |
|
831 // |
|
832 TInt CRsfwFsMountCB::CheckDisk() |
|
833 { |
|
834 return KErrNone; |
|
835 } |
|
836 |
|
837 |
|
838 // ----------------------------------------------------------------------------- |
|
839 // CRsfwFsMountCB::RSessionL |
|
840 // Singleton-function that creates a session to Remote File Engine once. |
|
841 // (other items were commented in a header). |
|
842 // ----------------------------------------------------------------------------- |
|
843 // |
|
844 RRsfwSession* CRsfwFsMountCB::RSessionL() |
|
845 { |
|
846 |
|
847 if (!iSession) |
|
848 { |
|
849 iSession = new (ELeave) RRsfwSession(); |
|
850 User::LeaveIfError(iSession->Connect()); |
|
851 } |
|
852 return iSession; |
|
853 |
|
854 } |
|
855 |
|
856 |
|
857 // End of File |