diff --git a/CMakeLists.txt b/CMakeLists.txt index 9902c271d..3813817ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,6 +219,12 @@ check_include_file(sys/time.h HAVE_SYS_TIME_H) # used in qconfig.h check_type_size(size_t QT_POINTER_SIZE) +# XSI POSIX.1-2001 functions +katie_check_function(strerror_r "string.h") +# POSIX.1-2008 functions +katie_check_function(realpath "stdlib.h") +katie_check_function(unsetenv "stdlib.h") + if(KATIE_COMPILER MATCHES "(gcc|clang)") set(QT_VISIBILITY_AVAILABLE TRUE) endif() diff --git a/cmake/modules/KatieBuildMacros.cmake b/cmake/modules/KatieBuildMacros.cmake index 77109641a..6e066268f 100644 --- a/cmake/modules/KatieBuildMacros.cmake +++ b/cmake/modules/KatieBuildMacros.cmake @@ -6,6 +6,9 @@ set(KATIE_RCC "rcc") set(KATIE_MOC "bootstrap_moc") set(KATIE_LRELEASE "lrelease") +include(CheckSymbolExists) +include(CheckFunctionExists) + # a macro to print a dev warning but only when the build type is Debug macro(KATIE_WARNING MESSAGESTR) if(CMAKE_BUILD_TYPE STREQUAL "Debug") @@ -13,6 +16,16 @@ macro(KATIE_WARNING MESSAGESTR) endif() endmacro() +macro(KATIE_CHECK_FUNCTION FORFUNCTION FROMHEADER) + check_symbol_exists("${FORFUNCTION}" "${FROMHEADER}" HAVE_${FORFUNCTION}) + if(NOT HAVE_${FORFUNCTION}) + check_function_exists("${FORFUNCTION}" HAVE_${FORFUNCTION}) + endif() + if(NOT HAVE_${FORFUNCTION}) + message(SEND_ERROR "check_function_exists(${FORFUNCTION}) failed") + endif() +endmacro() + # a macro to write data to file, does nothing if the file exists and its # content is the same as the data macro(KATIE_WRITE_FILE OUTFILE DATA) diff --git a/src/core/global/qglobal.cpp b/src/core/global/qglobal.cpp index 359778440..81a401ba4 100644 --- a/src/core/global/qglobal.cpp +++ b/src/core/global/qglobal.cpp @@ -1365,12 +1365,7 @@ QString qt_error_string(int errorCode) s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); break; default: { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L - QByteArray buf(1024, '\0'); - ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); -#else - ret = QString::fromLocal8Bit(strerror(errorCode)); -#endif + ret = fromstrerror_helper(errorCode); break; } } diff --git a/src/core/io/qfilesystemengine.cpp b/src/core/io/qfilesystemengine.cpp index ddf6b4d04..e1bfcfe8d 100644 --- a/src/core/io/qfilesystemengine.cpp +++ b/src/core/io/qfilesystemengine.cpp @@ -42,55 +42,6 @@ QT_BEGIN_NAMESPACE -/*! - \internal - - Returns the canonicalized form of \a path (i.e., with all symlinks - resolved, and all redundant path elements removed. -*/ -QString QFileSystemEngine::slowCanonicalized(const QString &path) -{ - if (path.isEmpty()) - return path; - - QFileInfo fi; - const QChar slash(QLatin1Char('/')); - QString tmpPath = path; - int separatorPos = 0; - QSet nonSymlinks; - QSet known; - - known.insert(path); - do { - separatorPos = tmpPath.indexOf(slash, separatorPos + 1); - QString prefix = separatorPos == -1 ? tmpPath : tmpPath.left(separatorPos); - if ( - !nonSymlinks.contains(prefix)) { - fi.setFile(prefix); - if (fi.isSymLink()) { - QString target = fi.readLink(); - if(QFileInfo(target).isRelative()) - target = fi.absolutePath() + slash + target; - if (separatorPos != -1) { - if (fi.isDir() && !target.endsWith(slash)) - target.append(slash); - target.append(tmpPath.mid(separatorPos)); - } - tmpPath = QDir::cleanPath(target); - separatorPos = 0; - - if (known.contains(tmpPath)) - return QString(); - known.insert(tmpPath); - } else { - nonSymlinks.insert(prefix); - } - } - } while (separatorPos != -1); - - return QDir::cleanPath(tmpPath); -} - static inline bool _q_checkEntry(QFileSystemEntry &entry, QFileSystemMetaData &data, bool resolvingEntry) { if (resolvingEntry) { diff --git a/src/core/io/qfilesystemengine_p.h b/src/core/io/qfilesystemengine_p.h index 14a60542d..db45ced64 100644 --- a/src/core/io/qfilesystemengine_p.h +++ b/src/core/io/qfilesystemengine_p.h @@ -90,8 +90,6 @@ public: static QAbstractFileEngine *resolveEntryAndCreateLegacyEngine(QFileSystemEntry &entry, QFileSystemMetaData &data); -private: - static QString slowCanonicalized(const QString &path); }; QT_END_NAMESPACE diff --git a/src/core/io/qfilesystemengine_unix.cpp b/src/core/io/qfilesystemengine_unix.cpp index 96ed1a9ca..b7c91d63b 100644 --- a/src/core/io/qfilesystemengine_unix.cpp +++ b/src/core/io/qfilesystemengine_unix.cpp @@ -120,27 +120,12 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, if (entry.isEmpty() || entry.isRoot()) return entry; -#if _POSIX_VERSION < 200809L - // realpath(X,0) is not supported - Q_UNUSED(data); - return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); -#else -#if _POSIX_VERSION >= 200801L - char *ret = realpath(entry.nativeFilePath().constData(), (char*)0); -#else - char *ret = static_cast(malloc(PATH_MAX + 1)); - if (realpath(entry.nativeFilePath().constData(), ret) == 0) { - const int savedErrno = errno; // errno is checked below, and free() might change it - free(ret); - errno = savedErrno; - ret = 0; - } -#endif + char *ret = ::realpath(entry.nativeFilePath().constData(), (char*)0); if (ret) { data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; data.entryFlags |= QFileSystemMetaData::ExistsAttribute; QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret)); - free(ret); + ::free(ret); return QFileSystemEntry(canonicalPath); } else if (errno == ENOENT) { // file doesn't exist data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; @@ -148,7 +133,6 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, return QFileSystemEntry(); } return entry; -#endif } //static diff --git a/src/core/kernel/qsystemerror.cpp b/src/core/kernel/qsystemerror.cpp index 59ad0e98e..743a2b886 100644 --- a/src/core/kernel/qsystemerror.cpp +++ b/src/core/kernel/qsystemerror.cpp @@ -59,12 +59,7 @@ static QString standardLibraryErrorString(int errorCode) s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); break; default: { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L - QByteArray buf(1024, '\0'); - ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); -#else - ret = QString::fromLocal8Bit(strerror(errorCode)); -#endif + ret = fromstrerror_helper(errorCode); break; } } if (s) { diff --git a/src/core/qcorecommon_p.h b/src/core/qcorecommon_p.h index 64916ce1e..a823cfa49 100644 --- a/src/core/qcorecommon_p.h +++ b/src/core/qcorecommon_p.h @@ -7,30 +7,31 @@ # include #endif +#include + QT_BEGIN_NAMESPACE // enough space to hold BOM, each char as surrogate pair and terminator #define QMAXUSTRLEN(X) 4 + (X * 2) + 2 -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L // There are two incompatible versions of strerror_r: // a) the XSI/POSIX.1 version, which returns an int, // indicating success or not // b) the GNU version, which returns a char*, which may or may not // be the beginning of the buffer we used // The GNU libc manpage for strerror_r says you should use the the XSI -// version in portable code. However, it's impossible to do that if -// _GNU_SOURCE is defined so we use C++ overloading to decide what to do -// depending on the return type -static inline QString fromstrerror_helper(int, const QByteArray &buf) +// version in portable code. +static inline QString fromstrerror_helper(const int errorcode) { - return QString::fromLocal8Bit(buf.constData()); -} -static inline QString fromstrerror_helper(const char *str, const QByteArray &) -{ - return QString::fromLocal8Bit(str); -} +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + char errbuf[1024]; + ::memset(errbuf, '\0', sizeof(errbuf)); + ::strerror_r(errorcode, errbuf, sizeof(errbuf)); + return QString::fromLocal8Bit(errbuf, sizeof(errbuf)); +#else + return QString::fromLocal8Bit(::strerror(errorcode)); #endif +} static inline void report_error(int code, const char *where, const char *what) { diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 8eb560bae..7b2b60901 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -95,10 +95,6 @@ # include #endif -#if _POSIX_VERSION+0 < 200112L && !defined(Q_OS_BSD4) -# define QT_NO_UNSETENV -#endif - QT_BEGIN_NAMESPACE //#define X_NOT_BROKEN @@ -1624,13 +1620,7 @@ void qt_init(QApplicationPrivate *priv, int, qt_x11Data->startupId = getenv("DESKTOP_STARTUP_ID"); if (qt_x11Data->startupId) { -#ifndef QT_NO_UNSETENV - unsetenv("DESKTOP_STARTUP_ID"); -#else - // it's a small memory leak, however we won't crash if Qt is - // unloaded and someones tries to use the envoriment. - putenv(strdup("DESKTOP_STARTUP_ID=")); -#endif + ::unsetenv("DESKTOP_STARTUP_ID"); } } else { // read some non-GUI settings when not using the X server... diff --git a/tests/auto/qdir/tst_qdir.cpp b/tests/auto/qdir/tst_qdir.cpp index 9183c024b..309c4e440 100644 --- a/tests/auto/qdir/tst_qdir.cpp +++ b/tests/auto/qdir/tst_qdir.cpp @@ -1081,9 +1081,7 @@ void tst_QDir::homePath() QVERIFY(!strHome.endsWith('/')); QByteArray envHome = qgetenv("HOME"); -#if !defined(_WRS_KERNEL) // unsetenv is not available on VxWorks DKM mode - unsetenv("HOME"); -#endif + ::unsetenv("HOME"); QCOMPARE(QDir::homePath(), QDir::rootPath()); qputenv("HOME", envHome); #endif