/*
* Copyright (c) 2008 - 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Java platform 2.0 javaappconverter process
*
*/
#include <e32base.h>
#include <apgcli.h>
#include <pathinfo.h>
#include <driveinfo.h>
#include "silentmidletconvert.h"
#include "javauids.h"
#include "javacommonutils.h"
#include "logger.h"
#include "javaprocessconstants.h"
#include "javasymbianoslayer.h"
using namespace java::util;
_LIT(KJarFileNameSuffix, ".jar");
_LIT(KJadFileNameSuffix, ".jad");
_LIT(KFLJarFileNameSuffix, ".dm");
_LIT(KSDJarFileNameSuffix, ".dcf");
_LIT(KSMCBackSplash, "\\");
// The directory where the java applications to be converted are searched from
_LIT(KMidletSuiteInstallBasePath, ":\\Private\\102033E6\\MIDlets\\");
/**
* To create new instance of this class.
*
* @param aFs - A reference to the file server.
* @return Reference to the object of this class.
* @exception If construction fails.
*
*/
CSilentMIDletConvert* CSilentMIDletConvert::NewLC(RFs& aFs)
{
CSilentMIDletConvert* self = new(ELeave) CSilentMIDletConvert(aFs);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
/**
* To do 1st phase construction for this object.
*
* Adds this active object to the scheduler.
*
* @param aFs - A reference to the file server.
*/
CSilentMIDletConvert::CSilentMIDletConvert(RFs& aFs) :
CActive(EPriorityStandard), iFs(aFs), iNumberOfAppsToInstall(0),
iDefaultTargetInstallationDrive(-1)
{
CActiveScheduler::Add(this);
}
/**
* To do 2nd phase construction for this object.
*
* @exception If the method is not able to allocate necessary buffers.
*/
void CSilentMIDletConvert::ConstructL()
{
JELOG2(EJavaConverters);
iConvertServer = new(ELeave) ConvertServer();
}
/**
* Deletes this object.
* All allocated resources are released.
*/
CSilentMIDletConvert::~CSilentMIDletConvert()
{
JELOG2(EJavaConverters);
Cancel();
iInstallFiles.ResetAndDestroy();
iInstallFiles.Close();
iDirs.ResetAndDestroy();
iDirs.Close();
delete iConvertServer;
iConvertServer = NULL;
}
/**
* To start silent installation.
*/
void CSilentMIDletConvert::Start()
{
JELOG2(EJavaConverters);
iState = EFindOutDeviceDrives;
CompleteRequest();
}
/**
* To stop whole preinstaller.
* Stops the active scheduler.
*/
void CSilentMIDletConvert::Exit()
{
Deque();
CActiveScheduler::Stop();
}
/**
* To complete the request for this object.
*
* @Postconditions The following conditions are true immediately after
* returning from this method.
* - iStatus == KErrNone
* - IsActive() == ETrue
*/
void CSilentMIDletConvert::CompleteRequest()
{
JELOG2(EJavaConverters);
TRequestStatus *status = &iStatus;
User::RequestComplete(status, KErrNone);
if (!IsActive())
{
SetActive();
}
}
/**
* To run this active object.
*
* The state logic is:
*
* EFindOutDeviceDrives: find out all non-remote drives in the device
* - mark externally mountable drives (removable drives)
* - mark read only drives (ROM)
*
* EFindOutDrivesToBeScannedNow: make list of drives to be scanned
* - start with all mounted drives
*
* EAppsInInstalledDirectories: go through all directories in iDirs one by one
* and find all java applications in the subdirectories of the directory
* - if only .jar/.dcf/.dm file is found it is added to iInstallFiles
* - if .jad file is found, it is added to iInstallFiles
*
* ECheckWhichAppsShouldBeConverted: for each java application check from
* AppArc whether it should be converted
* - if the application has been installed, convert it
*
* EExecuteConvertServer: give list of install files to preinstall server,
* start Java Installer in poll mode, start convert server in another thread,
* convert server will give the names of the .jad or .jar/.dcf/.dm files to Java Installer
* when it polls them, convert server will log whether each installation
* succeeded. After all install files have been polled, convert server will ask
* Java Installer to exit. After that this active object moves to next state.
*
* EMarkConversionDone: remove 'uids' data file created by javaapppreconverter
*
* EExit: free resources and exit
*
*/
void CSilentMIDletConvert::RunL()
{
JELOG2(EJavaConverters);
switch (iState)
{
case EFindOutDeviceDrives:
{
LOG(EJavaConverters, EInfo,
"CSilentMIDletConvert::RunL EFindOutDeviceDrives");
GetAllDeviceDrivesL();
iState = EFindOutDrivesToBeScannedNow;
CompleteRequest();
}
break;
case EFindOutDrivesToBeScannedNow:
{
LOG(EJavaConverters, EInfo,
"CSilentMIDletConvert::RunL EFindOutDrivesToBeScannedNow");
TChar driveChar = 'C';
// forget old search directories
iDirs.ResetAndDestroy();
for (TInt drive = 0; drive < KMaxDrives; drive++)
{
// All present drives will be scanned for
// java applications to be converted
if (iDriveStatuses[drive] & DriveInfo::EDrivePresent)
{
(void)iFs.DriveToChar(drive, driveChar);
// The base Java application install directory in this
// drive must be scanned.
// Reserve memory also for drive letter and terminating zero
// for logging.
HBufC *baseInstallDir = HBufC::NewLC(KMidletSuiteInstallBasePath().Length() + 2);
TPtr dirPtr(baseInstallDir->Des());
dirPtr.Append(driveChar);
dirPtr.Append(KMidletSuiteInstallBasePath());
// Add new search directory
iDirs.AppendL(baseInstallDir);
CleanupStack::Pop(baseInstallDir);
}
}
iState = EAppsInInstalledDirectories;
CompleteRequest();
}
break;
case EAppsInInstalledDirectories:
{
LOG(EJavaConverters, EInfo,
"CSilentMIDletConvert::RunL EAppsInInstalledDirectories");
GetInstallFilesL(iDirs);
iState = ECheckWhichAppsShouldBeConverted;
CompleteRequest();
}
break;
case ECheckWhichAppsShouldBeConverted:
{
LOG(EJavaConverters, EInfo,
"CSilentMIDletConvert::RunL ECheckWhichAppsShouldBeConverted");
// Check all Jad / Jar files in iInstallFiles and remove those
// that need not be converted (those that cannot be found from
// AppArc). Updates also iNumberOfAppsToInstall
CheckNeedToInstall();
iState = EExecuteConvertServer;
CompleteRequest();
}
break;
case EExecuteConvertServer:
{
LOG(EJavaConverters, EInfo,
"CSilentMIDletConvert::RunL EExecuteConvertServer");
if (iNumberOfAppsToInstall > 0)
{
// Install all MIDlet Suites still in iInstallFiles.
// Pass iInstallFiles to ConvertServer
iConvertServer->setInstallFiles(iInstallFiles);
// Start the server
int err = iConvertServer->start();
if (0 != err)
{
// server cannot be started
ELOG1(EJavaConverters,
"Cannot start convert server, err %d", err);
}
// Starts Java Installer, waits until Java Installer exits
RunJavaInstallerL();
iState = EMarkConversionDone;
}
else
{
iState = EMarkConversionDone;
CompleteRequest();
}
}
break;
case EMarkConversionDone:
{
// If this line is executed, converting old midlets succeeded.
// Remove the 'uids' data file so that conversion will not be
// done again if OMJ sis package is installed again to the same device.
RemoveDataFile();
iState = EExit;
CompleteRequest();
}
break;
case EExit:
{
LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunL EExit");
// Stops the server if it is running
iConvertServer->stop();
FullCleanup();
// The whole javaappconverter process is stopped.
Exit();
}
break;
}
}
/**
* To handle leave from RunL.
* This method exits this active object using normal state machine
* After calling this method this active object will exit.
*
* @param aError - A reason of error.
* @return KErrNone.
*/
TInt CSilentMIDletConvert::RunError(TInt aError)
{
ELOG2(EJavaConverters,
"CSilentMIDletConvert::RunError(%d) from state %d", aError, iState);
Cancel();
iState = EExit;
CompleteRequest();
return KErrNone;
}
/**
* To do cancelling for this object.
*
*/
void CSilentMIDletConvert::DoCancel()
{
ELOG1(EJavaConverters,
"CSilentMIDletConvert::DoCancel from state %d", iState);
// Check whether convert server must be stopped
if (iState == EExecuteConvertServer)
{
// Stops the server if it is running
iConvertServer->stop();
}
}
/**
* Add .jad files in the directories specified in aDirs to iInstallFiles.
* If a directory does not contain a .jad file but it contains a .jar/.dcf/.dm file,
* add that file to iInstallFiles
*
* @param aDirs - An array of directories to be scanned.
* @exception Unable to alloc memory for the internal buffers.
* @exception Unable to get directory's contents.
*/
void CSilentMIDletConvert::GetInstallFilesL(RPointerArray<HBufC>& aDirs)
{
JELOG2(EJavaConverters);
// Number of MIDlet installation base directories to scan,
// one directory per local drive
const TInt nBaseDirs = aDirs.Count();
for (TInt i = 0; i < nBaseDirs; i++)
{
TFileName suitePath;
// Form base directory path, MIDlets have been installed
// to subdirectories of this directory
const TPtrC& dir = ((HBufC *)(aDirs[i]))->Des();
TFileName baseSuitePath = dir;
CDir *entryList;
CDir *dirList;
TInt err = iFs.GetDir(baseSuitePath, KEntryAttMatchMask, ESortNone, entryList, dirList);
if (KErrNone != err)
{
WLOG1WSTR(EJavaConverters,
"CSilentMIDletConvert::GetInstallFilesL Cannot list directory %s",
(wchar_t *)(baseSuitePath.PtrZ()));
// If no S60 Java application has been installed to the drive,
// the directory does not exist but it is OK
if (KErrPathNotFound != err)
{
User::Leave(err);
}
continue;
}
// Only midlet installation directory entries are meaningfull,
// discard other possible entries
delete entryList;
TInt nCount = dirList->Count();
TEntry dirEntry;
for (TInt nInd = 0; nInd < nCount; nInd++)
{
dirEntry = (*dirList)[nInd];
// Just to make sure this really is subdirectory
if (dirEntry.IsDir())
{
// Is this midlet suite subdir?
// Midlet suite subdirs look like this "[102b567B]"
// Must parse the value of the Uid as unsigned int to avoid
// overflow
TUint32 nUid;
TLex lexer(dirEntry.iName);
lexer.Inc();
err = lexer.Val(nUid, EHex);
if (KErrNone != err)
{
// Not midlet suite subdir, skip it
continue;
}
// Does the subdirectory contain any Jar files?
suitePath = baseSuitePath;
suitePath.Append(dirEntry.iName);
suitePath.Append(KSMCBackSplash);
CDir *suiteDirEntryList;
err = iFs.GetDir(suitePath, KEntryAttMatchMask, ESortNone, suiteDirEntryList);
if (KErrNone != err)
{
ELOG1WSTR(EJavaConverters,
"CSilentMIDletConvert::GetInstallFilesL Cannot list content of suite dir %s",
(wchar_t *)(suitePath.PtrZ()));
User::Leave(err);
return;
}
// If there is .jad or Jar file in suiteDirEntryList, adds
// it to iInstallFiles.
// Recognizes also DRM protected Jar files (.dm, .dcf)
AddJadJarToInstallFilesL(suitePath, suiteDirEntryList);
delete suiteDirEntryList;
}
} // for - loop all directory entries in a base installation directories
delete dirList;
} // for - loop all base installation directories
if (iInstallFiles.Count() == 0)
{
WLOG(EJavaConverters,
"CSilentMIDletConvert::GetInstallFilesL No MIDlets to convert");
}
}
/**
* Check all Jad / Jar files in iInstallFiles and remove those
* that need not be converted. Updates also iNumberOfAppsToInstall.
*/
void CSilentMIDletConvert::CheckNeedToInstall()
{
// It is too late to check from AppArc whether the application is a
// valid java application or no. The Java registry dll:s have been eclipsed and
// old apps are now invalid.
// javaapppreconverter has stored the Uids of the valid midlets to 'uids' file
// in to the data subdirectory of this process.
// ReadMidletUids() can be used to read the uids of the valid midlets to array.
// If uid is in the array, it is valid.
TFileName uidsDataFilePathName(KUidsImportDataFilePathName);
RArray<TUid> validUids = ReadMidletUids(uidsDataFilePathName);
// loop through iInstallFiles one be one
TInt nNumberOfAppsToInstall = 0;
TInt err;
TInt nFiles = iInstallFiles.Count();
TParse fp;
for (TInt nInd = 0; nInd < nFiles; nInd++)
{
// get the directory path of the current iInstallFiles[nInd]
err = fp.Set(*(iInstallFiles[nInd]), NULL, NULL);
if (KErrNone != err)
{
WLOG1(EJavaConverters,
"CSilentMIDletConvert::CheckNeedToInstall Cannot parse install file name %s",
iInstallFiles[nInd]);
continue;
}
TPtrC installDir = fp.DriveAndPath();
// read Java applications uid(s) from 'uids' file in the directory
RArray<TUid> appUids = ReadMidletUids(installDir);
// For each app uid, check whether it is uid of an valid java application.
// If yes, make conversion installation for the .jad/Jar file
// in this directory.
TInt nIndUids;
TInt nCountUids = appUids.Count();
for (nIndUids = 0; nIndUids < nCountUids; nIndUids++)
{
err = validUids.Find(appUids[nIndUids]);
if (KErrNotFound == err)
{
LOG1(EJavaConverters, EInfo,
"CSilentMIDletConvert::CheckNeedToInstall Midlet with Uid %x "
"was not registered to AppArc",
appUids[nIndUids].iUid);
// Do not convert any app in this Midlet suite
delete iInstallFiles[nInd];
iInstallFiles[nInd] = NULL;
break;
}
else
{
// The application is valid, so it should be converted
nNumberOfAppsToInstall++;
}
}
appUids.Close();
}
validUids.Close();
// how many applications to convert
iNumberOfAppsToInstall = nNumberOfAppsToInstall;
}
/**
* Read the midlet uids from file 'uids' in the directory
* given in parameter aDir and return them in RArray
*
* @param aDir - directory that contains 'uids' file
* @return the midlet uids in RArray. Caller must destroy the RArray
*/
RArray<TUid> CSilentMIDletConvert::ReadMidletUids(const TPtrC& aDir)
{
RArray<TUid> midletUids;
RFile fileUids;
TFileName nameUids = aDir;
nameUids.Append(_L("uids"));
TInt err = fileUids.Open(iFs, nameUids, EFileRead);
if (KErrNone != err)
{
// cannot open "uids" file
nameUids.Append(0);
WLOG1WSTR(EJavaConverters,
"CSilentMIDletConvert::ReadMidletUids cannot open uids file in dir %s",
(wchar_t *)(&(nameUids[0])));
WLOG1(EJavaConverters, "Error is %d", err);
return midletUids;
}
TInt fileSize(0);
err = fileUids.Size(fileSize);
if (fileSize < 8)
{
// valid "uids" file contains at least the uid of the suite and
// uid of at least one midlet
fileUids.Close();
// invalid "uids" file
nameUids.Append(0);
WLOG1WSTR(EJavaConverters,
"CSilentMIDletConvert::ReadMidletUids invalid uids file in dir %s",
(wchar_t *)(&(nameUids[0])));
return midletUids;
}
// reserve buffer for one uid
TBuf8<4> readBuf;
TDes8 readBufDes(readBuf);
// The first uid is suite uid but we are not interested in it. Skip it.
err = fileUids.Read(readBufDes);
if (KErrNone != err)
{
fileUids.Close();
// cannot read "uids" file
nameUids.Append(0);
WLOG1WSTR(EJavaConverters,
"CSilentMIDletConvert::ReadMidletUids cannot read uids file in dir %s",
(wchar_t *)(&(nameUids[0])));
WLOG1(EJavaConverters, "Error is %d", err);
return midletUids;
}
// Now read rest of the file one uid at a time
TInt nReadBytes = readBufDes.Length();
TUint midletUidValue;
TUint temp;
while (nReadBytes == 4)
{
err = fileUids.Read(readBufDes);
if (KErrNone != err)
{
fileUids.Close();
// cannot read "uids" file
nameUids.Append(0);
WLOG1WSTR(EJavaConverters,
"CSilentMIDletConvert::ReadMidletUids(2) cannot from uids file in dir %s",
(wchar_t *)(&(nameUids[0])));
WLOG1(EJavaConverters, "Error is %d", err);
return midletUids;
}
nReadBytes = readBufDes.Length();
if (nReadBytes == 4)
{
// One whole midlet id was read to buffer.
// 4 bytes per midlet, least significant byte first
TUid midletUid;
midletUidValue = readBufDes[0];
temp = readBufDes[1];
midletUidValue += temp<<8;
temp = readBufDes[2];
midletUidValue += temp<<16;
temp = readBufDes[3];
midletUidValue += temp<<24;
midletUid.iUid = midletUidValue;
midletUids.Append(midletUid);
}
}
fileUids.Close();
return midletUids;
}
/**
* Scan the content of one directory entry and add the name of
* .jad / .jar /.dcf/.dm file to iInstallFiles if
* the directory contains a valid, installed Java application.
* Recognizes also DRM protected jar files (.dm, .dcf)
*
* @param aSuitePathName - directory to be scanned.
* @param aSuiteDirEntryList - contents of the directory
* @exception Unable to alloc memory for the internal buffers.
*/
void CSilentMIDletConvert::AddJadJarToInstallFilesL(
const TFileName &aSuitePathName,
const CDir *aSuiteDirEntryList)
{
JELOG2(EJavaConverters);
if (NULL == aSuiteDirEntryList)
{
return;
}
TInt nCount = aSuiteDirEntryList->Count();
if (0 == nCount)
{
return;
}
TInt suffixPos;
TEntry dirEntry;
TBool jarFileInSuiteDir = EFalse;
TBool jadFileInSuiteDir = EFalse;
TFileName jadFullPathName;
TFileName jarFullPathName;
for (TInt nInd = 0; nInd < nCount; nInd++)
{
dirEntry = (*aSuiteDirEntryList)[nInd];
// Directory cannot be Jar file.
// Empty file cannot valid Jar file
if (dirEntry.IsDir() || (dirEntry.iSize == 0))
{
continue;
}
// get the suffix of the name
suffixPos = dirEntry.iName.LocateReverse('.');
if (suffixPos == KErrNotFound)
{
// File name does not contain '.' char
continue;
}
TPtrC suffix(dirEntry.iName.Mid(suffixPos));
// if the name ends with ".jar" the name is current candidate
// for the name to be added to iInstallFiles list
if (suffix.CompareF(KJarFileNameSuffix) == 0)
{
jarFullPathName = aSuitePathName;
jarFullPathName.Append(dirEntry.iName);
jarFileInSuiteDir = ETrue;
}
else if (suffix.CompareF(KJadFileNameSuffix) == 0)
{
// If .jad file is found, then it will be added
// to iInstallFiles list
jadFullPathName = aSuitePathName;
jadFullPathName.Append(dirEntry.iName);
jadFileInSuiteDir = ETrue;
}
else if (suffix.CompareF(KFLJarFileNameSuffix) == 0)
{
// forward locked and combined delivery DRM protected
// .jar files have suffix ".dm"
jarFullPathName = aSuitePathName;
jarFullPathName.Append(dirEntry.iName);
jarFileInSuiteDir = ETrue;
}
else if (suffix.CompareF(KSDJarFileNameSuffix) == 0)
{
// separate delivery DRM protected .jar files have suffix ".dcf"
jarFullPathName = aSuitePathName;
jarFullPathName.Append(dirEntry.iName);
jarFileInSuiteDir = ETrue;
}
}
// If directory contains a Jar file, then add something to iInstallFiles
if (jarFileInSuiteDir)
{
// If directory contains also .jad file, add .jad file name to iInstallFiles
if (jadFileInSuiteDir)
{
// Reserve one char for null terminator
HBufC* path = HBufC::NewLC(jadFullPathName.Length() + 1);
TPtr pathPtr(path->Des());
pathPtr.Append(jadFullPathName);
LOG1WSTR(EJavaConverters, EInfo,
"CSilentMIDletConvert::AddJadJarToInstallFilesL Adding jad file %s",
(wchar_t *)(pathPtr.PtrZ()));
iInstallFiles.Append(path);
CleanupStack::Pop(path);
}
else
{
// Reserve one char for null terminator
HBufC* path = HBufC::NewLC(jarFullPathName.Length() + 1);
TPtr pathPtr(path->Des());
pathPtr.Append(jarFullPathName);
LOG1WSTR(EJavaConverters, EInfo,
"CSilentMIDletConvert::AddJadJarToInstallFilesL Adding jar file %s",
(wchar_t *)(pathPtr.PtrZ()));
iInstallFiles.Append(path);
CleanupStack::Pop(path);
}
}
}
/**
* Start Java Installer in poll mode and then wait until it exits.
*/
void CSilentMIDletConvert::RunJavaInstallerL()
{
LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller");
RProcess rJavaInstaller;
TFileName fileName;
TInt err;
// Max one path name, user name and password and some options ->
// 1536 is enough
TBuf<1536> commandLine;
// Build command line used to pass all necessary info to Java Installer
std::auto_ptr<HBufC> installerStarterDll(
stringToDes(java::runtime::JAVA_INSTALLER_STARTER_DLL));
commandLine = installerStarterDll->Des();
commandLine.Append(_L(" poll -address=convert"));
// Run installer silently
commandLine.Append(_L(" -silent"));
// Convert old S60 applications so that applications uids,
// private data and RMS data are all preserved
commandLine.Append(_L(" -convert=yes"));
// Upgrading MIDlets is allowed
commandLine.Append(_L(" -upgrade=yes"));
// No OCSP checks for converted MIDlets
commandLine.Append(_L(" -ocsp=no"));
// Allow upgrade even if version number has not increased
commandLine.Append(_L(" -overwrite=yes"));
// Downloading .jar is not allowed.
commandLine.Append(_L(" -download=no"));
// If upgrade install, automatically upgrade also the data
commandLine.Append(_L(" -upgrade_data=yes"));
// If the device has an internal drive with much free disk space,
// install all converted applications to that drive
if (iDefaultTargetInstallationDrive > -1)
{
TChar targetDrive;
err = RFs::DriveToChar(iDefaultTargetInstallationDrive, targetDrive);
if (KErrNone == err)
{
commandLine.Append(_L(" -drive="));
commandLine.Append(targetDrive);
}
}
// start JavaInstaller
std::auto_ptr<HBufC> installerProcess(
stringToDes(java::runtime::JAVA_PROCESS));
err = rJavaInstaller.Create(installerProcess->Des(), commandLine);
if (KErrNone == err)
{
LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller calling Rendezvous");
// This call will wait until Java Installer exits (or panics)
rJavaInstaller.Logon(iStatus);
LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller calling Resume");
rJavaInstaller.Resume();
}
else
{
ELOG1(EJavaConverters,
"CSilentMIDletConvert::RunJavaInstaller Cannot start Installer, error %d", err);
// CActive will trap the following leave, execution will go to RunError
User::Leave(err);
}
LOG(EJavaConverters, EInfo, "CSilentMIDletConvert::RunJavaInstaller calling RProcess::Close");
// free resources before returning
rJavaInstaller.Close();
// now wait until Java Installer exits
SetActive();
}
/**
* To cleanup member variables.
*/
void CSilentMIDletConvert::FullCleanup()
{
JELOG2(EJavaConverters);
iDirs.ResetAndDestroy();
iInstallFiles.ResetAndDestroy();
}
/**
* Checks all local drives in the device and stores the DriveInfo API drive
* status information for each drive to iDriveStatuses
* @exception Cannot get drive list.
*/
void CSilentMIDletConvert::GetAllDeviceDrivesL()
{
JELOG2(EJavaConverters);
TDriveList driveList;
// get all drives
TInt err = iFs.DriveList(driveList);
if (KErrNone != err)
{
ELOG1(EJavaConverters,
"CSilentMIDletConvert::GetAllDeviceDrives cannot get drive list, err %d", err);
User::Leave(err);
}
// store status of the non-remote, non-substed drives
TInt64 requiredFreeDiskSpace = KMinimumFreeDiskSpace;
TUint status = 0;
for (TInt drive = 0; drive < KMaxDrives; drive++)
{
iDriveStatuses[drive] = 0;
if (driveList[drive] == 0)
{
// no such drive in this device
continue;
}
err = DriveInfo::GetDriveStatus(iFs, drive, status);
if (KErrNone != err)
{
ELOG2(EJavaConverters,
"CSilentMIDletConvert::GetAllDeviceDrivesL cannot get drive %d status, err %d",
drive, err);
User::Leave(err);
}
// D drive is temporary RAM drive, skip it
// Drives J to Y are substed or remote drives, skip them
if ((drive == EDriveD) || ((drive >= EDriveJ) && (drive <= EDriveY)))
{
continue;
}
iDriveStatuses[drive] = status;
// If the device has an internal (non-removable) drive with much
// free disk space, use that drive as the target installation drive
// when making the conversion installations.
// Skip drives A: to D:, C: drive is not valid target drive because
// we do not want to fill C: drive unnecessarily
if (drive < EDriveE)
{
continue;
}
// drive must be internal and visible to the user but
// it must NOT be corrupted or in exclusive use or read only
if ((status & DriveInfo::EDriveInternal) &&
(!(status & DriveInfo::EDriveCorrupt)) &&
(!(status & DriveInfo::EDriveInUse)) &&
(!(status & DriveInfo::EDriveReadOnly)) &&
(status & DriveInfo::EDriveUserVisible))
{
// Is there 'enough' free disk space for conversion
TVolumeInfo volumeInfo;
err = iFs.Volume(volumeInfo, drive);
if (KErrNone == err)
{
if (volumeInfo.iFree > requiredFreeDiskSpace)
{
iDefaultTargetInstallationDrive = drive;
// If some other internal drive has even more free
// disk space, it will be used as the target drive
requiredFreeDiskSpace = volumeInfo.iFree;
}
}
}
}
}
/**
* Remove the data file that contain information about the midlets to be converted.
*/
void CSilentMIDletConvert::RemoveDataFile()
{
TFileName dataFile(KUidsImportDataFilePathName);
dataFile.Append(KUidsImportDataFileName);
TInt err = iFs.Delete(dataFile);
if (KErrNone != err)
{
ELOG1(EJavaConverters,
"CSilentMIDletConvert::RemoveDataFile: Cannot delete data file, err %d ",
err);
}
}