예제 #1
0
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;
}
예제 #2
0
/*!
    \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);
}
예제 #3
0
/*!
    \internal
*/
bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
{
    Q_Q(QFSFileEngine);

    if (openMode & QIODevice::Unbuffered) {
        int flags = openModeToOpenFlags(openMode);

        // Try to open the file in unbuffered mode.
        do {
            fd = QT_OPEN(fileEntry.nativeFilePath().constData(), flags, 0666);
        } while (fd == -1 && errno == EINTR);

        // On failure, return and report the error.
        if (fd == -1) {
            q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                        qt_error_string(errno));
            return false;
        }

        if (!(openMode & QIODevice::WriteOnly)) {
            // we don't need this check if we tried to open for writing because then
            // we had received EISDIR anyway.
            if (QFileSystemEngine::fillMetaData(fd, metaData)
                    && metaData.isDirectory()) {
                q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
                QT_CLOSE(fd);
                return false;
            }
        }

        // Seek to the end when in Append mode.
        if (flags & QFile::Append) {
            int ret;
            do {
                ret = QT_LSEEK(fd, 0, SEEK_END);
            } while (ret == -1 && errno == EINTR);

            if (ret == -1) {
                q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                            qt_error_string(int(errno)));
                return false;
            }
        }

        fh = 0;
    } else {
        QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData);

        // Try to open the file in buffered mode.
        do {
            fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData());
        } while (!fh && errno == EINTR);

        // On failure, return and report the error.
        if (!fh) {
            q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                        qt_error_string(int(errno)));
            return false;
        }

        if (!(openMode & QIODevice::WriteOnly)) {
            // we don't need this check if we tried to open for writing because then
            // we had received EISDIR anyway.
            if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData)
                    && metaData.isDirectory()) {
                q->setError(QFile::OpenError, QLatin1String("file to open is a directory"));
                fclose(fh);
                return false;
            }
        }

        setCloseOnExec(fileno(fh)); // ignore failure

        // Seek to the end when in Append mode.
        if (openMode & QIODevice::Append) {
            int ret;
            do {
                ret = QT_FSEEK(fh, 0, SEEK_END);
            } while (ret == -1 && errno == EINTR);

            if (ret == -1) {
                q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
                            qt_error_string(int(errno)));
                return false;
            }
        }

        fd = -1;
    }

    closeFileHandle = true;
    return true;
}
예제 #4
0
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
                                 QFile::MemoryMapFlags flags)
{
#ifndef Q_OS_WINPHONE
    Q_Q(QFSFileEngine);
    Q_UNUSED(flags);
    if (openMode == QFile::NotOpen) {
        q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
        return 0;
    }
    if (offset == 0 && size == 0) {
        q->setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
        return 0;
    }

    // check/setup args to map
    DWORD access = 0;
    if (flags & QFileDevice::MapPrivateOption) {
#ifdef FILE_MAP_COPY
        access = FILE_MAP_COPY;
#else
        q->setError(QFile::UnspecifiedError, "MapPrivateOption unsupported");
        return 0;
#endif
    } else if (openMode & QIODevice::WriteOnly) {
        access = FILE_MAP_WRITE;
    } else if (openMode & QIODevice::ReadOnly) {
        access = FILE_MAP_READ;
    }

    if (mapHandle == NULL) {
        // get handle to the file
        HANDLE handle = fileHandle;

#ifndef Q_OS_WINCE
        if (handle == INVALID_HANDLE_VALUE && fh)
            handle = (HANDLE)::_get_osfhandle(QT_FILENO(fh));
#endif

#ifdef Q_USE_DEPRECATED_MAP_API
        nativeClose();
        // handle automatically closed by kernel with mapHandle (below).
        handle = ::CreateFileForMapping((const wchar_t*)fileEntry.nativeFilePath().utf16(),
                GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0),
                0,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL,
                NULL);
        // Since this is a special case, we check if the return value was NULL and if so
        // we change it to INVALID_HANDLE_VALUE to follow the logic inside this function.
        if(0 == handle)
            handle = INVALID_HANDLE_VALUE;
#endif

        if (handle == INVALID_HANDLE_VALUE) {
            q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
            return 0;
        }

        // first create the file mapping handle
        DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY;
#ifndef Q_OS_WINRT
        mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0);
#else
        mapHandle = ::CreateFileMappingFromApp(handle, 0, protection, 0, 0);
#endif
        if (mapHandle == NULL) {
            q->setError(QFile::PermissionsError, qt_error_string());
#ifdef Q_USE_DEPRECATED_MAP_API
            ::CloseHandle(handle);
#endif
            return 0;
        }
    }

    DWORD offsetHi = offset >> 32;
    DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
    SYSTEM_INFO sysinfo;
#ifndef Q_OS_WINRT
    ::GetSystemInfo(&sysinfo);
#else
    ::GetNativeSystemInfo(&sysinfo);
#endif
    DWORD mask = sysinfo.dwAllocationGranularity - 1;
    DWORD extra = offset & mask;
    if (extra)
        offsetLo &= ~mask;

    // attempt to create the map
#ifndef Q_OS_WINRT
    LPVOID mapAddress = ::MapViewOfFile(mapHandle, access,
                                      offsetHi, offsetLo, size + extra);
#else
    LPVOID mapAddress = ::MapViewOfFileFromApp(mapHandle, access,
                                               (ULONG64(offsetHi) << 32) + offsetLo, size + extra);
#endif
    if (mapAddress) {
        uchar *address = extra + static_cast<uchar*>(mapAddress);
        maps[address] = extra;
        return address;
    }

    switch(GetLastError()) {
    case ERROR_ACCESS_DENIED:
        q->setError(QFile::PermissionsError, qt_error_string());
        break;
    case ERROR_INVALID_PARAMETER:
        // size are out of bounds
    default:
        q->setError(QFile::UnspecifiedError, qt_error_string());
    }

    ::CloseHandle(mapHandle);
    mapHandle = NULL;
#else // !Q_OS_WINPHONE
    Q_UNUSED(offset);
    Q_UNUSED(size);
    Q_UNUSED(flags);
    Q_UNIMPLEMENTED();
#endif // Q_OS_WINPHONE
    return 0;
}