Example #1
0
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
{
    const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));

    const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
    const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);

#ifdef O_CLOEXEC
    // First try with O_CLOEXEC flag, if that fails, fall back to normal flags
    EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag | O_CLOEXEC, omode));
    if (hand == -1)
        EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
#else
    EINTR_LOOP(hand, ::shm_open(shmName.constData(), oflag, omode));
#endif
    if (hand == -1) {
        const int errorNumber = errno;
        const QLatin1String function("QSharedMemory::attach (shm_open)");
        switch (errorNumber) {
        case ENAMETOOLONG:
        case EINVAL:
            errorString = QSharedMemory::tr("%1: bad name").arg(function);
            error = QSharedMemory::KeyError;
            break;
        default:
            setErrorString(function);
        }
        hand = -1;
        return false;
    }

    // grab the size
    QT_STATBUF st;
    if (QT_FSTAT(hand, &st) == -1) {
        setErrorString(QLatin1String("QSharedMemory::attach (fstat)"));
        cleanHandle();
        return false;
    }
    size = st.st_size;

    // grab the memory
    const int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE);
    memory = QT_MMAP(0, size, mprot, MAP_SHARED, hand, 0);
    if (memory == MAP_FAILED || !memory) {
        setErrorString(QLatin1String("QSharedMemory::attach (mmap)"));
        cleanHandle();
        memory = 0;
        size = 0;
        return false;
    }

#ifdef F_ADD_SEALS
    // Make sure the shared memory region will not shrink
    // otherwise someone could cause SIGBUS on us.
    // (see http://lwn.net/Articles/594919/)
    fcntl(hand, F_ADD_SEALS, F_SEAL_SHRINK);
#endif

    return true;
}
Example #2
0
void QWSSharedMemory::detach()
{
#ifndef QT_POSIX_IPC
    if (shmBase && shmBase != (void*)-1)
        shmdt(shmBase);
#else
    if (shmBase && shmBase != (void*)-1)
        munmap(shmBase, shmSize);
    if (hand > 0) {
        // get the number of current attachments
        int shm_nattch = 0;
        QT_STATBUF st;
        if (QT_FSTAT(hand, &st) == 0) {
            // subtract 2 from linkcount: one for our own open and one for the dir entry
            shm_nattch = st.st_nlink - 2;
        }
        qt_safe_close(hand);
        // if there are no attachments then unlink the shared memory
        if (shm_nattch == 0) {
            QByteArray shmName = makeKey(shmId);
            shm_unlink(shmName.constData());
        }
    }
#endif
    shmBase = 0;
    shmSize = 0;
    shmId = -1;
}
bool QFSFileEnginePrivate::doStat() const
{
    if (tried_stat == 0) {
        QFSFileEnginePrivate *that = const_cast<QFSFileEnginePrivate*>(this);
        if (fh && nativeFilePath.isEmpty()) {
            // ### actually covers two cases: d->fh and when the file is not open
            that->could_stat = (QT_FSTAT(fileno(fh), &st) == 0);
        } else if (fd == -1) {
            // ### actually covers two cases: d->fh and when the file is not open
            that->could_stat = (QT_STAT(nativeFilePath.constData(), &st) == 0);
        } else {
            that->could_stat = (QT_FSTAT(fd, &st) == 0);
        }
	that->tried_stat = 1;
    }
    return could_stat;
}
Example #4
0
bool QWSSharedMemory::create(int size)
{
    if (shmId != -1)
        detach();

#ifndef QT_POSIX_IPC
    shmId = shmget(IPC_PRIVATE, size, IPC_CREAT | 0600);
#else
    // ### generate really unique IDs
    shmId = (getpid() << 16) + (localUniqueId.fetchAndAddRelaxed(1) % ushort(-1));
    QByteArray shmName = makeKey(shmId);
    EINTR_LOOP(hand, shm_open(shmName.constData(), O_RDWR | O_CREAT, 0660));
    if (hand != -1) {
        // the size may only be set once; ignore errors
        int ret;
        EINTR_LOOP(ret, ftruncate(hand, size));
        if (ret == -1)
            shmId = -1;
    } else {
        shmId = -1;
    }
#endif
    if (shmId == -1) {
#ifdef QT_SHM_DEBUG
        perror("QWSSharedMemory::create():");
        qWarning("Error allocating shared memory of size %d", size);
#endif
        detach();
        return false;
    }

#ifndef QT_POSIX_IPC
    shmBase = shmat(shmId, 0, 0);
    // On Linux, it is possible to attach a shared memory segment even if it
    // is already marked to be deleted. However, POSIX.1-2001 does not specify
    // this behaviour and many other implementations do not support it.
    shmctl(shmId, IPC_RMID, 0);
#else
    // grab the size
    QT_STATBUF st;
    if (QT_FSTAT(hand, &st) != -1) {
        shmSize = st.st_size;
        // grab the memory
        shmBase = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, hand, 0);
    }
#endif
    if (shmBase == (void*)-1 || !shmBase) {
#ifdef QT_SHM_DEBUG
        perror("QWSSharedMemory::create():");
        qWarning("Error attaching to shared memory id %d", shmId);
#endif
        detach();
        return false;
    }

    return true;
}
Example #5
0
/*!
    \internal
*/
qint64 QFSFileEnginePrivate::sizeFdFh() const
{
    Q_Q(const QFSFileEngine);
    // ### Fix this function, it should not stat unless the file is closed.
    QT_STATBUF st;
    int ret = 0;
    const_cast<QFSFileEngine *>(q)->flush();
    if (fh && nativeFilePath.isEmpty()) {
        // Buffered stdlib mode.
        // ### This should really be an ftell
        ret = QT_FSTAT(QT_FILENO(fh), &st);
    } else if (fd == -1) {
        // Stateless stat.
        ret = QT_STAT(nativeFilePath.constData(), &st);
    } else {
        // Unbuffered stdio mode.
        ret = QT_FSTAT(fd, &st);
    }
    if (ret == -1)
        return 0;
    return st.st_size;
}
//static
bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
{
    data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
    data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;

    QT_STATBUF statBuffer;
    if (QT_FSTAT(fd, &statBuffer) == 0) {
        data.fillFromStatBuf(statBuffer);
        return true;
    }

    return false;
}
Example #7
0
bool QSharedMemoryPrivate::detach()
{
    // detach from the memory segment
    if (::munmap(memory, size) == -1) {
        setErrorString(QLatin1String("QSharedMemory::detach (munmap)"));
        return false;
    }
    memory = 0;
    size = 0;

#ifdef Q_OS_QNX
    // On QNX the st_nlink field of struct stat contains the number of
    // active shm_open() connections to the shared memory file, so we
    // can use it to automatically clean up the file once the last
    // user has detached from it.

    // get the number of current attachments
    int shm_nattch = 0;
    QT_STATBUF st;
    if (QT_FSTAT(hand, &st) == 0) {
        // subtract 2 from linkcount: one for our own open and one for the dir entry
        shm_nattch = st.st_nlink - 2;
    }

    cleanHandle();

    // if there are no attachments then unlink the shared memory
    if (shm_nattch == 0) {
        const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
        if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
            setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)"));
    }
#else
    // On non-QNX systems (tested Linux and Haiku), the st_nlink field is always 1,
    // so we'll simply leak the shared memory files.
    cleanHandle();
#endif

    return true;
}
Example #8
0
bool QWSSharedMemory::attach(int id)
{
    if (shmId == id)
        return id != -1;

    detach();

    if (id == -1)
        return false;

    shmId = id;
#ifndef QT_POSIX_IPC
    shmBase = shmat(shmId, 0, 0);
#else
    QByteArray shmName = makeKey(shmId);
    EINTR_LOOP(hand, shm_open(shmName.constData(), O_RDWR, 0660));
    if (hand != -1) {
        // grab the size
        QT_STATBUF st;
        if (QT_FSTAT(hand, &st) != -1) {
            shmSize = st.st_size;
            // grab the memory
            shmBase = mmap(0, shmSize, PROT_READ | PROT_WRITE, MAP_SHARED, hand, 0);
        }
    }
#endif
    if (shmBase == (void*)-1 || !shmBase) {
#ifdef QT_SHM_DEBUG
        perror("QWSSharedMemory::attach():");
        qWarning("Error attaching to shared memory id %d", shmId);
#endif
        detach();
        return false;
    }

    return true;
}
Example #9
0
    bool registerSelf(const QString &f) {
        bool fromMM = false;
        uchar *data = 0;
        unsigned int data_len = 0;

#ifdef QT_USE_MMAP

#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif

        int fd = QT_OPEN(QFile::encodeName(f), O_RDONLY,
#if defined(Q_OS_WIN)
                         _S_IREAD | _S_IWRITE
#else
                         0666
#endif
            );
        if (fd >= 0) {
            QT_STATBUF st;
            if (!QT_FSTAT(fd, &st)) {
                uchar *ptr;
                ptr = reinterpret_cast<uchar *>(
                    mmap(0, st.st_size,             // any address, whole file
                         PROT_READ,                 // read-only memory
                         MAP_FILE | MAP_PRIVATE,    // swap-backed map from file
                         fd, 0));                   // from offset 0 of fd
                if (ptr && ptr != reinterpret_cast<uchar *>(MAP_FAILED)) {
                    data = ptr;
                    data_len = st.st_size;
                    fromMM = true;
                }
            }
            ::close(fd);
        }
#endif // QT_USE_MMAP
        if(!data) {
            QFile file(f);
            if (!file.exists())
                return false;
            data_len = file.size();
            data = new uchar[data_len];

            bool ok = false;
            if (file.open(QIODevice::ReadOnly))
                ok = (data_len == (uint)file.read((char*)data, data_len));
            if (!ok) {
                delete [] data;
                data = 0;
                data_len = 0;
                return false;
            }
            fromMM = false;
        }
        if(data && QDynamicBufferResourceRoot::registerSelf(data)) {
            if(fromMM) {
                unmapPointer = data;
                unmapLength = data_len;
            }
            fileName = f;
            return true;
        }
        return false;
    }
Example #10
0
bool QTranslator::load(const QString & filename, const QString & directory,
                       const QString & search_delimiters,
                       const QString & suffix)
{
    Q_D(QTranslator);
    d->clear();

    QString prefix;
    if (QFileInfo(filename).isRelative()) {
        prefix = directory;
	if (prefix.length() && !prefix.endsWith(QLatin1Char('/')))
	    prefix += QLatin1Char('/');
    }

    QString fname = filename;
    QString realname;
    QString delims;
    delims = search_delimiters.isNull() ? QString::fromLatin1("_.") : search_delimiters;

    for (;;) {
        QFileInfo fi;

        realname = prefix + fname + (suffix.isNull() ? QString::fromLatin1(".qm") : suffix);
        fi.setFile(realname);
        if (fi.isReadable() && fi.isFile())
            break;

        realname = prefix + fname;
        fi.setFile(realname);
        if (fi.isReadable() && fi.isFile())
            break;

        int rightmost = 0;
        for (int i = 0; i < (int)delims.length(); i++) {
            int k = fname.lastIndexOf(delims[i]);
            if (k > rightmost)
                rightmost = k;
        }

        // no truncations? fail
        if (rightmost == 0)
            return false;

        fname.truncate(rightmost);
    }

    // realname is now the fully qualified name of a readable file.

    bool ok = false;

#ifdef QT_USE_MMAP

#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif

    int fd = -1;
    if (!realname.startsWith(QLatin1Char(':')))
        fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,
#if defined(Q_OS_WIN)
                     _S_IREAD | _S_IWRITE
#else
                     0666
#endif
            );
    if (fd >= 0) {
        QT_STATBUF st;
        if (!QT_FSTAT(fd, &st)) {
            char *ptr;
            ptr = reinterpret_cast<char *>(
                mmap(0, st.st_size,             // any address, whole file
                     PROT_READ,                 // read-only memory
                     MAP_FILE | MAP_PRIVATE,    // swap-backed map from file
                     fd, 0));                   // from offset 0 of fd
            if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
                d->used_mmap = true;
                d->unmapPointer = ptr;
                d->unmapLength = st.st_size;
                ok = true;
            }
        }
        ::close(fd);
    }
#endif // QT_USE_MMAP

    if (!ok) {
        QFile file(realname);
        d->unmapLength = file.size();
        if (!d->unmapLength)
            return false;
        d->unmapPointer = new char[d->unmapLength];

        if (file.open(QIODevice::ReadOnly))
            ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength));

        if (!ok) {
            delete [] d->unmapPointer;
            d->unmapPointer = 0;
            d->unmapLength = 0;
            return false;
        }
    }

    return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
}
QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEngine *fontEngine)
    : fd(fileDescriptor), renderingFontEngine(fontEngine)
{
    fontData = 0;
    dataSize = 0;
    fontDef = def;
    cache_cost = 100;
    freetype = 0;
    externalCMap = 0;
    cmapOffset = 0;
    cmapSize = 0;
    glyphMapOffset = 0;
    glyphMapEntries = 0;
    glyphDataOffset = 0;
    glyphDataSize = 0;
    kerning_pairs_loaded = false;
    readOnly = true;

#if defined(DEBUG_FONTENGINE)
    qDebug() << "QFontEngineQPF::QFontEngineQPF( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ")";
#endif

    if (fd < 0) {
        if (!renderingFontEngine)
            return;

        fileName = fontDef.family.toLower() + QLatin1String("_")
                   + QString::number(fontDef.pixelSize)
                   + QLatin1String("_") + QString::number(fontDef.weight)
                   + (fontDef.style != QFont::StyleNormal ?
                      QLatin1String("_italic") : QLatin1String(""))
                   + QLatin1String(".qsf");
        fileName.replace(QLatin1Char(' '), QLatin1Char('_'));
        fileName.prepend(qws_fontCacheDir());

        const QByteArray encodedName = QFile::encodeName(fileName);
        if (::access(encodedName, F_OK) == 0) {
#if defined(DEBUG_FONTENGINE)
            qDebug() << "found existing qpf:" << fileName;
#endif
            if (::access(encodedName, W_OK | R_OK) == 0)
                fd = ::open(encodedName, O_RDWR);
            else if (::access(encodedName, R_OK) == 0)
                fd = ::open(encodedName, O_RDONLY);
        } else {
#if defined(DEBUG_FONTENGINE)
            qDebug() << "creating qpf on the fly:" << fileName;
#endif
            if (::access(QFile::encodeName(qws_fontCacheDir()), W_OK) == 0) {
                fd = ::open(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644);

                QBuffer buffer;
                buffer.open(QIODevice::ReadWrite);
                QPFGenerator generator(&buffer, renderingFontEngine);
                generator.generate();
                buffer.close();
                const QByteArray &data = buffer.data();
                ::write(fd, data.constData(), data.size());
            }
        }
    }

    QT_STATBUF st;
    if (QT_FSTAT(fd, &st)) {
#if defined(DEBUG_FONTENGINE)
        qDebug() << "stat failed!";
#endif
        return;
    }
    dataSize = st.st_size;


    fontData = (const uchar *)::mmap(0, st.st_size, PROT_READ | (renderingFontEngine ? PROT_WRITE : 0), MAP_SHARED, fd, 0);
    if (!fontData || fontData == (const uchar *)MAP_FAILED) {
#if defined(DEBUG_FONTENGINE)
        perror("mmap failed");
#endif
        fontData = 0;
        return;
    }

    if (!verifyHeader(fontData, st.st_size)) {
#if defined(DEBUG_FONTENGINE)
        qDebug() << "verifyHeader failed!";
#endif
        return;
    }

    const Header *header = reinterpret_cast<const Header *>(fontData);

    readOnly = (header->lock == 0xffffffff);

    const uchar *data = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize);
    const uchar *endPtr = fontData + dataSize;
    while (data <= endPtr - 8) {
        quint16 blockTag = readValue<quint16>(data);
        data += 2; // skip padding
        quint32 blockSize = readValue<quint32>(data);

        if (blockTag == CMapBlock) {
            cmapOffset = data - fontData;
            cmapSize = blockSize;
        } else if (blockTag == GMapBlock) {
            glyphMapOffset = data - fontData;
            glyphMapEntries = blockSize / 4;
        } else if (blockTag == GlyphBlock) {
            glyphDataOffset = data - fontData;
            glyphDataSize = blockSize;
        }

        data += blockSize;
    }

    face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString());
    face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt();
#if !defined(QT_NO_FREETYPE)
    freetype = QFreetypeFace::getFace(face_id);
    if (!freetype) {
        QString newPath =
#ifndef QT_NO_SETTINGS
            QLibraryInfo::location(QLibraryInfo::LibrariesPath) +
#endif
                          QLatin1String("/fonts/") +
                          QFileInfo(QFile::decodeName(face_id.filename)).fileName();
        face_id.filename = QFile::encodeName(newPath);
        freetype = QFreetypeFace::getFace(face_id);
    }
    if (freetype) {
        const quint32 qpfTtfRevision = extractHeaderField(fontData, Tag_FontRevision).toUInt();
        uchar data[4];
        uint length = 4;
        bool ok = freetype->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd'), data, &length);
        if (!ok || length != 4
            || qFromBigEndian<quint32>(data) != qpfTtfRevision) {
            freetype->release(face_id);
            freetype = 0;
        }
    }
    if (!cmapOffset && freetype) {
        freetypeCMapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
        externalCMap = reinterpret_cast<const uchar *>(freetypeCMapTable.constData());
        cmapSize = freetypeCMapTable.size();
    }
#endif

    // get the real cmap
    if (cmapOffset) {
        int tableSize = cmapSize;
        const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize);
        if (cmapPtr)
            cmapOffset = cmapPtr - fontData;
        else
            cmapOffset = 0;
    } else if (externalCMap) {
        int tableSize = cmapSize;
        externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize);
    }

    // verify all the positions in the glyphMap
    if (glyphMapOffset) {
        const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset);
        for (uint i = 0; i < glyphMapEntries; ++i) {
            quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]);
            if (glyphDataPos == 0xffffffff)
                continue;
            if (glyphDataPos >= glyphDataSize) {
                // error
                glyphMapOffset = 0;
                glyphMapEntries = 0;
                break;
            }
        }
    }

#if defined(DEBUG_FONTENGINE)
    if (!isValid())
        qDebug() << "fontData" <<  fontData << "dataSize" << dataSize
                 << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset
                 << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset
                 << "fd" << fd << "glyphDataSize" << glyphDataSize;
#endif
#if defined(Q_WS_QWS)
    if (isValid() && renderingFontEngine)
        qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, QFile::encodeName(fileName));
#endif
}
Example #12
0
QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
        QStringList *files,
        QStringList *directories)
{
    QStringList p = paths;
    {
        QMutexLocker locker(&mutex);

        QMutableListIterator<QString> it(p);
        while (it.hasNext()) {
            QString path = it.next();
            int fd;
#if defined(O_EVTONLY)
            fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY);
#else
            fd = qt_safe_open(QFile::encodeName(path), O_RDONLY);
#endif
            if (fd == -1) {
                perror("QKqueueFileSystemWatcherEngine::addPaths: open");
                continue;
            }
            if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) {
                int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE);
                if (fddup != -1) {
                    ::close(fd);
                    fd = fddup;
                }
            }
            fcntl(fd, F_SETFD, FD_CLOEXEC);

            QT_STATBUF st;
            if (QT_FSTAT(fd, &st) == -1) {
                perror("QKqueueFileSystemWatcherEngine::addPaths: fstat");
                ::close(fd);
                continue;
            }
            int id = (S_ISDIR(st.st_mode)) ? -fd : fd;
            if (id < 0) {
                if (directories->contains(path)) {
                    ::close(fd);
                    continue;
                }
            } else {
                if (files->contains(path)) {
                    ::close(fd);
                    continue;
                }
            }

            struct kevent kev;
            EV_SET(&kev,
                   fd,
                   EVFILT_VNODE,
                   EV_ADD | EV_ENABLE | EV_CLEAR,
                   NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
                   0,
                   0);
            if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) {
                perror("QKqueueFileSystemWatcherEngine::addPaths: kevent");
                ::close(fd);
                continue;
            }

            it.remove();
            if (id < 0) {
                DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path;
                directories->append(path);
            } else {
                DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path;
                files->append(path);
            }

            pathToID.insert(path, id);
            idToPath.insert(id, path);
        }
    }

    if (!isRunning())
        start();
    else
        write(kqpipe[1], "@", 1);

    return p;
}
Example #13
0
bool QTranslatorPrivate::do_load(const QString &realname)
{
    QTranslatorPrivate *d = this;
    bool ok = false;

    const bool isResourceFile = realname.startsWith(QLatin1Char(':'));
    if (isResourceFile) {
        // If the translation is in a non-compressed resource file, the data is already in
        // memory, so no need to use QFile to copy it again.
        Q_ASSERT(!d->resource);
        d->resource = new QResource(realname);
        if (d->resource->isValid() && !d->resource->isCompressed()) {
            d->unmapLength = d->resource->size();
            d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(d->resource->data()));
            d->used_mmap = false;
            ok = true;
        } else {
            delete d->resource;
            d->resource = 0;
        }
    }

#ifdef QT_USE_MMAP

#ifndef MAP_FILE
#define MAP_FILE 0
#endif
#ifndef MAP_FAILED
#define MAP_FAILED -1
#endif

    else {
        int fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,
#if defined(Q_OS_WIN)
                     _S_IREAD | _S_IWRITE
#else
                     0666
#endif
            );

        if (fd >= 0) {
            QT_STATBUF st;
            if (!QT_FSTAT(fd, &st)) {
                char *ptr;
                ptr = reinterpret_cast<char *>(
                    mmap(0, st.st_size,             // any address, whole file
                         PROT_READ,                 // read-only memory
                         MAP_FILE | MAP_PRIVATE,    // swap-backed map from file
                         fd, 0));                   // from offset 0 of fd
                if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
                    d->used_mmap = true;
                    d->unmapPointer = ptr;
                    d->unmapLength = st.st_size;
                    ok = true;
                }
            }
            ::close(fd);
        }
    }
#endif // QT_USE_MMAP

    if (!ok) {
        QFile file(realname);
        d->unmapLength = file.size();
        if (!d->unmapLength)
            return false;
        d->unmapPointer = new char[d->unmapLength];

        if (file.open(QIODevice::ReadOnly))
            ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength));

        if (!ok) {
            delete [] d->unmapPointer;
            d->unmapPointer = 0;
            d->unmapLength = 0;
            return false;
        }
    }

    return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
}