From 512c2284cafb3eb23d06fc5cdc4e424b711a04b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Wed, 7 Oct 2009 17:42:39 +0200 Subject: (Windows) Don't create a file mapping for each view that is mapped Creating a file mapping for each view mapped to memory is sub-optimal and slow. With this change, a single mapping is created and reused when mapping subsequent views of the file. The handle returned from CreateFileForMapping (used in WinCE 5) is now discarded, since the kernel manages it automatically with the file mapping. This simplifies use of the deprecated map API. Reviewed-by: Maurice Kalinowski Reviewed-by: Marius Storm-Olsen --- src/corelib/io/qfsfileengine_win.cpp | 84 +++++++++++++----------------------- 1 file changed, 31 insertions(+), 53 deletions(-) (limited to 'src/corelib/io/qfsfileengine_win.cpp') diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 898447cc2e..151eabd7fa 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -455,17 +455,10 @@ bool QFSFileEnginePrivate::nativeClose() // Windows native mode. bool ok = true; - if ((fileHandle == INVALID_HANDLE_VALUE || !CloseHandle(fileHandle)) -#ifdef Q_USE_DEPRECATED_MAP_API - && (fileMapHandle == INVALID_HANDLE_VALUE || !CloseHandle(fileMapHandle)) -#endif - ) { + if ((fileHandle == INVALID_HANDLE_VALUE || !::CloseHandle(fileHandle))) { q->setError(QFile::UnspecifiedError, qt_error_string()); ok = false; } -#ifdef Q_USE_DEPRECATED_MAP_API - fileMapHandle = INVALID_HANDLE_VALUE; -#endif fileHandle = INVALID_HANDLE_VALUE; cachedFd = -1; // gets closed by CloseHandle above @@ -1931,42 +1924,42 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, return 0; } + if (mapHandle == INVALID_HANDLE_VALUE) { + // get handle to the file + HANDLE handle = fileHandle; - // 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)); + if (handle == INVALID_HANDLE_VALUE && fh) + handle = (HANDLE)::_get_osfhandle(QT_FILENO(fh)); #endif #ifdef Q_USE_DEPRECATED_MAP_API - if (fileMapHandle == INVALID_HANDLE_VALUE) { nativeClose(); - fileMapHandle = CreateFileForMapping((const wchar_t*)nativeFilePath.constData(), + // handle automatically closed by kernel with mapHandle (below). + handle = ::CreateFileForMapping((const wchar_t*)nativeFilePath.constData(), GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0), 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - } - handle = fileMapHandle; #endif - if (handle == INVALID_HANDLE_VALUE) { - q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); - return 0; - } + 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; - HANDLE mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); - if (mapHandle == NULL) { - q->setError(QFile::PermissionsError, qt_error_string()); + // first create the file mapping handle + DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY; + mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); + if (mapHandle == INVALID_HANDLE_VALUE) { + q->setError(QFile::PermissionsError, qt_error_string()); #ifdef Q_USE_DEPRECATED_MAP_API - mapHandleClose(); + ::CloseHandle(handle); #endif - return 0; + return 0; + } } // setup args to map @@ -1978,17 +1971,17 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, DWORD offsetLo = offset & Q_UINT64_C(0xffffffff); SYSTEM_INFO sysinfo; ::GetSystemInfo(&sysinfo); - int mask = sysinfo.dwAllocationGranularity - 1; - int extra = offset & mask; + DWORD mask = sysinfo.dwAllocationGranularity - 1; + DWORD extra = offset & mask; if (extra) offsetLo &= ~mask; // attempt to create the map - LPVOID mapAddress = MapViewOfFile(mapHandle, access, + LPVOID mapAddress = ::MapViewOfFile(mapHandle, access, offsetHi, offsetLo, size + extra); if (mapAddress) { uchar *address = extra + static_cast(mapAddress); - maps[address] = QPair(extra, mapHandle); + maps[address] = extra; return address; } @@ -2001,10 +1994,8 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, default: q->setError(QFile::UnspecifiedError, qt_error_string()); } - CloseHandle(mapHandle); -#ifdef Q_USE_DEPRECATED_MAP_API - mapHandleClose(); -#endif + + ::CloseHandle(mapHandle); return 0; } @@ -2015,32 +2006,19 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); return false; } - uchar *start = ptr - maps[ptr].first; + uchar *start = ptr - maps[ptr]; if (!UnmapViewOfFile(start)) { q->setError(QFile::PermissionsError, qt_error_string()); return false; } - if (!CloseHandle((HANDLE)maps[ptr].second)) { - q->setError(QFile::UnspecifiedError, qt_error_string()); - return false; - } maps.remove(ptr); - -#ifdef Q_USE_DEPRECATED_MAP_API - mapHandleClose(); -#endif - return true; -} - -#ifdef Q_USE_DEPRECATED_MAP_API -void QFSFileEnginePrivate::mapHandleClose() -{ if (maps.isEmpty()) { - CloseHandle(fileMapHandle); - fileMapHandle = INVALID_HANDLE_VALUE; + ::CloseHandle(mapHandle); + mapHandle = INVALID_HANDLE_VALUE; } + + return true; } -#endif QT_END_NAMESPACE -- cgit v1.2.3 From 2ad49361eeb1ad14a2b9c6c95a9d20d20f9aa851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 23 Oct 2009 11:23:55 +0200 Subject: On Windows, report a 0 file size for streams and other funny files Obtain file size directly, instead of relying on fseek/ftell and messing with the file position. Also changed the return value on errors to 0. This is mostly relevant on streams and pipes, where we used to return whatever error value ftell returned (usually -1). This change also makes the return value consistent with what is returned on Unix platforms and what we document for Windows CE. Nevertheless, documentation of this and related issues is misleading and needs to be updated. Reviewed-by: Markus Goetz --- src/corelib/io/qfsfileengine_win.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src/corelib/io/qfsfileengine_win.cpp') diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 151eabd7fa..b8a16fac93 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -499,11 +499,8 @@ qint64 QFSFileEnginePrivate::nativeSize() const // Buffered stdlib mode. if (fh) { - QT_OFF_T oldPos = QT_FTELL(fh); - QT_FSEEK(fh, 0, SEEK_END); - QT_OFF_T fileSize = QT_FTELL(fh); - QT_FSEEK(fh, oldPos, SEEK_SET); - return qint64(fileSize); + qint64 fileSize = _filelengthi64(QT_FILENO(fh)); + return (fileSize == -1) ? 0 : fileSize; } // Not-open mode, where the file name is known: We'll check the -- cgit v1.2.3 From f808fe435dc00398775fe8040d3c811aed6332a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 23 Oct 2009 13:44:23 +0200 Subject: Fix QFile::isSequential on Windows When not using native HANDLEs, the return of isSequential was hardcoded to true for files with a fd, and for the standard FILE* streams stdin, stdout and stderr; false for all other FILE* streams. We now use the native GetFileType call for all files by obtaining a native handle where required. We also treat files of type FILE_TYPE_CHAR as sequential, as is the case for the standard streams in console applications. When standard streams are redirected to/from files, GetFileType will return FILE_TYPE_DISK for them and they won't be considered sequential. This is alright since in this mode they behave like regular files and QFile::seek() will work for random offsets. Reviewed-by: Marius Storm-Olsen --- src/corelib/io/qfsfileengine_win.cpp | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'src/corelib/io/qfsfileengine_win.cpp') diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index b8a16fac93..9fc4500bb0 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -789,27 +789,18 @@ int QFSFileEnginePrivate::nativeHandle() const bool QFSFileEnginePrivate::nativeIsSequential() const { #if !defined(Q_OS_WINCE) - // stdlib / Windows native mode. - if (fh || fileHandle != INVALID_HANDLE_VALUE) { - if (fh == stdin || fh == stdout || fh == stderr) - return true; - - HANDLE handle = fileHandle; - if (fileHandle == INVALID_HANDLE_VALUE) { - // Rare case: using QFile::open(FILE*) to open a pipe. - handle = (HANDLE)_get_osfhandle(QT_FILENO(fh)); - return false; - } - - DWORD fileType = GetFileType(handle); - return fileType == FILE_TYPE_PIPE; - } + HANDLE handle = fileHandle; + if (fh || fd != -1) + handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd); + if (handle == INVALID_HANDLE_VALUE) + return false; - // stdio mode. - if (fd != -1) - return isSequentialFdFh(); -#endif + DWORD fileType = GetFileType(handle); + return (fileType == FILE_TYPE_CHAR) + || (fileType == FILE_TYPE_PIPE); +#else return false; +#endif } bool QFSFileEngine::remove() -- cgit v1.2.3 From 6b448660f0d967d2749a520b49aa6946e46bff6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Wed, 4 Nov 2009 20:28:55 +0100 Subject: Further fixes to file size handling on Windows with fd and FILE* filelength is not available on Windows CE instead, we must fallback to fseek/ftell as was being done previously. Still on Windows CE, we still don't report the file size for file descriptors, but we also won't set a random error string. Changed qt_error_string calls to use errno when errors come from CRT functions. Also, if we're using filelength on FILE* streams, there's no reason not to use it for file descriptors, instead of requesting a native handle. Reviewed-by: Olivier Goffart --- src/corelib/io/qfsfileengine_win.cpp | 43 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'src/corelib/io/qfsfileengine_win.cpp') diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 9fc4500bb0..a6cb5a9f7a 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -497,11 +497,30 @@ qint64 QFSFileEnginePrivate::nativeSize() const // ### Don't flush; for buffered files, we should get away with ftell. thatQ->flush(); +#if !defined(Q_OS_WINCE) + // stdlib/stdio mode. + if (fh || fd != -1) { + qint64 fileSize = _filelengthi64(fh ? QT_FILENO(fh) : fd); + if (fileSize == -1) { + fileSize = 0; + thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); + } + return fileSize; + } +#else // Q_OS_WINCE // Buffered stdlib mode. if (fh) { - qint64 fileSize = _filelengthi64(QT_FILENO(fh)); - return (fileSize == -1) ? 0 : fileSize; + QT_OFF_T oldPos = QT_FTELL(fh); + QT_FSEEK(fh, 0, SEEK_END); + qint64 fileSize = (qint64)QT_FTELL(fh); + QT_FSEEK(fh, oldPos, SEEK_SET); + if (fileSize == -1) { + fileSize = 0; + thatQ->setError(QFile::UnspecifiedError, qt_error_string(errno)); + } + return fileSize; } +#endif // Not-open mode, where the file name is known: We'll check the // file system directly. @@ -541,23 +560,13 @@ qint64 QFSFileEnginePrivate::nativeSize() const return 0; } - // Unbuffed stdio mode. - if(fd != -1) { -#if !defined(Q_OS_WINCE) - HANDLE handle = (HANDLE)_get_osfhandle(fd); - if (handle != INVALID_HANDLE_VALUE) { - BY_HANDLE_FILE_INFORMATION fileInfo; - if (GetFileInformationByHandle(handle, &fileInfo)) { - qint64 size = fileInfo.nFileSizeHigh; - size <<= 32; - size += fileInfo.nFileSizeLow; - return size; - } - } -#endif - thatQ->setError(QFile::UnspecifiedError, qt_error_string()); +#if defined(Q_OS_WINCE) + // Unbuffed stdio mode + if (fd != -1) { + thatQ->setError(QFile::UnspecifiedError, QLatin1String("Not implemented!")); return 0; } +#endif // Windows native mode. if (fileHandle == INVALID_HANDLE_VALUE) -- cgit v1.2.3