//static
bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
    if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
        return true;
    error = QSystemError(errno, QSystemError::StandardLibraryError);
    return false;
}
//static
bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data)
{
    mode_t mode = 0;
    if (permissions & (QFile::ReadOwner | QFile::ReadUser))
        mode |= S_IRUSR;
    if (permissions & (QFile::WriteOwner | QFile::WriteUser))
        mode |= S_IWUSR;
    if (permissions & (QFile::ExeOwner | QFile::ExeUser))
        mode |= S_IXUSR;
    if (permissions & QFile::ReadGroup)
        mode |= S_IRGRP;
    if (permissions & QFile::WriteGroup)
        mode |= S_IWGRP;
    if (permissions & QFile::ExeGroup)
        mode |= S_IXGRP;
    if (permissions & QFile::ReadOther)
        mode |= S_IROTH;
    if (permissions & QFile::WriteOther)
        mode |= S_IWOTH;
    if (permissions & QFile::ExeOther)
        mode |= S_IXOTH;

    bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0;
    if (success && data) {
        data->entryFlags &= ~QFileSystemMetaData::Permissions;
        data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions));
        data->knownFlagsMask |= QFileSystemMetaData::Permissions;
    }
    if (!success)
        error = QSystemError(errno, QSystemError::StandardLibraryError);
    return success;
}
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
    Q_UNUSED(source);
    Q_UNUSED(target);
    error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
    return false;
}
bool QFSFileEnginePrivate::unmap(uchar *ptr)
{
#if !defined(Q_OS_INTEGRITY)
    Q_Q(QFSFileEngine);
    if (!maps.contains(ptr)) {
        q->setError(QFile::PermissionsError, qt_error_string(EACCES));
        return false;
    }

#ifdef QT_SYMBIAN_USE_NATIVE_FILEMAP
    RFileMap mapping = maps.value(ptr);
    TInt err = mapping.Flush();
    mapping.Close();
    maps.remove(ptr);
    if (err) {
        q->setError(QFile::WriteError, QSystemError(err, QSystemError::NativeError).toString());
        return false;
    }
    return true;
#else
    uchar *start = ptr - maps[ptr].first;
    size_t len = maps[ptr].second;
    if (-1 == munmap(start, len)) {
        q->setError(QFile::UnspecifiedError, qt_error_string(errno));
        return false;
    }
    maps.remove(ptr);
    return true;
#endif
#else
    return false;
#endif
}
//static
bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
    Q_UNUSED(source)
    Q_UNUSED(target)
    error = QSystemError(KErrNotSupported, QSystemError::NativeError);
    return false;
}
//static
bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
{
    if (unlink(entry.nativeFilePath().constData()) == 0)
        return true;
    error = QSystemError(errno, QSystemError::StandardLibraryError);
    return false;

}
/*!
    Opens the file descriptor specified by \a file in the mode given by
    \a openMode. Returns true on success; otherwise returns false.

    The \a handleFlags argument specifies whether the file handle will be
    closed by Qt. See the QFile::FileHandleFlags documentation for more
    information.
*/
bool QFSFileEngine::open(QIODevice::OpenMode openMode, const RFile &file, QFile::FileHandleFlags handleFlags)
{
    Q_D(QFSFileEngine);

    // Append implies WriteOnly.
    if (openMode & QFile::Append)
        openMode |= QFile::WriteOnly;

    // WriteOnly implies Truncate if neither ReadOnly nor Append are sent.
    if ((openMode & QFile::WriteOnly) && !(openMode & (QFile::ReadOnly | QFile::Append)))
        openMode |= QFile::Truncate;

    d->openMode = openMode;
    d->lastFlushFailed = false;
    d->closeFileHandle = (handleFlags & QFile::AutoCloseHandle);
    d->fileEntry.clear();
    d->fh = 0;
    d->fd = -1;
    d->tried_stat = 0;

#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
    //RFile64 adds only functions to RFile, no data members
    d->symbianFile = static_cast<const RFile64&>(file);
#else
    d->symbianFile = file;
#endif
    TInt ret;
    d->symbianFilePos = 0;
    if (openMode & QFile::Append) {
        // Seek to the end when in Append mode.
        ret = d->symbianFile.Size(d->symbianFilePos);
    } else {
        // Seek to current otherwise
        ret = d->symbianFile.Seek(ESeekCurrent, d->symbianFilePos);
    }

    if (ret != KErrNone) {
        setError(QFile::OpenError, QSystemError(ret, QSystemError::NativeError).toString());

        d->openMode = QIODevice::NotOpen;
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
        d->symbianFile = RFile64();
#else
        d->symbianFile = RFile();
#endif
        return false;
    }

    // Extract filename (best effort)
    TFileName fn;
    TInt err = d->symbianFile.FullName(fn);
    if (err == KErrNone)
        d->fileEntry = QFileSystemEntry(qt_TDesC2QString(fn), QFileSystemEntry::FromNativePath());
    else
        d->fileEntry.clear();

    return true;
}
//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;
}
//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::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;
}
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;
}
qint64 QFSFileEnginePrivate::nativeSize() const
{
#ifdef Q_OS_SYMBIAN
    const Q_Q(QFSFileEngine);
    if (symbianFile.SubSessionHandle()) {
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
        qint64 size;
#else
        TInt size;
#endif
        TInt err = symbianFile.Size(size);
        if(err != KErrNone) {
            const_cast<QFSFileEngine*>(q)->setError(QFile::PositionError, QSystemError(err, QSystemError::NativeError).toString());
            return 0;
        }
        return size;
    }
#endif
    return sizeFdFh();
}
Exemple #13
0
void QSymbianHostResolver::run()
{
    switch (iState) {
    case EGetByName:
        processNameResult();
        break;
    case EGetByAddress:
        processAddressResult();
        break;
    case ECompleteFromCache:
    case EError:
        returnResults();
        break;
    default:
        qWarning("QSymbianHostResolver internal error, bad state in run()");
        iResults.setError(QHostInfo::UnknownError);
        iResults.setErrorString(QSystemError(KErrCorrupt,QSystemError::NativeError).toString());
        returnResults();
    }
}
Exemple #14
0
QT_BEGIN_NAMESPACE

static void setError_helper(QHostInfo &info, TInt symbianError)
{
    switch (symbianError) {
    case KErrDndNameNotFound:
    case KErrDndAddrNotFound:
    case KErrNotFound:
    case KErrEof:
        // various "no more results" error codes
        info.setError(QHostInfo::HostNotFound);
        info.setErrorString(QObject::tr("Host not found"));
        break;
    default:
        // Unknown error
        info.setError(QHostInfo::UnknownError);
        info.setErrorString(QSystemError(symbianError, QSystemError::NativeError).toString());
        break;
    }
}
//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;
}
/*!
    \internal
*/
qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
{
#ifdef Q_OS_SYMBIAN
    Q_Q(QFSFileEngine);
    if (symbianFile.SubSessionHandle()) {
        if(len > KMaxTInt) {
            //this check is more likely to catch a corrupt length, since it isn't possible to allocate 2GB buffers (yet..)
            q->setError(QFile::WriteError, QLatin1String("Maximum 2GB in single write on this platform"));
            return -1;
        }
        const TPtrC8 ptr(reinterpret_cast<const TUint8*>(data), static_cast<TInt>(len));
#ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
        TInt64 eofpos = 0;
#else
        TInt eofpos = 0;
#endif
        //The end of file position is not cached because QFile is read/write sharable, therefore another
        //process may have altered the file size.
        TInt r = symbianFile.Seek(ESeekEnd, eofpos);
        if (r == KErrNone && symbianFilePos > eofpos) {
            //seek position is beyond end of file so file needs to be extended before write.
            //note that SetSize does not zero-initialise (c.f. posix lseek)
            r = symbianFile.SetSize(symbianFilePos);
        }
        if (r == KErrNone) {
            //write to specific position in the file (i.e. use our own cursor rather than calling seek)
            r = symbianFile.Write(symbianFilePos, ptr);
        }
        if (r != KErrNone) {
            q->setError(QFile::WriteError, QSystemError(r, QSystemError::NativeError).toString());
            return -1;
        }
        symbianFilePos += len;
        return len;
    }
#endif
    return writeFdFh(data, len);
}
bool QFSFileEngine::renameOverwrite(const QString &newName)
{
    Q_D(QFSFileEngine);
#if defined(Q_OS_WINCE)
    // Windows Embedded Compact 7 does not have MoveFileEx, simulate it with  the following sequence:
    //   1. DeleteAndRenameFile  (Should work on RAM FS when both files exist)
    //   2. DeleteFile/MoveFile  (Should work on all file systems)
    //
    // DeleteFile/MoveFile fallback implementation violates atomicity, but it is more acceptable than
    // alternative CopyFile/DeleteFile sequence for the following reasons:
    //
    //  1. DeleteFile/MoveFile is way faster than CopyFile/DeleteFile and thus more atomic.
    //  2. Given the intended use case of this function in QSaveFile, DeleteFile/MoveFile sequence will
    //     delete the old content, but leave a file "filename.ext.XXXXXX" in the same directory if MoveFile fails.
    //     With CopyFile/DeleteFile sequence, it can happen that new data is partially copied to target file
    //     (because CopyFile is not atomic either), thus leaving *some* content to target file.
    //     This makes the need for application level recovery harder to detect than in DeleteFile/MoveFile
    //     sequence where target file simply does not exist.
    //
    bool ret = ::DeleteAndRenameFile((wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(),
                                     (wchar_t*)d->fileEntry.nativeFilePath().utf16()) != 0;
    if (!ret) {
        ret = ::DeleteFile((wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16()) != 0;
        if (ret || ::GetLastError() == ERROR_FILE_NOT_FOUND)
            ret = ::MoveFile((wchar_t*)d->fileEntry.nativeFilePath().utf16(),
                             (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16()) != 0;
    }
#else
    bool ret = ::MoveFileEx((wchar_t*)d->fileEntry.nativeFilePath().utf16(),
                            (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(),
                            MOVEFILE_REPLACE_EXISTING) != 0;
#endif
    if (!ret)
        setError(QFile::RenameError, QSystemError(::GetLastError(), QSystemError::NativeError).toString());
    return ret;
}
/*!
    \internal
*/
qint64 QFSFileEnginePrivate::nativeRead(char *data, qint64 len)
{
    Q_Q(QFSFileEngine);

#ifdef Q_OS_SYMBIAN
    if (symbianFile.SubSessionHandle()) {
        if(len > KMaxTInt) {
            //this check is more likely to catch a corrupt length, since it isn't possible to allocate 2GB buffers (yet..)
            q->setError(QFile::ReadError, QLatin1String("Maximum 2GB in single read on this platform"));
            return -1;
        }
        TPtr8 ptr(reinterpret_cast<TUint8*>(data), static_cast<TInt>(len));
        TInt r = symbianFile.Read(symbianFilePos, ptr);
        if (r != KErrNone)
        {
            q->setError(QFile::ReadError, QSystemError(r, QSystemError::NativeError).toString());
            return -1;
        }
        symbianFilePos += ptr.Length();
        return qint64(ptr.Length());
    }
#endif
    if (fh && nativeIsSequential()) {
        size_t readBytes = 0;
        int oldFlags = fcntl(QT_FILENO(fh), F_GETFL);
        for (int i = 0; i < 2; ++i) {
            // Unix: Make the underlying file descriptor non-blocking
            if ((oldFlags & O_NONBLOCK) == 0)
                fcntl(QT_FILENO(fh), F_SETFL, oldFlags | O_NONBLOCK);

            // Cross platform stdlib read
            size_t read = 0;
            do {
                read = fread(data + readBytes, 1, size_t(len - readBytes), fh);
            } while (read == 0 && !feof(fh) && errno == EINTR);
            if (read > 0) {
                readBytes += read;
                break;
            } else {
                if (readBytes)
                    break;
                readBytes = read;
            }

            // Unix: Restore the blocking state of the underlying socket
            if ((oldFlags & O_NONBLOCK) == 0) {
                fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
                if (readBytes == 0) {
                    int readByte = 0;
                    do {
                        readByte = fgetc(fh);
                    } while (readByte == -1 && errno == EINTR);
                    if (readByte != -1) {
                        *data = uchar(readByte);
                        readBytes += 1;
                    } else {
                        break;
                    }
                }
            }
        }
        // Unix: Restore the blocking state of the underlying socket
        if ((oldFlags & O_NONBLOCK) == 0) {
            fcntl(QT_FILENO(fh), F_SETFL, oldFlags);
        }
        if (readBytes == 0 && !feof(fh)) {
            // if we didn't read anything and we're not at EOF, it must be an error
            q->setError(QFile::ReadError, qt_error_string(int(errno)));
            return -1;
        }
        return readBytes;
    }

    return readFdFh(data, len);
}
/*!
    \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;
}
QT_BEGIN_NAMESPACE

void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply)
{
    // Perform DNS query.
    PDNS_RECORD dns_records = 0;
    const QString requestNameUtf16 = QString::fromUtf8(requestName.data(), requestName.size());
    const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, NULL, &dns_records, NULL);
    switch (status) {
    case ERROR_SUCCESS:
        break;
    case DNS_ERROR_RCODE_FORMAT_ERROR:
        reply->error = QDnsLookup::InvalidRequestError;
        reply->errorString = tr("Server could not process query");
        return;
    case DNS_ERROR_RCODE_SERVER_FAILURE:
        reply->error = QDnsLookup::ServerFailureError;
        reply->errorString = tr("Server failure");
        return;
    case DNS_ERROR_RCODE_NAME_ERROR:
        reply->error = QDnsLookup::NotFoundError;
        reply->errorString = tr("Non existent domain");
        return;
    case DNS_ERROR_RCODE_REFUSED:
        reply->error = QDnsLookup::ServerRefusedError;
        reply->errorString = tr("Server refused to answer");
        return;
    default:
        reply->error = QDnsLookup::InvalidReplyError;
        reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
        return;
    }

    // Extract results.
    for (PDNS_RECORD ptr = dns_records; ptr != NULL; ptr = ptr->pNext) {
        const QString name = QUrl::fromAce( QString::fromWCharArray( ptr->pName ).toLatin1() );
        if (ptr->wType == QDnsLookup::A) {
            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(ntohl(ptr->Data.A.IpAddress));
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::AAAA) {
            Q_IPV6ADDR addr;
            memcpy(&addr, &ptr->Data.AAAA.Ip6Address, sizeof(Q_IPV6ADDR));

            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(addr);
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::CNAME) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Cname.pNameHost).toLatin1());
            reply->canonicalNameRecords.append(record);
        } else if (ptr->wType == QDnsLookup::MX) {
            QDnsMailExchangeRecord record;
            record.d->name = name;
            record.d->exchange = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Mx.pNameExchange).toLatin1());
            record.d->preference = ptr->Data.Mx.wPreference;
            record.d->timeToLive = ptr->dwTtl;
            reply->mailExchangeRecords.append(record);
        } else if (ptr->wType == QDnsLookup::NS) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ns.pNameHost).toLatin1());
            reply->nameServerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::PTR) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ptr.pNameHost).toLatin1());
            reply->pointerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::SRV) {
            QDnsServiceRecord record;
            record.d->name = name;
            record.d->target = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Srv.pNameTarget).toLatin1());
            record.d->port = ptr->Data.Srv.wPort;
            record.d->priority = ptr->Data.Srv.wPriority;
            record.d->timeToLive = ptr->dwTtl;
            record.d->weight = ptr->Data.Srv.wWeight;
            reply->serviceRecords.append(record);
        } else if (ptr->wType == QDnsLookup::TXT) {
            QDnsTextRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            for (unsigned int i = 0; i < ptr->Data.Txt.dwStringCount; ++i) {
                record.d->values << QString::fromWCharArray((ptr->Data.Txt.pStringArray[i])).toLatin1();;
            }
            reply->textRecords.append(record);
        }
    }

    DnsRecordListFree(dns_records, DnsFreeRecordList);
}
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
}
/*!
    \internal

    Generates a unique file path and returns a native handle to the open file.
    \a path is used as a template when generating unique paths, \a pos
    identifies the position of the first character that will be replaced in the
    template and \a length the number of characters that may be substituted.

    Returns an open handle to the newly created file if successful, an invalid
    handle otherwise. In both cases, the string in \a path will be changed and
    contain the generated path name.
*/
static bool createFileFromTemplate(NativeFileHandle &file,
        QFileSystemEntry::NativePath &path, size_t pos, size_t length,
        QSystemError &error)
{
    Q_ASSERT(length != 0);
    Q_ASSERT(pos < size_t(path.length()));
    Q_ASSERT(length <= size_t(path.length()) - pos);

    Char *const placeholderStart = (Char *)path.data() + pos;
    Char *const placeholderEnd = placeholderStart + length;

    // Initialize placeholder with random chars + PID.
    {
        Char *rIter = placeholderEnd;

#if defined(QT_BUILD_CORE_LIB)
        quint64 pid = quint64(QCoreApplication::applicationPid());
        do {
            *--rIter = Latin1Char((pid % 10) + '0');
            pid /= 10;
        } while (rIter != placeholderStart && pid != 0);
#endif

        while (rIter != placeholderStart) {
            char ch = char((qrand() & 0xffff) % (26 + 26));
            if (ch < 26)
                *--rIter = Latin1Char(ch + 'A');
            else
                *--rIter = Latin1Char(ch - 26 + 'a');
        }
    }

    for (;;) {
        // Atomically create file and obtain handle
#if defined(Q_OS_WIN)
#  ifndef Q_OS_WINRT
        file = CreateFile((const wchar_t *)path.constData(),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW,
                FILE_ATTRIBUTE_NORMAL, NULL);
#  else // !Q_OS_WINRT
        file = CreateFile2((const wchar_t *)path.constData(),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, CREATE_NEW,
                NULL);
#  endif // Q_OS_WINRT

        if (file != INVALID_HANDLE_VALUE)
            return true;

        DWORD err = GetLastError();
        if (err == ERROR_ACCESS_DENIED) {
            WIN32_FILE_ATTRIBUTE_DATA attributes;
            if (!GetFileAttributesEx((const wchar_t *)path.constData(),
                                     GetFileExInfoStandard, &attributes)
                    || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
                // Potential write error (read-only parent directory, etc.).
                error = QSystemError(err, QSystemError::NativeError);
                return false;
            } // else file already exists as a directory.
        } else if (err != ERROR_FILE_EXISTS) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#else // POSIX
        file = QT_OPEN(path.constData(),
                QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
                0600);

        if (file != -1)
            return true;

        int err = errno;
        if (err != EEXIST) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#endif

        /* tricky little algorwwithm for backward compatibility */
        for (Char *iter = placeholderStart;;) {
            // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
            // String progression: "ZZaiC" => "aabiC"
            switch (char(*iter)) {
                case 'Z':
                    // Rollover, advance next character
                    *iter = Latin1Char('a');
                    if (++iter == placeholderEnd) {
                        // Out of alternatives. Return file exists error, previously set.
                        error = QSystemError(err, QSystemError::NativeError);
                        return false;
                    }

                    continue;

                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                    *iter = Latin1Char('a');
                    break;

                case 'z':
                    // increment 'z' to 'A'
                    *iter = Latin1Char('A');
                    break;

                default:
                    ++*iter;
                    break;
            }
            break;
        }
    }

    Q_ASSERT(false);
}
QT_BEGIN_NAMESPACE

void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply)
{
    // Perform DNS query.
    PDNS_RECORD dns_records = 0;
    const QString requestNameUtf16 = QString::fromUtf8(requestName.data(), requestName.size());
    IP4_ARRAY srvList;
    memset(&srvList, 0, sizeof(IP4_ARRAY));
    if (!nameserver.isNull()) {
        if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) {
            // The below code is referenced from: http://support.microsoft.com/kb/831226
            srvList.AddrCount = 1;
            srvList.AddrArray[0] = htonl(nameserver.toIPv4Address());
        } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) {
            // For supoprting IPv6 nameserver addresses, we'll need to switch
            // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
            // address in the nameserver list
            qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported";
            reply->error = QDnsLookup::ResolverError;
            reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
            return;
        }
    }
    const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, &srvList, &dns_records, NULL);
    switch (status) {
    case ERROR_SUCCESS:
        break;
    case DNS_ERROR_RCODE_FORMAT_ERROR:
        reply->error = QDnsLookup::InvalidRequestError;
        reply->errorString = tr("Server could not process query");
        return;
    case DNS_ERROR_RCODE_SERVER_FAILURE:
        reply->error = QDnsLookup::ServerFailureError;
        reply->errorString = tr("Server failure");
        return;
    case DNS_ERROR_RCODE_NAME_ERROR:
        reply->error = QDnsLookup::NotFoundError;
        reply->errorString = tr("Non existent domain");
        return;
    case DNS_ERROR_RCODE_REFUSED:
        reply->error = QDnsLookup::ServerRefusedError;
        reply->errorString = tr("Server refused to answer");
        return;
    default:
        reply->error = QDnsLookup::InvalidReplyError;
        reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
        return;
    }

    // Extract results.
    for (PDNS_RECORD ptr = dns_records; ptr != NULL; ptr = ptr->pNext) {
        const QString name = QUrl::fromAce( QString::fromWCharArray( ptr->pName ).toLatin1() );
        if (ptr->wType == QDnsLookup::A) {
            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(ntohl(ptr->Data.A.IpAddress));
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::AAAA) {
            Q_IPV6ADDR addr;
            memcpy(&addr, &ptr->Data.AAAA.Ip6Address, sizeof(Q_IPV6ADDR));

            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(addr);
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::CNAME) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Cname.pNameHost).toLatin1());
            reply->canonicalNameRecords.append(record);
        } else if (ptr->wType == QDnsLookup::MX) {
            QDnsMailExchangeRecord record;
            record.d->name = name;
            record.d->exchange = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Mx.pNameExchange).toLatin1());
            record.d->preference = ptr->Data.Mx.wPreference;
            record.d->timeToLive = ptr->dwTtl;
            reply->mailExchangeRecords.append(record);
        } else if (ptr->wType == QDnsLookup::NS) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ns.pNameHost).toLatin1());
            reply->nameServerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::PTR) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ptr.pNameHost).toLatin1());
            reply->pointerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::SRV) {
            QDnsServiceRecord record;
            record.d->name = name;
            record.d->target = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Srv.pNameTarget).toLatin1());
            record.d->port = ptr->Data.Srv.wPort;
            record.d->priority = ptr->Data.Srv.wPriority;
            record.d->timeToLive = ptr->dwTtl;
            record.d->weight = ptr->Data.Srv.wWeight;
            reply->serviceRecords.append(record);
        } else if (ptr->wType == QDnsLookup::TXT) {
            QDnsTextRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            for (unsigned int i = 0; i < ptr->Data.Txt.dwStringCount; ++i) {
                record.d->values << QString::fromWCharArray((ptr->Data.Txt.pStringArray[i])).toLatin1();;
            }
            reply->textRecords.append(record);
        }
    }

    DnsRecordListFree(dns_records, DnsFreeRecordList);
}
Exemple #24
0
/*!
    \internal

    Generates a unique file path and returns a native handle to the open file.
    \a path is used as a template when generating unique paths, \a pos
    identifies the position of the first character that will be replaced in the
    template and \a length the number of characters that may be substituted.

    Returns an open handle to the newly created file if successful, an invalid
    handle otherwise. In both cases, the string in \a path will be changed and
    contain the generated path name.
*/
static bool createFileFromTemplate(NativeFileHandle &file,
        QFileSystemEntry::NativePath &path, size_t pos, size_t length,
        QSystemError &error)
{
    Q_ASSERT(length != 0);
    Q_ASSERT(pos < size_t(path.length()));
    Q_ASSERT(length <= size_t(path.length()) - pos);

    Char *const placeholderStart = (Char *)path.data() + pos;
    Char *const placeholderEnd = placeholderStart + length;

    // Initialize placeholder with random chars + PID.
    {
        Char *rIter = placeholderEnd;

#if defined(QT_BUILD_CORE_LIB)
        quint64 pid = quint64(QCoreApplication::applicationPid());
        do {
            *--rIter = Latin1Char((pid % 10) + '0');
            pid /= 10;
        } while (rIter != placeholderStart && pid != 0);
#endif

        while (rIter != placeholderStart) {
            char ch = char((qrand() & 0xffff) % (26 + 26));
            if (ch < 26)
                *--rIter = Latin1Char(ch + 'A');
            else
                *--rIter = Latin1Char(ch - 26 + 'a');
        }
    }

#ifdef Q_OS_SYMBIAN
    RFs& fs = qt_s60GetRFs();
#endif

    for (;;) {
        // Atomically create file and obtain handle
#if defined(Q_OS_WIN)
        file = CreateFile((const wchar_t *)path.constData(),
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW,
                FILE_ATTRIBUTE_NORMAL, NULL);

        if (file != INVALID_HANDLE_VALUE)
            return true;

        DWORD err = GetLastError();
        if (err != ERROR_FILE_EXISTS) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#elif defined(Q_OS_SYMBIAN)
        TInt err = file.Create(fs, qt_QString2TPtrC(path),
                EFileRead | EFileWrite | EFileShareReadersOrWriters);

        if (err == KErrNone)
            return true;

        if (err != KErrAlreadyExists) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#else // POSIX
        file = QT_OPEN(path.constData(),
                QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
                0600);

        if (file != -1)
            return true;

        int err = errno;
        if (err != EEXIST) {
            error = QSystemError(err, QSystemError::NativeError);
            return false;
        }
#endif

        /* tricky little algorwwithm for backward compatibility */
        for (Char *iter = placeholderStart;;) {
            // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
            // String progression: "ZZaiC" => "aabiC"
            switch (char(*iter)) {
                case 'Z':
                    // Rollover, advance next character
                    *iter = Latin1Char('a');
                    if (++iter == placeholderEnd) {
                        // Out of alternatives. Return file exists error, previously set.
                        error = QSystemError(err, QSystemError::NativeError);
                        return false;
                    }

                    continue;

                case '0': case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                    *iter = Latin1Char('a');
                    break;

                case 'z':
                    // increment 'z' to 'A'
                    *iter = Latin1Char('A');
                    break;

                default:
                    ++*iter;
                    break;
            }
            break;
        }
    }

    Q_ASSERT(false);
}