Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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 the License "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:
// f32\sfile\sf_plugin_shim.cpp
//
//
#include "cl_std.h"
#include "sf_std.h"
/*******************************************************
* RFsPlugin *
*******************************************************/
EXPORT_C RFsPlugin::RFsPlugin(TFsPluginRequest& aRequest, TBool aDirectToDrive)
: iSessionHelper(&aRequest, aDirectToDrive)
{
SetReturnedHandle(KNullHandle);
}
EXPORT_C RFsPlugin::~RFsPlugin()
{
Close();
}
EXPORT_C TInt RFsPlugin::Connect()
/**
Connects a file server plugin to the file server.
To end the file server session, use Close().
@return KErrNone, if successful, otherwise one of the other system-wide error codes.
*/
{
return KErrNone;
}
EXPORT_C void RFsPlugin::Close()
/**
Closes a file server plugin session.
*/
{
SetReturnedHandle(KNullHandle);
}
EXPORT_C TInt RFsPlugin::Delete(const TDesC& aName)
/**
Deletes a single file.
@see RFs::Delete
*/
{
return(RFs::Delete(aName));
}
EXPORT_C TInt RFsPlugin::Rename(const TDesC& aOldName,const TDesC& aNewName)
/**
Renames a single file or directory.
@see RFs::Rename
*/
{
return(RFs::Rename(aOldName, aNewName));
}
EXPORT_C TInt RFsPlugin::Replace(const TDesC& aOldName,const TDesC& aNewName)
/**
Replaces a single file with another.
@see RFs::Replace
*/
{
return(RFs::Replace(aOldName, aNewName));
}
EXPORT_C TInt RFsPlugin::Entry(const TDesC& aName,TEntry& aEntry) const
/**
Gets the entry details for a file or directory.
@see RFs::Entry
*/
{
return(RFs::Entry(aName, aEntry));
}
EXPORT_C TInt RFsPlugin::SetEntry(const TDesC& aName,const TTime& aTime,TUint aSetAttMask,TUint aClearAttMask)
/**
Sets both the attributes and the last modified date and time for a file or directory.
@see RFs::SetEntry
*/
{
return(RFs::SetEntry(aName,aTime,aSetAttMask,aClearAttMask));
}
EXPORT_C TInt RFsPlugin::ReadFileSection(const TDesC& aName,TInt64 aPos,TDes8& aDes,TInt aLength) const
/**
Reads data from a file without opening it.
The contents of the file can be accessed regardless of the file's lock state.
@see RFs::ReadFileSection
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return(RFs::ReadFileSection(aName,I64LOW(aPos),aDes,aLength));
#else
return(RFs::ReadFileSection(aName,aPos,aDes,aLength));
#endif
}
EXPORT_C TInt RFsPlugin::Volume(TVolumeInfo &aVol, TInt aDrive) const
/**
Gets volume information for a formatted device.
@see RFs::Volume
*/
{
return (RFs::Volume(aVol, aDrive));
}
TInt RFsPlugin::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
{
return iSessionHelper.SendReceive(aFunction, aArgs);
}
TInt RFs::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
{
if(Handle())
return RSessionBase::SendReceive(aFunction, aArgs);
return ((RFsPlugin*) this)->SendReceive(aFunction, aArgs);
}
/*******************************************************
* RFilePlugin *
*******************************************************/
EXPORT_C RFilePlugin::RFilePlugin(TFsPluginRequest& aRequest, TBool aDirectToDrive)
: iSessionHelper(&aRequest, aDirectToDrive)
{
SetHandle(KErrBadHandle);
SetSubSessionHandle(KErrBadHandle);
}
EXPORT_C RFilePlugin::~RFilePlugin()
{
Close();
}
EXPORT_C TInt RFilePlugin::Open(const TDesC& aName,TUint aMode)
/**
Opens an existing file for reading or writing.
If the file does not already exist, an error is returned.
@see RFile::Open
*/
{
RFs fs;
fs.SetHandle(Session().Handle());
return(CreateSubSession(fs,EFsFileOpen,TIpcArgs(&aName,aMode)));
}
EXPORT_C void RFilePlugin::Close()
/**
Closes the file.
@see RFile::Close
*/
{
CloseSubSession(EFsFileSubClose);
SetSubSessionHandle(KErrBadHandle);
}
EXPORT_C TInt RFilePlugin::Create(const TDesC& aName,TUint aFileMode)
/**
Closes the file.
@see RFile::Create
*/
{
RFs fs;
fs.SetHandle(Session().Handle());
return(CreateSubSession(fs,EFsFileCreate,TIpcArgs(&aName,aFileMode)));
}
EXPORT_C TInt RFilePlugin::Replace(const TDesC& aName,TUint aFileMode)
/**
Closes the file.
@see RFile::Replace
*/
{
RFs fs;
fs.SetHandle(Session().Handle());
return(CreateSubSession(fs,EFsFileReplace,TIpcArgs(&aName,aFileMode)));
}
EXPORT_C TInt RFilePlugin::Temp(const TDesC& aPath,TFileName& aName,TUint aFileMode)
/**
Closes the file.
@see RFile::Temp
*/
{
RFs fs;
fs.SetHandle(Session().Handle());
return(CreateSubSession(fs,EFsFileTemp,TIpcArgs(&aPath,aFileMode,&aName)));
}
EXPORT_C TInt RFilePlugin::AdoptFromClient()
/**
Closes the file.
@see RFile::AdoptFromClient
*/
{
TFsPluginRequest* request = iSessionHelper.Request();
if(request == NULL)
return KErrBadHandle;
TInt clientSubSessionHandle;
TInt err = request->ClientSubSessionHandle(clientSubSessionHandle);
if (err != KErrNone)
return err;
RFs fs;
fs.SetHandle(Session().Handle());
err = CreateSubSession(fs,EFsFileDuplicate, TIpcArgs(clientSubSessionHandle, ETrue));
if (err != KErrNone)
return err;
SetSubSessionHandle(SubSessionHandle() ^ KSubSessionMangleBit);
return err;
}
EXPORT_C TInt RFilePlugin::TransferToClient()
/**
Closes the file.
@see RFile::TransferToClient
*/
{
TFsPluginRequest* request = iSessionHelper.Request();
if(request == NULL)
return KErrBadHandle;
// This doesn't behave like a standard duplicate as we're running in the context of the
// client's session. Instead, we can simply return our subsession handle to the client.
TRAPD(err, request->Request()->WriteL(KMsgPtr3, TPckgC<TInt>(SubSessionHandle())));
// Next we have to free up the close request reserved for our internal subsession
// otherwise two messages will be reserved for the client...
RequestAllocator::OpenSubFailed(request->Request()->Session());
// And now we're done - we don't bother closing, as the client now completely owns the handle
SetSubSessionHandle(KErrBadHandle);
return err;
}
EXPORT_C TInt RFilePlugin::Write(TInt64 aPos, const TDesC8& aDes)
/**
Writes to the file at the specified offset within the file
@see RFile::Write
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::Write(I64LOW(aPos), aDes);
#else
return RFile64::Write(aPos, aDes);
#endif
}
EXPORT_C TInt RFilePlugin::Write(TInt64 aPos,const TDesC8& aDes,TInt aLen)
/**
Writes the specified number of bytes to the file at the specified offset within the file.
@see RFile::Write
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::Write(I64LOW(aPos), aDes, aLen);
#else
return RFile64::Write(aPos, aDes, aLen);
#endif
}
EXPORT_C TInt RFilePlugin::Read(TInt64 aPos,TDes8& aDes) const
/**
Reads from the file at the specified offset within the file
@see RFile::Read
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::Read(I64LOW(aPos), aDes);
#else
return RFile64::Read(aPos, aDes);
#endif
}
EXPORT_C TInt RFilePlugin::Read(TInt64 aPos,TDes8& aDes,TInt aLen) const
/**
Reads the specified number of bytes of binary data from the file at a specified
offset within the file.
@see RFile::Read
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::Read(I64LOW(aPos), aDes, aLen);
#else
return RFile64::Read(aPos, aDes, aLen);
#endif
}
EXPORT_C TInt RFilePlugin::Size(TInt64& aSize) const
/**
Gets the current file size.
@see RFile::Size
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
TInt size = I64LOW(aSize);
TInt err = RFile::Size(size);
aSize = size;
return err;
#else
return RFile64::Size(aSize);
#endif
}
EXPORT_C TInt RFilePlugin::SetSize(TInt64 aSize)
/**
Sets the file size.
@see RFile::SetSize
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::SetSize(I64LOW(aSize));
#else
return RFile64::SetSize(aSize);
#endif
}
EXPORT_C TInt RFilePlugin::Lock(TInt64 aPos, TInt64 aLength) const
/**
Locks a region within the file as defined by a range of bytes.
@see RFile::Lock
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::Lock(I64LOW(aPos), I64LOW(aLength));
#else
return RFile64::Lock(aPos, aLength);
#endif
}
EXPORT_C TInt RFilePlugin::UnLock(TInt64 aPos, TInt64 aLength) const
/**
Unlocks a region within the file as defined by a range of bytes.
@see RFile::UnLock
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
return RFile::UnLock(I64LOW(aPos), I64LOW(aLength));
#else
return RFile64::UnLock(aPos, aLength);
#endif
}
EXPORT_C TInt RFilePlugin::Seek(TSeek aMode,TInt64& aPos) const
/**
Sets the the current file position.
@see RFile::Seek
*/
{
#ifndef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
TInt position = I64LOW(aPos);
TInt err = RFile::Seek(aMode, position);
if(err != KErrNone)
return err;
aPos = position;
return KErrNone;
#else
return RFile64::Seek(aMode, aPos);
#endif
}
EXPORT_C TInt RFilePlugin::Flush()
/**
Commits data to the storage device and flushes internal buffers without closing
the file.
@see RFile::Flush
*/
{
return RFile::Flush();
}
EXPORT_C TInt RFilePlugin::Att(TUint& aVal) const
/**
Gets the file's attributes.
@see RFile::Att
*/
{
return RFile::Att(aVal);
}
EXPORT_C TInt RFilePlugin::SetAtt(TUint aSetAttMask,TUint aClearAttMask)
/**
Sets or clears file attributes using two bitmasks.
@see RFile::SetAtt
*/
{
return RFile::SetAtt(aSetAttMask, aClearAttMask);
}
EXPORT_C TInt RFilePlugin::Modified(TTime& aTime) const
/**
Gets local date and time the file was last modified, in universal time.
@see RFile::Modified
*/
{
return RFile::Modified(aTime);
}
EXPORT_C TInt RFilePlugin::SetModified(const TTime& aTime)
/**
Sets the date and time the file was last modified. UTC date and time should be used.
@see RFile::SetModified
*/
{
return RFile::SetModified(aTime);
}
EXPORT_C TInt RFilePlugin::Set(const TTime& aTime,TUint aMask,TUint aVal)
/**
Sets the file’s attributes, and the date and time it was last modified.
@see RFile::Set
*/
{
return RFile::Set(aTime, aMask, aVal);
}
EXPORT_C TInt RFilePlugin::ChangeMode(TFileMode aNewMode)
/**
Switches an open file's access mode between EFileShareExclusive and EFileShareReadersOnly.
@see RFile::ChangeMode
*/
{
return RFile::ChangeMode(aNewMode);
}
EXPORT_C TInt RFilePlugin::Rename(const TDesC& aNewName)
/**
Renames a file.
@see RFile::Rename
*/
{
return RFile::Rename(aNewName);
}
void RFilePlugin::SetHandle(TInt aHandle)
{
*(((TInt*) this) + 0) = aHandle;
}
void RFilePlugin::SetSubSessionHandle(TInt aHandle)
{
*(((TInt*) this) + 1) = aHandle;
}
TInt RFilePlugin::CreateSubSession(const RSessionBase& aSession, TInt aFunction, const TIpcArgs& aArgs)
{
TInt reply;
TInt err = iSessionHelper.CreateSubSession(aSession, aFunction, aArgs, &reply);
if(err == KErrNone)
SetSubSessionHandle(reply);
return(err);
}
void RFilePlugin::CloseSubSession(TInt aFunction)
{
if (SubSessionHandle())
{
SendReceive(aFunction,TIpcArgs(TIpcArgs::ENothing,TIpcArgs::ENothing,TIpcArgs::ENothing,SubSessionHandle()));
}
SetHandle(KErrBadHandle);
SetSubSessionHandle(KErrBadHandle);
}
TInt RFilePlugin::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
{
return iSessionHelper.SendReceive(aFunction, aArgs, ((RFilePlugin*) this)->SubSessionHandle());
}
TInt RFile::CreateSubSession(const RSessionBase& aSession,TInt aFunction,const TIpcArgs& aArgs)
{
if(SubSessionHandle() == KErrBadHandle)
return ((RFilePlugin*) this)->CreateSubSession(aSession, aFunction, aArgs);
return RSubSessionBase::CreateSubSession(aSession, aFunction, aArgs);
}
void RFile::CloseSubSession(TInt aFunction)
{
if((Session().Handle() ^ CObjectIx::ENoClose) != KErrBadHandle)
RSubSessionBase::CloseSubSession(aFunction);
else
((RFilePlugin*) this)->CloseSubSession(aFunction);
}
TInt RFile::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
{
if((Session().Handle() ^ CObjectIx::ENoClose) != KErrBadHandle)
return RSubSessionBase::SendReceive(aFunction, aArgs);
return ((RFilePlugin*) this)->SendReceive(aFunction, aArgs);
}
/*******************************************************
* RDirPlugin *
*******************************************************/
EXPORT_C RDirPlugin::RDirPlugin(TFsPluginRequest& aRequest, TBool aDirectToDrive)
: iSessionHelper(&aRequest, aDirectToDrive)
{
SetHandle(KErrBadHandle);
SetSubSessionHandle(KErrBadHandle);
}
EXPORT_C RDirPlugin::~RDirPlugin()
{
Close();
}
EXPORT_C TInt RDirPlugin::Open(const TDesC& aMatchName,const TUidType& aUidType)
/**
Opens a directory using the specified UID type to filter the
directory entry types that will subsequently be read.
@see RDir::Open
*/
{
RFs fs;
fs.SetHandle(Session().Handle());
TPckgC<TUidType> pckgUid(aUidType);
return(CreateSubSession(fs,EFsDirOpen,TIpcArgs(&aMatchName,KEntryAttAllowUid,&pckgUid)));
}
EXPORT_C TInt RDirPlugin::Open(const TDesC& aMatchName,TUint anAttMask)
/**
Opens a directory using an attribute bitmask to filter the directory entry
types that will subsequently be read.
@see RDir::Open
*/
{
RFs fs;
fs.SetHandle(Session().Handle());
TUidType uidType(TUid::Null(),TUid::Null(),TUid::Null());
TPckgC<TUidType> pckgUid(uidType);
return(CreateSubSession(fs,EFsDirOpen,TIpcArgs(&aMatchName,anAttMask,&pckgUid)));
}
EXPORT_C void RDirPlugin::Close()
/**
Closes the the directory.
@see RDir::Close
*/
{
CloseSubSession(EFsDirSubClose);
SetSubSessionHandle(KErrBadHandle);
}
EXPORT_C TInt RDirPlugin::Read(TEntryArray& aArray)
/**
Reads all filtered directory entries into the specified array.
@see RDir::Read
*/
{
return RDir::Read(aArray);
}
EXPORT_C TInt RDirPlugin::Read(TEntry& aEntry)
/**
Reads all filtered directory entries into the specified array.
@see RDir::Read
*/
{
return RDir::Read(aEntry);
}
void RDirPlugin::SetHandle(TInt aHandle)
{
*(((TInt*) this) + 0) = aHandle;
}
void RDirPlugin::SetSubSessionHandle(TInt aHandle)
{
*(((TInt*) this) + 1) = aHandle;
}
TInt RDirPlugin::CreateSubSession(const RSessionBase& aSession, TInt aFunction, const TIpcArgs& aArgs)
{
TInt reply;
TInt err = iSessionHelper.CreateSubSession(aSession, aFunction, aArgs, &reply);
if(err == KErrNone)
SetSubSessionHandle(reply);
return(err);
}
void RDirPlugin::CloseSubSession(TInt aFunction)
{
if (SubSessionHandle())
{
SendReceive(aFunction,TIpcArgs(TIpcArgs::ENothing,TIpcArgs::ENothing,TIpcArgs::ENothing,SubSessionHandle()));
}
SetHandle(KErrBadHandle);
SetSubSessionHandle(KErrBadHandle);
}
TInt RDirPlugin::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
{
return iSessionHelper.SendReceive(aFunction, aArgs, ((RDirPlugin*) this)->SubSessionHandle());
}
TInt RDir::SendReceive(TInt aFunction,const TIpcArgs& aArgs) const
{
if((Session().Handle() ^ CObjectIx::ENoClose) != KErrBadHandle)
return RSubSessionBase::SendReceive(aFunction, aArgs);
return ((RDirPlugin*) this)->SendReceive(aFunction, aArgs);
}
/*******************************************************
* TFsPluginSessionHelper *
*******************************************************/
TPluginSessionHelper::TPluginSessionHelper()
{ memclr(this, sizeof(TPluginSessionHelper)); }
TPluginSessionHelper::TPluginSessionHelper(TFsPluginRequest* aRequest, TBool aDirectToDrive)
: iPlugin(aRequest->Request()->iCurrentPlugin),
iSession(aRequest->Request()->Session()),
iDirectToDrive(aDirectToDrive),
iRequest(aRequest)
{
// need to initialise RLocalMessage with client session
*((RMessage2*) &iMessage) = aRequest->Message();
iMessage.InitHandle(); // set handle to KLocalMessageHandle
memclr(iSpare, sizeof(iSpare));
}
TInt TPluginSessionHelper::CreateSubSession(const RSessionBase& aSession, TInt aFunction, const TIpcArgs& aArgs, TInt* aReply)
{
(void)aSession;
// Init message
TIpcArgs args;
args.iArgs[0] = aArgs.iArgs[0];
args.iArgs[1] = aArgs.iArgs[1];
args.iArgs[2] = aArgs.iArgs[2];
args.iFlags = aArgs.iFlags&((1<<(3*TIpcArgs::KBitsPerType))-1);
TPckgBuf<TInt> reply;
args.Set(3,&reply);
// copy session pointer
RLocalMessage message = iMessage;
message.SetFunction(aFunction);
message.SetArgs(args);
TInt err = Dispatch(aFunction, args);
if (err == KErrNone)
*aReply = reply();
return err;
}
TInt TPluginSessionHelper::Dispatch(TInt aFunction, TIpcArgs& aArgs) const
{
// copy session pointer
RLocalMessage message = iMessage;
message.SetFunction(aFunction);
message.SetArgs(aArgs);
// allocate request
CFsClientMessageRequest* newRequest;
const TOperation& oP = OperationArray[aFunction & KIpcFunctionMask];
TInt err = RequestAllocator::GetMessageRequest(oP, message, newRequest);
if (err != KErrNone)
return err;
newRequest->Set(message, oP, iSession);
//This is wrong. drive number is set in TFsXxx::initialise
//newRequest->SetDrive(&TheDrives[iPlugin->Drive()]);
newRequest->iCurrentPlugin = iPlugin;
newRequest->iOwnerPlugin = iPlugin;
newRequest->iDirectToDrive = iDirectToDrive;
newRequest->Dispatch();
// NOTE : newRequest will be free'd by the File Server before completing the
// request so it's not safe to touch the request from now on...
return(iPlugin->WaitForRequest());
}
TInt TPluginSessionHelper::SendReceive(TInt aFunction, const TIpcArgs& aArgs, TInt aSubSessionHandle) const
{
// Init message
TIpcArgs args;
args.iArgs[0] = aArgs.iArgs[0];
args.iArgs[1] = aArgs.iArgs[1];
args.iArgs[2] = aArgs.iArgs[2];
args.iFlags = aArgs.iFlags&((1<<(3*TIpcArgs::KBitsPerType))-1);
args.iArgs[3] = aSubSessionHandle;
return Dispatch(aFunction, args);
}
TInt TPluginSessionHelper::SendReceive(TInt aFunction, const TIpcArgs& aArgs) const
{
// Init message
TIpcArgs args;
args.iArgs[0] = aArgs.iArgs[0];
args.iArgs[1] = aArgs.iArgs[1];
args.iArgs[2] = aArgs.iArgs[2];
args.iArgs[3] = aArgs.iArgs[3];
args.iFlags = aArgs.iFlags&((1<<(3*TIpcArgs::KBitsPerType))-1);
return Dispatch(aFunction, args);
}
GLDEF_C void Panic(TClientPanic aPanic)
//
// Panic the current client with a file server client side panic.
//
{
User::Panic(_L("FS_PLUGIN_CLIENT panic"),aPanic);
}