255 #ifdef _DEBUG |
264 #ifdef _DEBUG |
256 |
265 |
257 TBool simulatedWriteFailure = EFalse; //-- if true it means that the write failure has been simulated |
266 TBool simulatedWriteFailure = EFalse; //-- if true it means that the write failure has been simulated |
258 |
267 |
259 //-- debug interface to simulate write failure |
268 //-- debug interface to simulate write failure |
260 if(iMount->IsWriteFail()) |
269 if(iMount->IsWriteFail()) |
261 { |
270 { |
262 if(iMount->WriteFailCount() != 0) |
271 if(iMount->WriteFailCount() != 0) |
263 { |
272 { |
264 iMount->DecWriteFailCount(); |
273 iMount->DecWriteFailCount(); |
265 } |
274 } |
266 else |
275 else |
267 {//-- simulate write failure |
276 {//-- simulate write failure |
268 if(iMount->WriteFailError()==-99) |
277 if(iMount->WriteFailError()==-99) |
269 UserSvr::ResetMachine(EStartupWarmReset); |
278 UserSvr::ResetMachine(EStartupWarmReset); |
270 else |
279 else |
271 { |
280 { |
272 //-- invalidate caches, because actual write to the drive isn't going to happen |
281 //-- invalidate caches, because actual write to the drive isn't going to happen |
273 if(iMount->RawDisk().DirCacheInterface()) |
282 if(iMount->RawDisk().DirCacheInterface()) |
274 iMount->RawDisk().DirCacheInterface()->InvalidateCache(); |
283 iMount->RawDisk().DirCacheInterface()->InvalidateCache(); |
275 |
284 |
276 iMount->SetWriteFail(EFalse); |
285 iMount->SetWriteFail(EFalse); |
277 |
286 |
278 TRAP_IGNORE(iMount->RawDisk().InvalidateUidCache()); //-- invalidate whole UID data cache |
287 TRAP_IGNORE(iMount->RawDisk().InvalidateUidCache()); //-- invalidate whole UID data cache |
279 TRAP_IGNORE(iMount->FAT().InvalidateCacheL()); //-- invalidate whole FAT cache |
288 TRAP_IGNORE(iMount->FAT().InvalidateCacheL()); //-- invalidate whole FAT cache |
280 |
289 |
281 iMount->InvalidateLeafDirCache(); |
290 iMount->InvalidateLeafDirCache(); |
282 |
291 |
283 nRes = iMount->WriteFailError(); |
292 nRes = iMount->WriteFailError(); |
284 simulatedWriteFailure = ETrue; //-- won't perform actual write later |
293 simulatedWriteFailure = ETrue; //-- won't perform actual write later |
285 __PRINT4(_L("TFatDriveInterface::WriteCritical() Simulating write failure. drv:%d, aPos=%LU len=%d Code=%d"), iMount->DriveNumber(), aPos,aSrc.Length(),nRes); |
294 __PRINT4(_L("TFatDriveInterface::WriteCritical() Simulating write failure. drv:%d, aPos=%LU len=%d Code=%d"), iMount->DriveNumber(), aPos,aSrc.Length(),nRes); |
286 |
295 |
287 } |
296 } |
288 } |
297 } |
289 }//if(iMount->IsWriteFail()) |
298 }//if(iMount->IsWriteFail()) |
290 |
299 |
291 if(!simulatedWriteFailure) |
300 if(!simulatedWriteFailure) |
292 #endif // _DEBUG |
301 #endif // _DEBUG |
293 { |
302 { |
294 //-- try to write data until success or user gives up |
303 //-- try to write data until success or user gives up |
295 for(;;) |
304 for(;;) |
296 { |
305 { |
297 for(TInt i=0; i<KMaxCriticalRetries; i++) |
306 for(TInt i=0; i<KMaxCriticalRetries; i++) |
298 { |
307 { |
299 iMount->OpenMountForWrite(); //-- make a callback to CFatMountCB to perform some actions on 1st write. |
308 iMount->OpenMountForWrite(); //-- make a callback to CFatMountCB to perform some actions on 1st write. |
300 nRes=iProxyDrive.Write(aPos,aSrc); |
309 nRes=iProxyDrive.Write(aPos,aSrc); |
301 if (nRes==KErrNone) |
310 if (nRes==KErrNone) |
302 return nRes; |
311 return nRes; |
303 } |
312 } |
304 |
313 |
305 //-- write error occured |
314 //-- write error occured |
306 __PRINT4(_L("TFatDriveInterface::WriteCritical() failure! drv:%d, aPos=%LU len=%d retval=%d"), iMount->DriveNumber(), aPos,aSrc.Length(),nRes); |
315 __PRINT4(_L("TFatDriveInterface::WriteCritical() failure! drv:%d, aPos=%LU len=%d retval=%d"), iMount->DriveNumber(), aPos,aSrc.Length(),nRes); |
307 |
316 |
308 nRes=HandleCriticalError(nRes); |
317 nRes=HandleCriticalError(nRes); |
309 if (nRes!=ERetry) |
318 if (nRes!=ERetry) |
310 break; |
319 break; |
311 |
320 |
312 }//for(;;) |
321 }//for(;;) |
313 |
322 |
314 }// if(!simulatedWriteFailure) |
323 }// if(!simulatedWriteFailure) |
315 |
324 |
316 return nRes; |
325 return nRes; |
317 } |
326 } |
341 @return KErrAbort - User aborted notifier |
350 @return KErrAbort - User aborted notifier |
342 @return KErrAccessDenied - media is read only |
351 @return KErrAccessDenied - media is read only |
343 @return KErrCorrupt - cf-card is corrupt |
352 @return KErrCorrupt - cf-card is corrupt |
344 */ |
353 */ |
345 TInt TFatDriveInterface::HandleCriticalError(TInt aResult) const |
354 TInt TFatDriveInterface::HandleCriticalError(TInt aResult) const |
346 { |
355 { |
347 __PRINT2(_L("TFatDriveInterface::HandleCriticalError drv:%d, code:%d"), iMount->DriveNumber(),aResult); |
356 __PRINT2(_L("TFatDriveInterface::HandleCriticalError drv:%d, code:%d"), iMount->DriveNumber(),aResult); |
348 |
357 |
349 TLocaleMessage line1; |
358 TLocaleMessage line1; |
350 TLocaleMessage line2; |
359 TLocaleMessage line2; |
351 |
360 |
352 TInt r=KErrAbort; |
361 TInt r=KErrAbort; |
353 |
362 |
354 if (aResult==KErrLocked) |
363 if (aResult==KErrLocked) |
355 { |
364 { |
356 r=KErrLocked; |
365 r=KErrLocked; |
357 goto End; |
366 goto End; |
358 } |
367 } |
359 |
368 |
360 if (aResult==KErrAccessDenied) |
369 if (aResult==KErrAccessDenied) |
361 { |
370 { |
362 r=KErrAccessDenied; |
371 r=KErrAccessDenied; |
363 goto End; |
372 goto End; |
364 } |
373 } |
365 |
374 |
366 if (aResult==KErrArgument || aResult==KErrBadDescriptor) |
375 if (aResult==KErrArgument || aResult==KErrBadDescriptor) |
367 { |
376 { |
368 r=KErrCorrupt; |
377 r=KErrCorrupt; |
369 goto End; |
378 goto End; |
370 } |
379 } |
371 |
380 |
372 if (iMount->Drive().IsChanged()) |
381 if (iMount->Drive().IsChanged()) |
373 {//-- check if the media we accessing is the same as it used to be |
382 {//-- check if the media we accessing is the same as it used to be |
374 if(iMount->CheckVolumeTheSame()) |
383 if(iMount->CheckVolumeTheSame()) |
375 {//-- the media is the same |
384 {//-- the media is the same |
376 if(!IsDriveWriteProtected()) |
385 if(!IsDriveWriteProtected()) |
377 { |
386 { |
378 iMount->Drive().SetChanged(EFalse); |
387 iMount->Drive().SetChanged(EFalse); |
379 r=ERetry; |
388 r=ERetry; |
380 goto End; |
389 goto End; |
381 } |
390 } |
382 } |
391 } |
383 } |
392 } |
384 |
393 |
385 if (aResult==KErrAbort && !iMount->Drive().IsChanged()) |
394 if (aResult==KErrAbort && !iMount->Drive().IsChanged()) |
386 { |
395 { |
387 r=ERetry; |
396 r=ERetry; |
388 goto End; |
397 goto End; |
389 } |
398 } |
390 |
399 |
391 if (aResult==KErrBadPower) |
400 if (aResult==KErrBadPower) |
392 { |
401 { |
393 line1=EFileServer_LowPowerLine1; |
402 line1=EFileServer_LowPowerLine1; |
394 line2=EFileServer_LowPowerLine2; |
403 line2=EFileServer_LowPowerLine2; |
395 } |
404 } |
396 else if (iMount->Drive().IsChanged()) |
405 else if (iMount->Drive().IsChanged()) |
397 { |
406 { |
398 line1=EFileServer_PutTheCardBackLine1; |
407 line1=EFileServer_PutTheCardBackLine1; |
399 line2=EFileServer_PutTheCardBackLine2; |
408 line2=EFileServer_PutTheCardBackLine2; |
400 } |
409 } |
401 else |
410 else |
402 { |
411 { |
403 line1=EFileServer_DiskErrorLine1; |
412 line1=EFileServer_DiskErrorLine1; |
404 line2=EFileServer_DiskErrorLine2; |
413 line2=EFileServer_DiskErrorLine2; |
405 } |
414 } |
406 |
415 |
407 if (NotifyUser()) |
416 if (NotifyUser()) |
408 { |
417 { |
409 FOREVER |
418 FOREVER |
410 { |
419 { |
411 TInt buttonVal; |
420 TInt buttonVal; |
412 TInt ret=iMount->Notifier()->Notify(TLocaleMessageText(line1), |
421 TInt ret=iMount->Notifier()->Notify(TLocaleMessageText(line1), |
413 TLocaleMessageText(line2), |
422 TLocaleMessageText(line2), |
414 TLocaleMessageText(EFileServer_Button1), |
423 TLocaleMessageText(EFileServer_Button1), |
415 TLocaleMessageText(EFileServer_Button2), |
424 TLocaleMessageText(EFileServer_Button2), |
416 buttonVal); |
425 buttonVal); |
417 if (ret!=KErrNone) |
426 if (ret!=KErrNone) |
418 break; |
427 break; |
419 if (buttonVal!=1) |
428 if (buttonVal!=1) |
420 break; // Abort |
429 break; // Abort |
421 |
430 |
422 if (iMount->Drive().IsChanged()) |
431 if (iMount->Drive().IsChanged()) |
423 { |
432 { |
424 // |
433 // |
425 // Without this code, retry will indiscriminately write over whatever disk happens to be present. |
434 // Without this code, retry will indiscriminately write over whatever disk happens to be present. |
426 // However if the write error is to the bootsector remounting will always fail because the boot |
435 // However if the write error is to the bootsector remounting will always fail because the boot |
427 // sector will have changed and hence the disk is useless. |
436 // sector will have changed and hence the disk is useless. |
428 // |
437 // |
455 @return KErrCorrupt - media is corrupt |
464 @return KErrCorrupt - media is corrupt |
456 @return KErrBadPower - low power failure |
465 @return KErrBadPower - low power failure |
457 @return KErrNotReady - non-critical error |
466 @return KErrNotReady - non-critical error |
458 */ |
467 */ |
459 TInt TFatDriveInterface::HandleRecoverableError(TInt aResult) const |
468 TInt TFatDriveInterface::HandleRecoverableError(TInt aResult) const |
460 { |
469 { |
461 __PRINT2(_L("TFatDriveInterface::HandleRecoverableError drv:%d, code:%d"), iMount->DriveNumber(),aResult); |
470 __PRINT2(_L("TFatDriveInterface::HandleRecoverableError drv:%d, code:%d"), iMount->DriveNumber(),aResult); |
462 |
471 |
463 if (aResult==KErrAccessDenied) |
472 if (aResult==KErrAccessDenied) |
464 return(KErrAccessDenied); |
473 return(KErrAccessDenied); |
465 if (aResult == KErrLocked) |
474 if (aResult == KErrLocked) |
466 return KErrLocked; |
475 return KErrLocked; |
467 if (aResult==KErrArgument || aResult==KErrBadDescriptor) |
476 if (aResult==KErrArgument || aResult==KErrBadDescriptor) |
468 return(KErrCorrupt); |
477 return(KErrCorrupt); |
469 if (aResult==KErrBadPower) |
478 if (aResult==KErrBadPower) |
470 return(KErrBadPower); |
479 return(KErrBadPower); |
471 if (aResult==KErrDied) // client thread died |
480 if (aResult==KErrDied) // client thread died |
472 return(KErrDied); |
481 return(KErrDied); |
473 if (iMount->Drive().IsChanged()) |
482 if (iMount->Drive().IsChanged()) |
474 { |
483 { |
475 |
484 |
476 if(! iMount->CheckVolumeTheSame()) |
485 if(! iMount->CheckVolumeTheSame()) |
477 {//-- the media is different now. |
486 {//-- the media is different now. |
478 return KErrNotReady; |
487 return KErrNotReady; |
479 } |
488 } |
480 else if(!IsRecoverableRemount()) |
489 else if(!IsRecoverableRemount()) |
481 { |
490 { |
482 return KErrAccessDenied; |
491 return KErrAccessDenied; |
483 } |
492 } |
484 } |
493 } |
485 return(ERetry); |
494 return(ERetry); |
486 } |
495 } |
487 |
496 |
488 /** @return true if the mount can be remounted for a recoverable error */ |
497 /** @return true if the mount can be remounted for a recoverable error */ |
489 TBool TFatDriveInterface::IsRecoverableRemount() const |
498 TBool TFatDriveInterface::IsRecoverableRemount() const |
490 { |
499 { |
491 if(IsDriveWriteProtected()&&(iMount->Drive().IsWriteableResource()||iMount->Drive().IsCurrentWriteFunction())) |
500 if(IsDriveWriteProtected()&&(iMount->Drive().IsWriteableResource()||iMount->Drive().IsCurrentWriteFunction())) |
492 return(EFalse); |
501 return(EFalse); |
493 return(ETrue); |
502 return(ETrue); |
494 } |
503 } |
495 |
504 |
496 /** return true if the media is write protected */ |
505 /** return true if the media is write protected */ |
497 TBool TFatDriveInterface::IsDriveWriteProtected() const |
506 TBool TFatDriveInterface::IsDriveWriteProtected() const |
498 { |
507 { |
499 TLocalDriveCapsV2Buf localDriveCaps; |
508 TLocalDriveCapsV2Buf localDriveCaps; |
500 TInt r=iProxyDrive.Caps(localDriveCaps); |
509 TInt r=iProxyDrive.Caps(localDriveCaps); |
501 |
510 |
502 if(r!=KErrNone) |
511 if(r!=KErrNone) |
503 return(EFalse); |
512 return(EFalse); |
504 |
513 |
505 return((localDriveCaps().iMediaAtt&KMediaAttWriteProtected)!=0); |
514 return((localDriveCaps().iMediaAtt&KMediaAttWriteProtected)!=0); |
506 } |
515 } |
507 |
516 |
508 |
517 |
509 |
518 |
510 //--------------------------------------------------------------------------------------------------------------------------------------- |
519 //--------------------------------------------------------------------------------------------------------------------------------------- |
511 |
520 |