|
1 // Copyright (c) 1997-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 "FDESC.H" |
|
17 #include "LPOSIX.H" |
|
18 #include "LTIME.H" |
|
19 #include <string.h> |
|
20 #include <stdio_r.h> |
|
21 #include <fcntl.h> // for struct stat |
|
22 #include <sys/errno.h> // for ENOTSOCK |
|
23 #include <sys/ioctl.h> |
|
24 #include <c32comm.h> |
|
25 |
|
26 #include "POSIXIF.H" // for details of CPosixRequest::iLink |
|
27 |
|
28 // Cleanup support |
|
29 |
|
30 void CFileDescBase::Cleanup(TAny *aPtr) |
|
31 { |
|
32 ((CFileDescBase*)aPtr)->Close(); |
|
33 } |
|
34 |
|
35 void CFileDescBase::PushLC() |
|
36 { |
|
37 CleanupStack::PushL(TCleanupItem(Cleanup,this)); |
|
38 } |
|
39 |
|
40 // Private constructor |
|
41 |
|
42 inline TPosixRequestQueue::TPosixRequestQueue() |
|
43 : TSglQue<CPosixRequest>(_FOFF(CPosixRequest,iLink)) |
|
44 {} |
|
45 |
|
46 CFileDescBase::CFileDescBase() : iReadTimeout(-1) |
|
47 { |
|
48 } |
|
49 |
|
50 // A CFileDescBase factory function, for "named" file-like objects |
|
51 |
|
52 //CFileDescBase* CFileDescBase::Open(RFs& aSession, const char* name, int mode, int perms, TInt& err) |
|
53 //CFileDescBase* CFileDescBase::Open(RFs& aSession, const wchar_t* name, int mode, int perms, TInt& err) |
|
54 CFileDescBase* CFileDescBase::Open(RSessionBase& aSession, const wchar_t* name, int mode, int perms, TInt& err) |
|
55 { |
|
56 CFileDescBase* ret=0; |
|
57 |
|
58 if (wcscmp(name,L"CON:")==0) |
|
59 ret= new CTtyDesc; // NB. This won't be the default stdin/stdout/stderr console |
|
60 else |
|
61 if (wcscmp(name,L"NUL:")==0) |
|
62 ret= new CFileDescBase; |
|
63 else |
|
64 if (wcscmp(name,L"TMP:")==0) |
|
65 { |
|
66 RFs& rfs = static_cast<RFs&>(aSession); |
|
67 TParse path; |
|
68 err=GetFullPath(path,(const TText16*)WIDEP_tmpdir, rfs,NULL); |
|
69 if (err) |
|
70 return 0; |
|
71 CTempFileDesc* tmp= new CTempFileDesc; |
|
72 if (tmp) |
|
73 { |
|
74 err=tmp->Open(rfs,path.DriveAndPath()); |
|
75 if (err) |
|
76 { |
|
77 delete tmp; |
|
78 return 0; |
|
79 } |
|
80 } |
|
81 ret=tmp; |
|
82 } |
|
83 else if ((L'C' == name[0]) && (L'O' == name[1]) && (L'M' == name[2]) && (L':' == name[4]) && ((name[3] >= L'1') && (name[3] <= L'9')) || |
|
84 (L'I' == name[0]) && (L'R' == name[1]) && (L'C' == name[2]) && (L'O' == name[3]) && (L'M' == name[4]) && (L':' == name[6]) && ((name[5] >= L'1') && (name[5] <= L'9'))) |
|
85 { |
|
86 |
|
87 RCommServ& rcs = static_cast<RCommServ&>(aSession); |
|
88 if (!rcs.Handle()) |
|
89 { |
|
90 err=rcs.Connect(); //connect to the server |
|
91 if (err) |
|
92 return 0; |
|
93 } |
|
94 CSerialDesc * tmp = new CSerialDesc; |
|
95 if (tmp) |
|
96 { |
|
97 RCommServ& rcs = static_cast<RCommServ&>(aSession); |
|
98 CleanupStack::PushL(tmp); |
|
99 err = tmp->Open(rcs, name, mode, perms); |
|
100 CleanupStack::Pop(tmp); |
|
101 if (err) |
|
102 { |
|
103 delete tmp; |
|
104 return 0; |
|
105 } |
|
106 } |
|
107 ret = tmp; |
|
108 } |
|
109 else |
|
110 { |
|
111 TFullName fullName; |
|
112 RFs& rfs = static_cast<RFs&>(aSession); |
|
113 err=GetFullFile(fullName,(const TText16*)name,rfs); |
|
114 if (err) |
|
115 return 0; |
|
116 CFileDesc* f= new CFileDesc; |
|
117 if (f) |
|
118 { |
|
119 err=f->Open(rfs,fullName,mode,perms); |
|
120 if (err) |
|
121 { |
|
122 delete f; |
|
123 return 0; |
|
124 } |
|
125 } |
|
126 ret=f; |
|
127 } |
|
128 err=(ret==0)? KErrNoMemory:KErrNone; |
|
129 return ret; |
|
130 } |
|
131 |
|
132 // Useful default implementations for CFileDescBase virtual functions. |
|
133 |
|
134 TInt CFileDescBase::LSeek (int& offset, int) |
|
135 { |
|
136 // minimal implementation for devices which can't seek |
|
137 offset=0; |
|
138 return KErrNone; |
|
139 } |
|
140 |
|
141 void CFileDescBase::Read (TDes8& aBuf, TRequestStatus& aStatus) |
|
142 { |
|
143 // minimal implementation for /dev/null |
|
144 aBuf.Zero(); // set length to zero |
|
145 TRequestStatus* sp=&aStatus; |
|
146 User::RequestComplete(sp,KErrNone); |
|
147 } |
|
148 |
|
149 void CFileDescBase::ReadCancel() {} |
|
150 |
|
151 TInt CFileDescBase::ReadCompletion (TDes8& /*aBuf*/, TInt aStatus) |
|
152 { |
|
153 return aStatus; |
|
154 } |
|
155 |
|
156 |
|
157 TInt CFileDescBase::FStat (struct stat *st) |
|
158 { |
|
159 // minimal implementation: |
|
160 // I am a character device about which little is known |
|
161 st->st_mode = S_IFCHR; |
|
162 st->st_blksize=0; |
|
163 return KErrNone; |
|
164 } |
|
165 |
|
166 void CFileDescBase::Complete (TRequestStatus& aStatus, TInt aResult) |
|
167 { |
|
168 TRequestStatus* sp=&aStatus; |
|
169 User::RequestComplete(sp,aResult); |
|
170 } |
|
171 |
|
172 void CFileDescBase::Write (TDes8& /*aBuf*/, TRequestStatus& aStatus) |
|
173 { |
|
174 // minimal implementation for /dev/null |
|
175 // we will claim to have written all of the data |
|
176 Complete(aStatus,KErrNone); |
|
177 } |
|
178 |
|
179 void CFileDescBase::WriteCancel() {} |
|
180 |
|
181 TInt CFileDescBase::WriteCompletion (TDes8& /*aBuf*/, TInt aStatus) |
|
182 { |
|
183 return aStatus; |
|
184 } |
|
185 |
|
186 void CFileDescBase::Sync (TRequestStatus& aStatus) |
|
187 { |
|
188 // minimal implementation for /dev/null |
|
189 Complete(aStatus,KErrNone); |
|
190 } |
|
191 |
|
192 void CFileDescBase::SyncCancel() {} |
|
193 |
|
194 void CFileDescBase::Ioctl(int /*aCmd*/, void* /*aParam*/, TRequestStatus& aStatus) |
|
195 { |
|
196 // minimal implementation for /dev/null and other synchronous devices |
|
197 Complete(aStatus,KErrNone); |
|
198 } |
|
199 |
|
200 void CFileDescBase::IoctlCancel() |
|
201 { |
|
202 return; // suitable for all synchronous ioctls |
|
203 } |
|
204 |
|
205 TInt CFileDescBase::IoctlCompletion(int aCmd, void* aParam, TInt aStatus) |
|
206 { |
|
207 TInt ret=aStatus; |
|
208 if (ret!=KErrNone) |
|
209 return ret; |
|
210 int *param=REINTERPRET_CAST(int*,aParam); |
|
211 switch (aCmd) |
|
212 { |
|
213 case E32IONREAD: |
|
214 *param=0; // claim that no data is available |
|
215 break; |
|
216 case E32IOSELECT: |
|
217 *param=(*param)&(E32SELECT_READ|E32SELECT_WRITE); // but don't block |
|
218 break; |
|
219 default: |
|
220 ret=KErrNotSupported; |
|
221 break; |
|
222 } |
|
223 return ret; |
|
224 } |
|
225 |
|
226 // A CFileDescBase factory function, for socket objects |
|
227 |
|
228 CFileDescBase* CFileDescBase::Socket(RSocketServ& aSs, int family, int style, int protocol, TInt& err) |
|
229 { |
|
230 // connect to the Socket Server if necessary |
|
231 if (aSs.Handle()==0) |
|
232 { |
|
233 err=aSs.Connect(TUint(-1)); // allow arbitrary number of requests |
|
234 if (err) |
|
235 return 0; |
|
236 } |
|
237 CSocketDesc* s= new CSocketDesc; |
|
238 if (s==0) |
|
239 { |
|
240 err=KErrNoMemory; |
|
241 return 0; |
|
242 } |
|
243 err=s->Socket(aSs,family,style,protocol); |
|
244 if (err) |
|
245 { |
|
246 delete s; |
|
247 return 0; |
|
248 } |
|
249 return s; |
|
250 } |
|
251 |
|
252 // minimal implementation of sockets, useful for all non-socket descriptors |
|
253 |
|
254 void CFileDescBase::RecvFrom(TDes8& /*aDesc*/, TSockAddr& /*from*/, int /*flags*/, TRequestStatus& aStatus) |
|
255 { |
|
256 // minimal implementation |
|
257 Complete(aStatus,ENOTSOCK); |
|
258 } |
|
259 |
|
260 void CFileDescBase::RecvFromCancel () {} |
|
261 |
|
262 TInt CFileDescBase::RecvFromCompletion(TInt& /*aLength*/, TInt aStatus) |
|
263 { |
|
264 return aStatus; |
|
265 } |
|
266 |
|
267 void CFileDescBase::SendTo(TDes8& /*aDesc*/, TSockAddr& /*to*/, int /*flags*/, TRequestStatus& aStatus) |
|
268 { |
|
269 // minimal implementation |
|
270 Complete(aStatus,ENOTSOCK); |
|
271 } |
|
272 |
|
273 void CFileDescBase::SendToCancel () {} |
|
274 |
|
275 TInt CFileDescBase::SendToCompletion(TDes8& /*aDesc*/, TInt aStatus) |
|
276 { |
|
277 return aStatus; |
|
278 } |
|
279 |
|
280 void CFileDescBase::Shutdown(TUint /*aHow*/,TRequestStatus& aStatus) |
|
281 { |
|
282 // minimal implementation |
|
283 Complete(aStatus,ENOTSOCK); |
|
284 } |
|
285 |
|
286 void CFileDescBase::ShutdownCancel () {} |
|
287 |
|
288 TInt CFileDescBase::Bind(TSockAddr& /*anAddr*/) |
|
289 { |
|
290 return ENOTSOCK; |
|
291 } |
|
292 |
|
293 TInt CFileDescBase::Listen(TUint /*qSize*/) |
|
294 { |
|
295 return ENOTSOCK; |
|
296 } |
|
297 |
|
298 void CFileDescBase::Accept(CSocketDesc*& /*aNewSocket*/, TRequestStatus& aStatus, RSocketServ& /*aSs*/) |
|
299 { |
|
300 // minimal implementation |
|
301 Complete(aStatus,ENOTSOCK); |
|
302 } |
|
303 |
|
304 void CFileDescBase::AcceptCancel () {} |
|
305 |
|
306 void CFileDescBase::Connect(TSockAddr& /*anAddr*/,TRequestStatus& aStatus) |
|
307 { |
|
308 // minimal implementation |
|
309 Complete(aStatus,ENOTSOCK); |
|
310 } |
|
311 |
|
312 void CFileDescBase::ConnectCancel () {} |
|
313 |
|
314 TInt CFileDescBase::SockName(int /*anEnd*/, TSockAddr& /*anAddr*/) |
|
315 { |
|
316 return ENOTSOCK; |
|
317 } |
|
318 |
|
319 TInt CFileDescBase::GetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDes8& /*anOption*/) |
|
320 { |
|
321 return ENOTSOCK; |
|
322 } |
|
323 |
|
324 TInt CFileDescBase::SetSockOpt(TUint /*anOptionName*/,TUint /*anOptionLevel*/,TDesC8& /*anOption*/) |
|
325 { |
|
326 return ENOTSOCK; |
|
327 } |
|
328 |
|
329 // Queue handling |
|
330 |
|
331 void CFileDescBase::AddLast(CPosixRequest& aRequest, IOQueues aQueue) |
|
332 { |
|
333 TPosixRequestQueue& queue = iQueues[aQueue]; |
|
334 queue.AddLast(aRequest); |
|
335 if (queue.IsFirst(&aRequest)) |
|
336 aRequest.StartAsynch(); // queue was empty, so start straight away |
|
337 } |
|
338 |
|
339 void CFileDescBase::Remove(CPosixRequest& aRequest, IOQueues aQueue) |
|
340 { |
|
341 TPosixRequestQueue& queue = iQueues[aQueue]; |
|
342 TBool wasFirst = queue.IsFirst(&aRequest); |
|
343 queue.Remove(aRequest); |
|
344 if (wasFirst) |
|
345 { |
|
346 if (!queue.IsEmpty()) |
|
347 queue.First()->StartAsynch(); // start the next outstanding request |
|
348 } |
|
349 } |
|
350 |
|
351 |
|
352 // Generic (non-virtual) handling for Close |
|
353 |
|
354 TInt CFileDescBase::Close() |
|
355 { |
|
356 TInt err=KErrNone; |
|
357 if (--iDupCount < 0) |
|
358 { |
|
359 err=FinalClose(); |
|
360 delete this; |
|
361 } |
|
362 return err; |
|
363 } |
|
364 |
|
365 TInt CFileDescBase::FinalClose() |
|
366 { |
|
367 return KErrNone; |
|
368 } |
|
369 |
|
370 |
|
371 // Simple implementation of File handling |
|
372 |
|
373 static int MapMode(int aMode, TUint& fMode) |
|
374 { |
|
375 // EPOC32 doesn't support Write-Only |
|
376 |
|
377 if (aMode & (O_WRONLY|O_RDWR)) |
|
378 { |
|
379 fMode = EFileWrite; |
|
380 fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareAny; |
|
381 } |
|
382 else |
|
383 { |
|
384 fMode = EFileRead; |
|
385 fMode |= (aMode & O_EXCL) ? EFileShareExclusive : EFileShareReadersOnly; |
|
386 } |
|
387 |
|
388 fMode |= (aMode & O_TEXT) ? EFileStreamText : EFileStream; |
|
389 |
|
390 return aMode & (O_CREAT|O_TRUNC|O_APPEND|O_EXCL); |
|
391 } |
|
392 |
|
393 CFileDesc::CFileDesc() |
|
394 :CFileDescBase(), iSize(EBufferSize), iExt(-1) |
|
395 {} |
|
396 |
|
397 CFileDesc::~CFileDesc() |
|
398 { |
|
399 iFile.Close(); |
|
400 delete [] iBuffer; |
|
401 } |
|
402 |
|
403 TInt CFileDesc::FinalClose() |
|
404 { |
|
405 return DoSync(); |
|
406 } |
|
407 |
|
408 TInt CFileDesc::Open(RFs& aSession, const TDesC& aName, int mode, int /*perms*/) |
|
409 { |
|
410 TInt err; |
|
411 TUint fMode; |
|
412 |
|
413 iDrive=(TInt16)TDriveUnit(aName); |
|
414 |
|
415 // Create = make new file, can return KErrAlreadyExists |
|
416 // Open = open an existing file, can return KErrPathNotFound or KErrNotFound |
|
417 // Replace = open a new file, zapping the existing one if necessary |
|
418 |
|
419 int mapped=MapMode(mode, fMode); |
|
420 switch (mapped) |
|
421 { |
|
422 case O_CREAT|O_EXCL: |
|
423 err = iFile.Create(aSession, aName, fMode); |
|
424 break; |
|
425 case O_CREAT|O_TRUNC: |
|
426 err = iFile.Replace(aSession, aName, fMode); |
|
427 break; |
|
428 case O_TRUNC: |
|
429 err = iFile.Open(aSession, aName, fMode); |
|
430 if (err == KErrPathNotFound) |
|
431 { |
|
432 // missing directories etc, so fail directly |
|
433 } |
|
434 else |
|
435 { |
|
436 iFile.Close(); |
|
437 err = iFile.Replace(aSession, aName, fMode); |
|
438 } |
|
439 break; |
|
440 |
|
441 // Everything else is assumed to mean open existing file, |
|
442 // If the file isn't there, O_CREAT implies that we should make it |
|
443 default: |
|
444 err = iFile.Open(aSession, aName, fMode); |
|
445 if (err == KErrNotFound && (mapped & O_CREAT)) |
|
446 err = iFile.Create(aSession, aName, fMode); |
|
447 if (err == KErrNone && (mapped & O_APPEND)) |
|
448 { |
|
449 iPos = Ext(); |
|
450 if (iPos < 0) |
|
451 err = iPos; |
|
452 } |
|
453 break; |
|
454 } |
|
455 if ((mode & O_BUFFERED) == 0) |
|
456 iSize = 0; |
|
457 return err; |
|
458 } |
|
459 |
|
460 TInt CFileDesc::LSeek (int& offset, int whence) |
|
461 { |
|
462 |
|
463 TInt pos=offset; |
|
464 TInt ext=Ext(); |
|
465 if (ext < 0) |
|
466 return ext; |
|
467 |
|
468 switch (whence) |
|
469 { |
|
470 case SEEK_SET: |
|
471 break; |
|
472 case SEEK_CUR: |
|
473 pos += Pos(); |
|
474 break; |
|
475 case SEEK_END: |
|
476 pos += ext; |
|
477 break; |
|
478 default: |
|
479 return KErrArgument; |
|
480 } |
|
481 TInt ret = KErrNone; |
|
482 if (pos < 0) |
|
483 { |
|
484 pos = 0; |
|
485 ret = KErrEof; |
|
486 } |
|
487 else if (pos > ext) |
|
488 { |
|
489 pos = ext; |
|
490 ret = KErrEof; |
|
491 } |
|
492 |
|
493 switch (iState) |
|
494 { |
|
495 case EAlloc: |
|
496 iPos = pos; |
|
497 break; |
|
498 case EReading: |
|
499 { |
|
500 TInt lag = iPos - pos; |
|
501 if (lag >= 0 && lag <= (iEnd - iBuffer)) |
|
502 iPtr = iEnd - lag; |
|
503 else |
|
504 { |
|
505 iPtr = iEnd; |
|
506 iPos = pos; |
|
507 } |
|
508 } |
|
509 break; |
|
510 case EWriting: |
|
511 if (pos != Pos()) |
|
512 { |
|
513 ret = Flush(); |
|
514 if (ret == KErrNone) |
|
515 iPos = pos; |
|
516 } |
|
517 break; |
|
518 } |
|
519 offset = pos; |
|
520 return ret; |
|
521 } |
|
522 |
|
523 void CFileDesc::MapStat(struct stat& st, const TTime& aModTime, TUint& aAttr) |
|
524 { |
|
525 st.st_mode = (aAttr&KEntryAttDir) ? S_IFDIR:S_IFREG; |
|
526 if ((aAttr&KEntryAttReadOnly)==0) |
|
527 st.st_mode |= S_IWUSR; |
|
528 st.st_nlink = 1; |
|
529 st.st_mtime = as_time_t(aModTime); |
|
530 st.st_blksize=512; |
|
531 } |
|
532 |
|
533 TInt CFileDesc::FStat (struct stat* st) |
|
534 { |
|
535 TInt err; |
|
536 TUint att; |
|
537 TTime modtime; |
|
538 |
|
539 err = iFile.Att(att); |
|
540 if (!err) |
|
541 { |
|
542 err = iFile.Modified(modtime); |
|
543 if (!err) |
|
544 { |
|
545 err=Ext(); |
|
546 if (err >= 0) |
|
547 { |
|
548 st->st_size = err; |
|
549 st->st_dev = st->st_rdev = iDrive; |
|
550 MapStat(*st, modtime, att); |
|
551 return 0; |
|
552 } |
|
553 } |
|
554 } |
|
555 return err; |
|
556 } |
|
557 |
|
558 TInt CFileDesc::Alloc() |
|
559 { |
|
560 if (iSize) |
|
561 { |
|
562 iBuffer = new TUint8[iSize]; |
|
563 if (iBuffer == 0) |
|
564 return KErrNoMemory; |
|
565 } |
|
566 return KErrNone; |
|
567 } |
|
568 |
|
569 TInt CFileDesc::FileRead(TUint8* aPtr,TInt aLength) |
|
570 { |
|
571 TPtr8 ptr(aPtr,aLength); |
|
572 TInt r=iFile.Read(iPos,ptr); |
|
573 if (r == KErrNone) |
|
574 { |
|
575 r = ptr.Length(); |
|
576 iPos += r; |
|
577 if (r < aLength) |
|
578 iExt = iPos; |
|
579 } |
|
580 return r; |
|
581 } |
|
582 |
|
583 TInt CFileDesc::FileWrite(TUint8* aPtr,TInt aLength) |
|
584 { |
|
585 TPtrC8 ptr(aPtr,aLength); |
|
586 TInt r = iFile.Write(iPos,ptr); |
|
587 if (r == KErrNone) |
|
588 { |
|
589 iPos += aLength; |
|
590 if (iPos > iExt && iExt >= 0) |
|
591 iExt = iPos; |
|
592 } |
|
593 return r; |
|
594 } |
|
595 |
|
596 TInt CFileDesc::Flush() |
|
597 { |
|
598 if (iPtr > iBuffer) |
|
599 { |
|
600 TInt r = FileWrite(iBuffer, iPtr-iBuffer); |
|
601 if (r < 0) |
|
602 return r; |
|
603 iPtr = iBuffer; |
|
604 } |
|
605 return KErrNone; |
|
606 } |
|
607 |
|
608 TInt CFileDesc::DoRead (TDes8& aDesc) |
|
609 { |
|
610 if (iState != EReading) |
|
611 { |
|
612 TInt ret = (iState == EAlloc) ? Alloc() : Flush(); |
|
613 if (ret != KErrNone) |
|
614 return ret; |
|
615 iState = EReading; |
|
616 iPtr = iEnd = iBuffer; |
|
617 } |
|
618 |
|
619 TUint8* p = (TUint8*) aDesc.Ptr(); |
|
620 TInt max = aDesc.MaxLength(); |
|
621 TInt avail = iEnd - iPtr; |
|
622 TInt len = Min(max, avail); |
|
623 if (len > 0) |
|
624 { |
|
625 p = Mem::Copy(p, iPtr, len); |
|
626 iPtr += len; |
|
627 max -= len; |
|
628 } |
|
629 if (max >= iSize) |
|
630 { |
|
631 TInt ret = FileRead(p, max); |
|
632 if (ret < 0) |
|
633 return ret; |
|
634 p += ret; |
|
635 } |
|
636 else if (max > 0) |
|
637 { |
|
638 TInt ret = FileRead(iBuffer, Min(max + EReadAhead, iSize)); |
|
639 if (ret < 0) |
|
640 return ret; |
|
641 len = Min(max, ret); |
|
642 p = Mem::Copy(p, iBuffer, len); |
|
643 iPtr = iBuffer + len; |
|
644 iEnd = iBuffer + ret; |
|
645 } |
|
646 aDesc.SetLength(p-aDesc.Ptr()); |
|
647 return KErrNone; |
|
648 } |
|
649 |
|
650 void CFileDesc::Read (TDes8& aDesc, TRequestStatus& aStatus) |
|
651 { |
|
652 Complete(aStatus,DoRead(aDesc)); |
|
653 } |
|
654 |
|
655 TInt CFileDesc::DoWrite (TDes8& aDesc) |
|
656 { |
|
657 if (iState != EWriting) |
|
658 { |
|
659 if (iState == EAlloc) |
|
660 { |
|
661 TInt ret = Alloc(); |
|
662 if (ret != KErrNone) |
|
663 return ret; |
|
664 } |
|
665 else |
|
666 iPos -= iEnd - iPtr; |
|
667 |
|
668 iState = EWriting; |
|
669 iPtr = iBuffer; |
|
670 iEnd = iBuffer + iSize; |
|
671 } |
|
672 |
|
673 TUint8* p = (TUint8*) aDesc.Ptr(); |
|
674 TInt max = aDesc.Length(); |
|
675 TInt avail = iEnd - iPtr; |
|
676 TInt len = Min(max, avail); |
|
677 if (len > 0) |
|
678 { |
|
679 iPtr = Mem::Copy(iPtr, p, len); |
|
680 p += len; |
|
681 max -= len; |
|
682 } |
|
683 if (max == 0) |
|
684 return KErrNone; |
|
685 TInt r=Flush(); |
|
686 if (r < 0) |
|
687 return r; |
|
688 if (max >= iSize) |
|
689 return FileWrite(p, max); |
|
690 iPtr = Mem::Copy(iPtr, p, max); |
|
691 return KErrNone; |
|
692 } |
|
693 |
|
694 void CFileDesc::Write(TDes8& aDesc, TRequestStatus& aStatus) |
|
695 { |
|
696 Complete(aStatus,DoWrite(aDesc)); |
|
697 } |
|
698 |
|
699 TInt CFileDesc::DoSync() |
|
700 { |
|
701 if (iState == EWriting) |
|
702 { |
|
703 TInt ret = Flush(); |
|
704 if (ret < 0) |
|
705 return ret; |
|
706 } |
|
707 return iFile.Flush(); |
|
708 } |
|
709 |
|
710 void CFileDesc::Sync(TRequestStatus& aStatus) |
|
711 { |
|
712 Complete(aStatus,DoSync()); |
|
713 } |
|
714 |
|
715 TInt CFileDesc::Pos() |
|
716 { |
|
717 TInt pos = iPos; |
|
718 if (iState == EReading) |
|
719 pos -= (iEnd - iPtr); |
|
720 else if (iState == EWriting) |
|
721 pos += (iPtr - iBuffer); |
|
722 return pos; |
|
723 } |
|
724 |
|
725 TInt CFileDesc::Ext() |
|
726 { |
|
727 if (iExt < 0) |
|
728 { |
|
729 TInt r = iFile.Size(iExt); |
|
730 if (r < 0) |
|
731 return r; |
|
732 } |
|
733 return Max(iExt, Pos()); |
|
734 } |
|
735 |
|
736 TInt CFileDesc::IoctlCompletion(int aCmd, void* aParam, TInt aStatus) |
|
737 { |
|
738 TInt ret=aStatus; |
|
739 if (ret!=KErrNone) |
|
740 return ret; |
|
741 // some useful sums about the current state of the file |
|
742 TInt curoff = Pos(); |
|
743 TInt size = Ext(); |
|
744 if (size < 0) |
|
745 ret = size; |
|
746 int *param=REINTERPRET_CAST(int*,aParam); |
|
747 switch (aCmd) |
|
748 { |
|
749 case E32IONREAD: |
|
750 if (ret==KErrNone) |
|
751 *param=(size-curoff); |
|
752 break; |
|
753 case E32IOSELECT: |
|
754 { |
|
755 int mask=E32SELECT_WRITE; |
|
756 if ((size-curoff)>0) |
|
757 mask |= E32SELECT_READ; |
|
758 *param=(*param)&mask; // but don't block |
|
759 } |
|
760 break; |
|
761 default: |
|
762 ret=KErrNotSupported; |
|
763 break; |
|
764 } |
|
765 return ret; |
|
766 } |
|
767 |
|
768 // Extra support for temporary files |
|
769 |
|
770 TInt CTempFileDesc::Open(RFs& aSession, const TDesC& aPath) |
|
771 { |
|
772 iSession=aSession; |
|
773 iDrive=(TInt16)TDriveUnit(aPath); |
|
774 TInt err=iFile.Temp(aSession, aPath, iName, EFileShareAny); |
|
775 return err; |
|
776 } |
|
777 |
|
778 TInt CTempFileDesc::FinalClose() |
|
779 { |
|
780 iFile.Close(); |
|
781 TInt err=iSession.Delete(iName); |
|
782 return err; |
|
783 } |