//static bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { QString sourcepath = absoluteName(source).nativeFilePath(); QString targetpath = absoluteName(target).nativeFilePath(); RFs& fs(qt_s60GetRFs()); TInt err = fs.Rename(qt_QString2TPtrC(sourcepath), qt_QString2TPtrC(targetpath)); if (err == KErrNone) return true; error = QSystemError(err, QSystemError::NativeError); return false; }
//static bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents) { QString abspath = absoluteName(entry).nativeFilePath(); if (!abspath.endsWith(QLatin1Char('\\'))) abspath.append(QLatin1Char('\\')); TInt r; if (createParents) r = qt_s60GetRFs().MkDirAll(qt_QString2TPtrC(abspath)); else r = qt_s60GetRFs().MkDir(qt_QString2TPtrC(abspath)); if (createParents && r == KErrAlreadyExists) return true; //# Qt5 - QDir::mkdir returns false for existing dir, QDir::mkpath returns true (should be made consistent in Qt 5) return (r == KErrNone); }
//static bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error) { //CFileMan is allocated each time because it is not thread-safe CFileMan *fm = 0; TRAPD(err, fm = CFileMan::NewL(qt_s60GetRFs())); if (err == KErrNone) { err = fm->Copy(qt_QString2TPtrC(absoluteName(source).nativeFilePath()), qt_QString2TPtrC(absoluteName(target).nativeFilePath()), 0); delete fm; } if (err == KErrNone) return true; error = QSystemError(err, QSystemError::NativeError); return false; }
static bool handleOtherSchemes(const QUrl &url) { QString encUrl(QString::fromUtf8(url.toEncoded())); TPtrC urlPtr(qt_QString2TPtrC(encUrl)); TRAPD( err, handleOtherSchemesL(urlPtr)); return err ? false : true; }
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */) { // Grab a pointer to the memory block if (!chunk.Handle()) { QString function = QLatin1String("QSharedMemory::handle"); QString safeKey = makePlatformSafeKey(key); if (safeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: unable to make key").arg(function); return false; } TPtrC ptr(qt_QString2TPtrC(safeKey)); TInt err = KErrNoMemory; err = chunk.OpenGlobal(ptr, false); if (err != KErrNone) { setErrorString(function, err); return false; } } size = chunk.Size(); memory = chunk.Base(); return true; }
bool QSharedMemoryPrivate::create(int size) { // Get a windows acceptable key QString safeKey = makePlatformSafeKey(key); QString function = QLatin1String("QSharedMemory::create"); if (safeKey.isEmpty()) { error = QSharedMemory::KeyError; errorString = QSharedMemory::tr("%1: key error").arg(function); return false; } TPtrC ptr(qt_QString2TPtrC(safeKey)); TInt err = chunk.CreateGlobal(ptr, size, size); setErrorString(function, err); if (err != KErrNone) return false; // Zero out the created chunk Mem::FillZ(chunk.Base(), chunk.Size()); return true; }
int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode) { if (semaphore.Handle()) { return semaphore.Handle(); } // don't allow making handles on empty keys if (key.isEmpty()) return 0; TPtrC name(qt_QString2TPtrC(fileName)); int err = KErrAlreadyExists; int tryCount = 10; // Sort out race conditions by retrying several times until existing handle is acquired. // Sometimes opening can fail inexplicably with KErrPermissionDenied many times in a row. while (err != KErrNoMemory && err != KErrNone && tryCount-- >= 0) { err = semaphore.CreateGlobal(name, initialValue, EOwnerProcess); if (err != KErrNoMemory && err != KErrNone) err = semaphore.OpenGlobal(name,EOwnerProcess); } if (err){ setErrorString(QLatin1String("QSystemSemaphore::handle"),err); return 0; } return semaphore.Handle(); }
QString CSmfCredMgrClientSymbian::storeRSAKeysL(const QString KeyLabel, const QString keydata, const QDateTime Validity) { RDebug::Printf("Sending store RSA key message to server"); TPtrC labelPtr(qt_QString2TPtrC(KeyLabel)); TPtr dataPtr((qt_QString2HBufC(keydata)->Des())); QDateTime CurrentTime = QDateTime::currentDateTime(); TTimeIntervalSeconds duration(CurrentTime.secsTo(Validity)); TTime startDate; startDate.UniversalTime(); TTime endDate(startDate); endDate += duration; CSmfRsaKeyParameters* storeRSAKeysparams = CSmfRsaKeyParameters::NewL( labelPtr, startDate, endDate, (dataPtr.Collapse())); CleanupStack::PushL(storeRSAKeysparams); CBufFlat* buf = CBufFlat::NewL(KMinBufSize); CleanupStack::PushL(buf); RBufWriteStream stream(*buf); CleanupClosePushL(stream); storeRSAKeysparams->ExternalizeL(stream); stream.CommitL(); TPtr8 bufPtr = buf->Ptr(0); TIpcArgs args; args.Set(0, &bufPtr); CleanupStack::PopAndDestroy(&stream); HBufC8* retBuf = HBufC8::NewLC(KSHA1HashLengthBytes); TPtr8 retBufPtr(retBuf->Des()); args.Set(1, &retBufPtr); iSession.RequestService(ESmfStoreRSAKey, args); RDebug::Printf("SMF: Message completed"); TBuf<KSHA1HashLengthBytes> key; key.Copy(retBufPtr); QString RetString(qt_TDesC2QString(key)); CleanupStack::Pop(retBuf); CleanupStack::PopAndDestroy(buf); CleanupStack::PopAndDestroy(storeRSAKeysparams); RDebug::Printf("-In storeAuthDataL()"); return (RetString); }
//static bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error) { QString targetpath = absoluteName(entry).nativeFilePath(); RFs& fs(qt_s60GetRFs()); TInt err = fs.Delete(qt_QString2TPtrC(targetpath)); if (err == KErrNone) return true; error = QSystemError(err, QSystemError::NativeError); return false; }
// The biggest advantage of schemehandler is that it can handle // wide range of schemes and is extensible by plugins static bool handleUrl(const QUrl &url) { if (!url.isValid()) return false; QString urlString(url.toString()); TPtrC urlPtr(qt_QString2TPtrC(urlString)); TRAPD( err, handleUrlL(urlPtr)); return err ? false : true; }
CFont *QFontEngineS60::fontWithSize(qreal size) const { CFont *result = 0; TFontSpec fontSpec(qt_QString2TPtrC(QFontEngine::fontDef.family), TInt(size)); fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); fontSpec.iFontStyle.SetPosture(QFontEngine::fontDef.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); fontSpec.iFontStyle.SetStrokeWeight(QFontEngine::fontDef.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal); const TInt errorCode = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(result, fontSpec); Q_ASSERT(result && (errorCode == 0)); return result; }
static bool openDocument(const QUrl &file) { if (!file.isValid()) return false; QString filePath = file.toLocalFile(); filePath = QDir::toNativeSeparators(filePath); TPtrC filePathPtr(qt_QString2TPtrC(filePath)); TRAPD(err, openDocumentL(filePathPtr)); return err ? false : true; }
QT_BEGIN_NAMESPACE QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &path, QDir::Filters filters, const QStringList &nameFilters, QDirIterator::IteratorFlags iteratorFlags) : lastError(KErrNone), entryIndex(-1) { RFs& fs = qt_s60GetRFs(); nativePath = path.nativeFilePath(); if (!nativePath.endsWith(QLatin1Char('\\'))) nativePath.append(QLatin1Char('\\')); QString absPath = QFileSystemEngine::absoluteName(path).nativeFilePath(); if (!absPath.endsWith(QLatin1Char('\\'))) absPath.append(QLatin1Char('\\')); int pathLen = absPath.length(); if (pathLen > KMaxFileName) { lastError = KErrBadName; return; } //set up server side filtering to reduce IPCs //RDir won't accept all valid name filters e.g. "*. bar" if (nameFilters.count() == 1 && !(filters & QDir::AllDirs) && iteratorFlags == QDirIterator::NoIteratorFlags && pathLen + nameFilters[0].length() <= KMaxFileName) { //server side supports one mask - skip this for recursive mode or if only files should be filtered absPath.append(nameFilters[0]); } TUint symbianMask = 0; if ((filters & QDir::Dirs) || (filters & QDir::AllDirs) || (iteratorFlags & QDirIterator::Subdirectories)) symbianMask |= KEntryAttDir; //include directories if (filters & QDir::Hidden) symbianMask |= KEntryAttHidden; if (filters & QDir::System) symbianMask |= KEntryAttSystem; //Do not use KEntryAttMatchExclusive to optimise to return only //directories for QDir::Dirs. There may be a file which is actually //a "mount point" for a file engine and needs to be returned so it //can be overriden to be a directory, see QTBUG-23688 if (symbianMask == 0 && ((filters & QDir::PermissionMask) == QDir::Writable)) { symbianMask = KEntryAttMatchExclude | KEntryAttReadOnly; } lastError = dirHandle.Open(fs, qt_QString2TPtrC(absPath), symbianMask); }
void writeToSymbianStoreLX(const QMimeData* aData, CClipboard* clipboard) { // This function both leaves and throws exceptions. There must be no destructor // dependencies between cleanup styles, and no cleanup stack dependencies on stacked objects. if (aData->hasText()) { CPlainText* text = CPlainText::NewL(); CleanupStack::PushL(text); TPtrC textPtr(qt_QString2TPtrC(aData->text())); text->InsertL(KPlainTextBegin, textPtr); text->CopyToStoreL(clipboard->Store(), clipboard->StreamDictionary(), KPlainTextBegin, textPtr.Length()); CleanupStack::PopAndDestroy(text); } }
/*! \property QPluginLoader::fileName \brief the file name of the plugin To be loadable, the file's suffix must be a valid suffix for a loadable library in accordance with the platform, e.g. \c .so on Unix, \c .dylib on Mac OS X, and \c .dll on Windows. The suffix can be verified with QLibrary::isLibrary(). If the file name does not exist, it will not be set. This property will then contain an empty string. By default, this property contains an empty string. Note: In Symbian the \a fileName must point to plugin stub file. \sa load() */ void QPluginLoader::setFileName(const QString &fileName) { #if defined(QT_SHARED) QLibrary::LoadHints lh; if (d) { lh = d->loadHints; d->release(); d = 0; did_load = false; } #if defined(Q_OS_SYMBIAN) // In Symbian we actually look for plugin stub, so modify the filename // to make canonicalFilePath find the file, if .dll is specified. QFileInfo fi(fileName); if (fi.suffix() == QLatin1String("dll")) { QString stubName = fileName; stubName.chop(3); stubName += QLatin1String("qtplugin"); fi = QFileInfo(stubName); } QString fn = fi.canonicalFilePath(); // If not found directly, check also all the available drives if (!fn.length()) { QString stubPath(fi.fileName().length() ? fi.absoluteFilePath() : QString()); if (stubPath.length() > 1) { if (stubPath.at(1).toAscii() == ':') stubPath.remove(0,2); QFileInfoList driveList(QDir::drives()); RFs rfs = qt_s60GetRFs(); foreach(const QFileInfo& drive, driveList) { QString testFilePath(drive.absolutePath() + stubPath); testFilePath = QDir::cleanPath(testFilePath); // Use native Symbian code to check for file existence, because checking // for file from under non-existent protected dir like E:/private/<uid> using // QFile::exists causes platform security violations on most apps. QString nativePath = QDir::toNativeSeparators(testFilePath); TPtrC ptr(qt_QString2TPtrC(nativePath)); TUint attributes; TInt err = rfs.Att(ptr, attributes); if (err == KErrNone) { fn = testFilePath; break; } } }
bool QSharedMemoryPrivate::create(int size) { if (!handle()) return false; TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = chunk.CreateGlobal(ptr, size, size); if (err != KErrNone) { setErrorString(QLatin1String("QSharedMemory::create"), err); return false; } // Zero out the created chunk Mem::FillZ(chunk.Base(), chunk.Size()); return true; }
EXPORT_C QString localizedDirectoryName(QString& rawPath) { QString ret; std::exception dummy; // voodoo fix for "Undefined symbol typeinfo for std::exception" in armv5 build TRAPD(err, QT_TRYCATCH_LEAVING( CDirectoryLocalizer* localizer = CDirectoryLocalizer::NewL(); CleanupStack::PushL(localizer); localizer->SetFullPath(qt_QString2TPtrC(QDir::toNativeSeparators(rawPath))); if(localizer->IsLocalized()){ TPtrC locName(localizer->LocalizedName()); ret = qt_TDesC2QString(locName); } CleanupStack::PopAndDestroy(localizer); ) ) if (err != KErrNone)
QT_BEGIN_NAMESPACE /* Helper function for calling into Symbian classes that expect a TDes&. This function converts a QString to a TDes by allocating memory that must be deleted by the caller. */ Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString) { HBufC *buffer; #ifdef QT_NO_UNICODE TPtrC8 ptr(reinterpret_cast<const TUint8*>(aString.toLocal8Bit().constData())); #else TPtrC16 ptr(qt_QString2TPtrC(aString)); #endif buffer = q_check_ptr(HBufC::New(ptr.Length())); buffer->Des().Copy(ptr); return buffer; }
//static bool QFileSystemEngine::removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents) { QString abspath = absoluteName(entry).nativeFilePath(); if (!abspath.endsWith(QLatin1Char('\\'))) abspath.append(QLatin1Char('\\')); TPtrC dir(qt_QString2TPtrC(abspath)); RFs& fs = qt_s60GetRFs(); bool ok = false; //behaviour of FS file engine: //returns true if the directory could be removed //success/failure of removing parent directories does not matter while (KErrNone == fs.RmDir(dir)) { ok = true; if (!removeEmptyParents) break; //RFs::RmDir treats "c:\foo\bar" and "c:\foo\" the same, so it is sufficient to remove the last \ to the end dir.Set(dir.Left(dir.LocateReverse(TChar('\\')))); } return ok; }
bool QSymSQLResult::prepare(const QString &query) { if (!driver() || !driver()->isOpen() || driver()->isOpenError()) return false; d->cleanup(); setSelect(false); TInt res = d->stmt.Prepare(d->access, qt_QString2TPtrC(query)); if (res != KErrNone) { setLastError(qMakeError(d->access, QCoreApplication::translate("QSymSQLResult", "Unable to execute statement"), QSqlError::StatementError, res)); d->finalize(); return false; } d->prepareCalled = true; return true; }
QString QDesktopServices::displayName(StandardLocation type) { QString ret; #ifdef Q_WS_S60 QString rawPath = storageLocation(type); TRAPD(err, QT_TRYCATCH_LEAVING( CDirectoryLocalizer* localizer = CDirectoryLocalizer::NewL(); CleanupStack::PushL(localizer); localizer->SetFullPath(qt_QString2TPtrC(QDir::toNativeSeparators(rawPath))); if (localizer->IsLocalized()) { TPtrC locName(localizer->LocalizedName()); ret = qt_TDesC2QString(locName); } CleanupStack::PopAndDestroy(localizer); ) ) if (err != KErrNone)
//static bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data) { QString targetpath = absoluteName(entry).nativeFilePath(); TUint setmask = 0; TUint clearmask = 0; RFs& fs(qt_s60GetRFs()); if (permissions & (QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) clearmask = KEntryAttReadOnly; //if anyone can write, it's not read-only else setmask = KEntryAttReadOnly; TInt err = fs.SetAtt(qt_QString2TPtrC(targetpath), setmask, clearmask); if (data && !err) { data->entryFlags &= ~QFileSystemMetaData::Permissions; data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions)); data->knownFlagsMask |= QFileSystemMetaData::Permissions; } if (err == KErrNone) return true; error = QSystemError(err, QSystemError::NativeError); return false; }
//static bool QFileSystemEngine::createDirectory(const QFileSystemEntry &entry, bool createParents) { QString abspath = absoluteName(entry).nativeFilePath(); if (!abspath.endsWith(QLatin1Char('\\'))) abspath.append(QLatin1Char('\\')); TInt r; TPtrC symPath(qt_QString2TPtrC(abspath)); if (createParents) r = qt_s60GetRFs().MkDirAll(symPath); else r = qt_s60GetRFs().MkDir(symPath); if (createParents && r == KErrAlreadyExists) return true; //# Qt5 - QDir::mkdir returns false for existing dir, QDir::mkpath returns true (should be made consistent in Qt 5) if (createParents && r == KErrPermissionDenied) { // check for already exists, which is not returned from RFs when it denies permission TEntry entry; if (qt_s60GetRFs().Entry(symPath, entry) == KErrNone) r = KErrNone; } return (r == KErrNone); }
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */) { // Grab a pointer to the memory block if (!chunk.Handle()) { if (!handle()) return false; TPtrC ptr(qt_QString2TPtrC(nativeKey)); TInt err = KErrNoMemory; err = chunk.OpenGlobal(ptr, false); if (err != KErrNone) { setErrorString(QLatin1String("QSharedMemory::attach"), err); return false; } } size = chunk.Size(); memory = chunk.Base(); return true; }
bool QFSFileEngine::setSize(qint64 size) { Q_D(QFSFileEngine); bool ret = false; TInt err = KErrNone; if (d->symbianFile.SubSessionHandle()) { TInt err = d->symbianFile.SetSize(size); ret = (err == KErrNone); if (ret && d->symbianFilePos > size) d->symbianFilePos = size; } else if (d->fd != -1) ret = QT_FTRUNCATE(d->fd, size) == 0; else if (d->fh) ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; else { RFile tmp; QString symbianFilename(d->fileEntry.nativeFilePath()); err = tmp.Open(qt_s60GetRFs(), qt_QString2TPtrC(symbianFilename), EFileWrite); if (err == KErrNone) { err = tmp.SetSize(size); tmp.Close(); } ret = (err == KErrNone); } if (!ret) { QSystemError error; if (err) error = QSystemError(err, QSystemError::NativeError); else error = QSystemError(errno, QSystemError::StandardLibraryError); setError(QFile::ResizeError, error.toString()); } return ret; }
//static bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &entry) { QFileSystemMetaData meta; QFileSystemEntry absname = absoluteName(entry); fillMetaData(absname, meta, QFileSystemMetaData::ExistsAttribute | QFileSystemMetaData::DirectoryType); if(!(meta.exists() && meta.isDirectory())) return false; RFs& fs = qt_s60GetRFs(); QString abspath = absname.nativeFilePath(); if(!abspath.endsWith(QLatin1Char('\\'))) abspath.append(QLatin1Char('\\')); TInt r = fs.SetSessionPath(qt_QString2TPtrC(abspath)); //SetSessionPath succeeds for non existent directory, which is why it's checked above if (r == KErrNone) { __ASSERT_COMPILE(sizeof(wchar_t) == sizeof(unsigned short)); //attempt to set open C to the same path r = ::wchdir(reinterpret_cast<const wchar_t *>(absname.filePath().utf16())); if (r < 0) qWarning("failed to sync path to open C"); return true; } return false; }
//static bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what) { if (what & QFileSystemMetaData::SymbianTEntryFlags) { RFs& fs(qt_s60GetRFs()); TInt err; QFileSystemEntry absentry(absoluteName(entry)); if (entry.isEmpty()) { err = KErrNotFound; } else if (absentry.isRoot()) { //Root directories don't have an entry, and Entry() returns KErrBadName. //Therefore get information about the volume instead. TInt drive; err = RFs::CharToDrive(TChar(absentry.nativeFilePath().at(0).unicode()), drive); if (!err) { TVolumeInfo info; err = fs.Volume(info, drive); if (!err) data.fillFromVolumeInfo(info); } } else { TEntry ent; err = fs.Entry(qt_QString2TPtrC(absentry.nativeFilePath()), ent); if (!err) data.fillFromTEntry(ent); } if (err) { data.size_ = 0; data.modificationTime_ = TTime(0); data.entryFlags &= ~(QFileSystemMetaData::SymbianTEntryFlags); } //files in /sys/bin on any drive are executable, even though we don't normally have permission to check whether they exist or not if(absentry.filePath().midRef(1,10).compare(QLatin1String(":/sys/bin/"), Qt::CaseInsensitive) == 0) data.entryFlags |= QFileSystemMetaData::ExecutePermissions; } return data.hasFlags(what); }
static void handleMailtoSchemeLX(const QUrl &url) { // this function has many intermingled leaves and throws. Qt and Symbian objects do not have // destructor dependencies, and cleanup object is used to prevent cleanup stack dependency on stack. QString recipient = url.path(); QString subject = url.queryItemValue(QLatin1String("subject")); QString body = url.queryItemValue(QLatin1String("body")); QString to = url.queryItemValue(QLatin1String("to")); QString cc = url.queryItemValue(QLatin1String("cc")); QString bcc = url.queryItemValue(QLatin1String("bcc")); // these fields might have comma separated addresses QStringList recipients = recipient.split(QLatin1String(","), QString::SkipEmptyParts); QStringList tos = to.split(QLatin1String(","), QString::SkipEmptyParts); QStringList ccs = cc.split(QLatin1String(","), QString::SkipEmptyParts); QStringList bccs = bcc.split(QLatin1String(","), QString::SkipEmptyParts); RSendAs sendAs; User::LeaveIfError(sendAs.Connect()); QAutoClose<RSendAs> sendAsCleanup(sendAs); CSendAsAccounts* accounts = CSendAsAccounts::NewL(); CleanupStack::PushL(accounts); sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts); TInt count = accounts->Count(); CleanupStack::PopAndDestroy(accounts); if(!count) { // TODO: Task 259192: We should try to create account if count == 0 // CSendUi would provide account creation service for us, but it requires ridicilous // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData User::Leave(KErrNotSupported); } else { RSendAsMessage sendAsMessage; sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP); QAutoClose<RSendAsMessage> sendAsMessageCleanup(sendAsMessage); // Subject sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject)); // Body sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body)); // To foreach(QString item, recipients) sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo); foreach(QString item, tos) sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo); // Cc foreach(QString item, ccs) sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc); // Bcc foreach(QString item, bccs) sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc); // send the message sendAsMessage.LaunchEditorAndCloseL(); // sendAsMessage is already closed sendAsMessageCleanup.Forget(); } }
/*! \internal */ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) { Q_Q(QFSFileEngine); fh = 0; fd = -1; QString fn(QFileSystemEngine::absoluteName(fileEntry).nativeFilePath()); RFs& fs = qt_s60GetRFs(); TUint symbianMode = 0; if(openMode & QIODevice::ReadOnly) symbianMode |= EFileRead; if(openMode & QIODevice::WriteOnly) symbianMode |= EFileWrite; if(openMode & QIODevice::Text) symbianMode |= EFileStreamText; if (openMode & QFile::Unbuffered) { if (openMode & QIODevice::WriteOnly) symbianMode |= 0x00001000; //EFileWriteDirectIO; // ### Unbuffered read is not used, because it prevents file open in /resource // ### and has no obvious benefits } else { if (openMode & QIODevice::WriteOnly) symbianMode |= 0x00000800; //EFileWriteBuffered; // use implementation defaults for read buffering } // Until Qt supports file sharing, we can't support EFileShareReadersOrWriters safely, // but Qt does this on other platforms and autotests rely on it. // The reason is that Unix locks are only advisory - the application needs to test the // lock after opening the file. Symbian and Windows locks are mandatory - opening a // locked file will fail. symbianMode |= EFileShareReadersOrWriters; TInt r; //note QIODevice::Truncate only has meaning for read/write access //write-only files are always truncated unless append is specified //reference openModeToOpenFlags in qfsfileengine_unix.cpp if ((openMode & QIODevice::Truncate) || (!(openMode & QIODevice::ReadOnly) && !(openMode & QIODevice::Append))) { r = symbianFile.Replace(fs, qt_QString2TPtrC(fn), symbianMode); } else { r = symbianFile.Open(fs, qt_QString2TPtrC(fn), symbianMode); if (r == KErrNotFound && (openMode & QIODevice::WriteOnly)) { r = symbianFile.Create(fs, qt_QString2TPtrC(fn), symbianMode); } } if (r == KErrNone) { #ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API TInt64 size; #else TInt size; #endif r = symbianFile.Size(size); if (r==KErrNone) { if (openMode & QIODevice::Append) symbianFilePos = size; else symbianFilePos = 0; //TODO: port this (QFileSystemMetaData in open?) //cachedSize = size; } } if (r != KErrNone) { q->setError(QFile::OpenError, QSystemError(r, QSystemError::NativeError).toString()); symbianFile.Close(); return false; } closeFileHandle = true; return true; }
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags) { Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QIODevice::NotOpen) { q->setError(QFile::PermissionsError, qt_error_string(int(EACCES))); return 0; } if (offset < 0 || offset != qint64(QT_OFF_T(offset)) || size < 0 || quint64(size) > quint64(size_t(-1))) { q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); return 0; } // If we know the mapping will extend beyond EOF, fail early to avoid // undefined behavior. Otherwise, let mmap have its say. if (doStat(QFileSystemMetaData::SizeAttribute) && (QT_OFF_T(size) > metaData.size() - QT_OFF_T(offset))) qWarning("QFSFileEngine::map: Mapping a file beyond its size is not portable"); int access = 0; if (openMode & QIODevice::ReadOnly) access |= PROT_READ; if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE; #if defined(Q_OS_INTEGRITY) int pageSize = sysconf(_SC_PAGESIZE); #else int pageSize = getpagesize(); #endif int extra = offset % pageSize; if (quint64(size + extra) > quint64((size_t)-1)) { q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); return 0; } size_t realSize = (size_t)size + extra; QT_OFF_T realOffset = QT_OFF_T(offset); realOffset &= ~(QT_OFF_T(pageSize - 1)); #ifdef QT_SYMBIAN_USE_NATIVE_FILEMAP TInt nativeMapError = KErrNone; RFileMap mapping; TUint mode(EFileMapRemovableMedia); TUint64 nativeOffset = offset & ~(mapping.PageSizeInBytes() - 1); //If the file was opened for write or read/write, then open the map for read/write if (openMode & QIODevice::WriteOnly) mode |= EFileMapWrite; if (symbianFile.SubSessionHandle()) { nativeMapError = mapping.Open(symbianFile, nativeOffset, size, mode); } else { //map file by name if we don't have a native handle QString fn = QFileSystemEngine::absoluteName(fileEntry).nativeFilePath(); TUint filemode = EFileShareReadersOrWriters | EFileRead; if (openMode & QIODevice::WriteOnly) filemode |= EFileWrite; nativeMapError = mapping.Open(qt_s60GetRFs(), qt_QString2TPtrC(fn), filemode, nativeOffset, size, mode); } if (nativeMapError == KErrNone) { QScopedResource<RFileMap> ptr(mapping); //will call Close if adding to mapping throws an exception uchar *address = mapping.Base() + (offset - nativeOffset); maps[address] = mapping; ptr.take(); return address; } QFile::FileError reportedError = QFile::UnspecifiedError; switch (nativeMapError) { case KErrAccessDenied: case KErrPermissionDenied: reportedError = QFile::PermissionsError; break; case KErrNoMemory: reportedError = QFile::ResourceError; break; } q->setError(reportedError, QSystemError(nativeMapError, QSystemError::NativeError).toString()); return 0; #else #ifdef Q_OS_SYMBIAN //older phones & emulator don't support native mapping, so need to keep the open C way around for those. void *mapAddress; TRAPD(err, mapAddress = QT_MMAP((void*)0, realSize, access, MAP_SHARED, getMapHandle(), realOffset)); if (err != KErrNone) { qWarning("OpenC bug: leave from mmap %d", err); mapAddress = MAP_FAILED; errno = EINVAL; } #else void *mapAddress = QT_MMAP((void*)0, realSize, access, MAP_SHARED, nativeHandle(), realOffset); #endif if (MAP_FAILED != mapAddress) { uchar *address = extra + static_cast<uchar*>(mapAddress); maps[address] = QPair<int,size_t>(extra, realSize); return address; } switch(errno) { case EBADF: q->setError(QFile::PermissionsError, qt_error_string(int(EACCES))); break; case ENFILE: case ENOMEM: q->setError(QFile::ResourceError, qt_error_string(int(errno))); break; case EINVAL: // size are out of bounds default: q->setError(QFile::UnspecifiedError, qt_error_string(int(errno))); break; } return 0; #endif }