diff --git a/CMakeLists.txt b/CMakeLists.txt index d8a2e7225..150f94627 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -232,6 +232,12 @@ katie_check_function(fcvt "stdlib.h") katie_check_function(ecvt "stdlib.h") # NetBSD 1.6 and FreeBSD 4.4 katie_check_function(getprogname "stdlib.h") +# GNU +katie_check_function(get_current_dir_name "unistd.h") +katie_check_function(fegetenv "fenv.h") +katie_check_function(fesetenv "fenv.h") +katie_check_function(feclearexcept "fenv.h") +katie_check_function(feenableexcept "fenv.h") # 64-bit offset alternatives, if any of the functions is not found it will set # QT_LARGEFILE_SUPPORT to FALSE. QT_LARGEFILE_SUPPORT is used in qconfig.h diff --git a/cmake/modules/KatieBuildMacros.cmake b/cmake/modules/KatieBuildMacros.cmake index 0275b0a3f..a2b8b4b7f 100644 --- a/cmake/modules/KatieBuildMacros.cmake +++ b/cmake/modules/KatieBuildMacros.cmake @@ -17,15 +17,45 @@ macro(KATIE_WARNING MESSAGESTR) endif() endmacro() +# a function to check for C function/definition, works for external functions too +function(KATIE_CHECK_DEFINED FORDEFINITION FROMHEADER) + cmake_reset_check_state() + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${ARGN}) + check_symbol_exists("${FORDEFINITION}" "${FROMHEADER}" HAVE_${FORDEFINITION}) + if(NOT HAVE_${FORDEFINITION}) + check_function_exists("${FORDEFINITION}" HAVE_${FORDEFINITION}) + endif() + cmake_pop_check_state() + + if(NOT HAVE_${FORDEFINITION}) + set(compileout "${CMAKE_BINARY_DIR}/${FORDEFINITION}.cpp") + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/modules/katie_check_defined.cpp.cmake" + "${compileout}" + @ONLY + ) + try_compile(${FORDEFINITION}_test + "${CMAKE_BINARY_DIR}" + "${compileout}" + COMPILE_DEFINITIONS ${ARGN} + OUTPUT_VARIABLE ${FORDEFINITION}_test_output + ) + if(${FORDEFINITION}_test) + message(STATUS "Found ${FORDEFINITION} in: <${FROMHEADER}>") + set(HAVE_${FORDEFINITION} TRUE PARENT_SCOPE) + else() + message(STATUS "Could not find ${FORDEFINITION} in: <${FROMHEADER}>") + set(HAVE_${FORDEFINITION} FALSE PARENT_SCOPE) + endif() + endif() +endfunction() + # a macro to check for function presence in header, if function is found a # definition is added. note that check_symbol_exists() and # check_function_exists() cache the result variables so they can be used # anywhere macro(KATIE_CHECK_FUNCTION FORFUNCTION FROMHEADER) - check_symbol_exists("${FORFUNCTION}" "${FROMHEADER}" HAVE_${FORFUNCTION}) - if(NOT HAVE_${FORFUNCTION}) - check_function_exists("${FORFUNCTION}" HAVE_${FORFUNCTION}) - endif() + katie_check_defined("${FORFUNCTION}" "${FROMHEADER}") if(HAVE_${FORFUNCTION}) string(TOUPPER "${FORFUNCTION}" upperfunction) @@ -36,17 +66,11 @@ endmacro() # a function to check for function with 64-bit offset alternative, sets # QT_LARGEFILE_SUPPORT to FALSE if not available function(KATIE_CHECK_FUNCTION64 FORFUNCTION FROMHEADER) - cmake_reset_check_state() - set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE) - check_symbol_exists("${FORFUNCTION}" "${FROMHEADER}" HAVE_${FORFUNCTION}) - if(NOT HAVE_${FORFUNCTION}) - check_function_exists("${FORFUNCTION}" HAVE_${FORFUNCTION}) - endif() + katie_check_defined("${FORFUNCTION}" "${FROMHEADER}" -D_LARGEFILE64_SOURCE -D_LARGEFILE_SOURCE) if(NOT HAVE_${FORFUNCTION}) set(QT_LARGEFILE_SUPPORT FALSE PARENT_SCOPE) endif() - cmake_pop_check_state() endfunction() # a macro to write data to file, does nothing if the file exists and its diff --git a/cmake/modules/katie_check_defined.cpp.cmake b/cmake/modules/katie_check_defined.cpp.cmake new file mode 100644 index 000000000..1d6980a5c --- /dev/null +++ b/cmake/modules/katie_check_defined.cpp.cmake @@ -0,0 +1,9 @@ +#include +#include <@FROMHEADER@> + +int main() { +#ifndef @FORDEFINITION@ + return printf("%p\n", &@FORDEFINITION@); +#endif + return 0; +} diff --git a/src/core/io/qfilesystemengine_unix.cpp b/src/core/io/qfilesystemengine_unix.cpp index 83e9e048c..8074c903a 100644 --- a/src/core/io/qfilesystemengine_unix.cpp +++ b/src/core/io/qfilesystemengine_unix.cpp @@ -38,9 +38,6 @@ #include "qfileinfo.h" #include "qcore_unix_p.h" -#include // for realpath() -#include -#include #include #include #include @@ -49,6 +46,10 @@ # include #endif +#ifndef PATH_MAX +# define PATH_MAX _POSIX_PATH_MAX +#endif + QT_BEGIN_NAMESPACE bool QFileSystemEngine::isCaseSensitive() @@ -59,45 +60,21 @@ bool QFileSystemEngine::isCaseSensitive() //static QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data) { -#if defined(__GLIBC__) && !defined(PATH_MAX) -#define PATH_CHUNK_SIZE 256 - char *s = 0; - int len = -1; - int size = PATH_CHUNK_SIZE; - - while (1) { - s = (char *) ::realloc(s, size); - Q_CHECK_PTR(s); - len = ::readlink(link.nativeFilePath().constData(), s, size); - if (len < 0) { - ::free(s); - break; - } - if (len < size) { - break; - } - size *= 2; - } -#else - char s[PATH_MAX+1]; - int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX); -#endif + char readlinkbuf[PATH_MAX]; + int len = ::readlink(link.nativeFilePath().constData(), readlinkbuf, sizeof(readlinkbuf)); if (len > 0) { QString ret; if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) fillMetaData(link, data, QFileSystemMetaData::DirectoryType); - if (data.isDirectory() && s[0] != '/') { + if (data.isDirectory() && readlinkbuf[0] != '/') { QDir parent(link.filePath()); parent.cdUp(); ret = parent.path(); if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/'))) ret += QLatin1Char('/'); } - s[len] = '\0'; - ret += QFile::decodeName(QByteArray(s)); -#if defined(__GLIBC__) && !defined(PATH_MAX) - ::free(s); -#endif + readlinkbuf[len] = '\0'; + ret += QFile::decodeName(QByteArray(readlinkbuf)); if (!ret.startsWith(QLatin1Char('/'))) { if (link.filePath().startsWith(QLatin1Char('/'))) { @@ -172,16 +149,16 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) //static QString QFileSystemEngine::resolveUserName(uint userId) { - struct passwd *pw = 0; #if !defined(QT_NO_THREAD) && defined(QT_HAVE_GETPWUID_R) int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); if (size_max == -1) size_max = 1024; char buf[size_max]; struct passwd entry; - getpwuid_r(userId, &entry, buf, size_max, &pw); + struct passwd *pw = Q_NULLPTR; + ::getpwuid_r(userId, &entry, buf, size_max, &pw); #else - pw = getpwuid(userId); + struct passwd *pw = ::getpwuid(userId); #endif if (pw) return QFile::decodeName(QByteArray(pw->pw_name)); @@ -191,16 +168,16 @@ QString QFileSystemEngine::resolveUserName(uint userId) //static QString QFileSystemEngine::resolveGroupName(uint groupId) { - struct group *gr = 0; #if !defined(QT_NO_THREAD) && defined(QT_HAVE_GETGRGID_R) int size_max = sysconf(_SC_GETGR_R_SIZE_MAX); if (size_max == -1) size_max = 1024; char buf[size_max]; struct group entry; - getgrgid_r(groupId, &entry, buf, size_max, &gr); + struct group *gr = Q_NULLPTR; + ::getgrgid_r(groupId, &entry, buf, size_max, &gr); #else - gr = getgrgid(groupId); + struct group *gr = ::getgrgid(groupId); #endif if (gr) return QFile::decodeName(QByteArray(gr->gr_name)); @@ -511,20 +488,20 @@ bool QFileSystemEngine::setCurrentPath(const QFileSystemEntry &path) QFileSystemEntry QFileSystemEngine::currentPath() { QFileSystemEntry result; -#if defined(__GLIBC__) +#ifdef QT_HAVE_GET_CURRENT_DIR_NAME #define GETCWDFUNCNAME "get_current_dir_name" - char *currentName = ::get_current_dir_name(); - if (currentName) { - result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath()); - ::free(currentName); + char *currentdir = ::get_current_dir_name(); + if (currentdir) { + result = QFileSystemEntry(QByteArray(currentdir), QFileSystemEntry::FromNativePath()); + ::free(currentdir); } #else #define GETCWDFUNCNAME "getcwd" - char currentName[PATH_MAX+1]; - if (::getcwd(currentName, PATH_MAX)) { - result = QFileSystemEntry(QByteArray(currentName), QFileSystemEntry::FromNativePath()); + char getcwdbuffer[PATH_MAX]; + if (::getcwd(getcwdbuffer, sizeof(getcwdbuffer))) { + result = QFileSystemEntry(QByteArray(getcwdbuffer), QFileSystemEntry::FromNativePath()); } -#endif // __GLIBC__ +#endif // QT_HAVE_GET_CURRENT_DIR_NAME #ifndef QT_NO_DEBUG if (result.isEmpty()) diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index c100765a5..f758ce837 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -44,8 +44,8 @@ #include #include -// TODO: should check if feenableexcept is available -#if defined(Q_OS_LINUX) && defined(__GLIBC__) +#if defined(Q_OS_LINUX) && defined(QT_HAVE_FEGETENV) && defined(QT_HAVE_FESETENV) \ + && defined(QT_HAVE_FECLEAREXCEPT) && defined(QT_HAVE_FEENABLEEXCEPT) # define TEST_FP_EXCEPTION #endif