From 80c152d6898c1b8727ac14d32437b274153a7089 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 30 Jun 2017 13:30:52 -0700 Subject: [PATCH] Move the readlink(2) wrapper to qcore_unix.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This deduplicates the code between QFileSystemEngine and QLockFile. Change-Id: I1eba2b016de74620bfc8fffd14cd005d5fd9beaa Reviewed-by: Jędrzej Nowacki --- qmake/Makefile.unix | 3 +++ qmake/Makefile.unix.unix | 2 ++ src/corelib/io/qfilesystemengine_unix.cpp | 33 +++-------------------- src/corelib/io/qlockfile_unix.cpp | 8 +++--- src/corelib/kernel/qcore_unix.cpp | 33 +++++++++++++++++++++++ src/corelib/kernel/qcore_unix_p.h | 2 ++ src/tools/bootstrap/bootstrap.pro | 3 ++- 7 files changed, 50 insertions(+), 34 deletions(-) diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index 259c5cba16..1da4b3727f 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -319,6 +319,9 @@ qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp qcore_mac.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< +qcore_unix.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_unix.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $< + qoperatingsystemversion.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp $(CXX) -c -o $@ $(CXXFLAGS) $< diff --git a/qmake/Makefile.unix.unix b/qmake/Makefile.unix.unix index 63eba4f5a5..e8c1cd1017 100644 --- a/qmake/Makefile.unix.unix +++ b/qmake/Makefile.unix.unix @@ -1,10 +1,12 @@ EXEEXT = QTOBJS = \ + qcore_unix.o \ qfilesystemengine_unix.o \ qfilesystemiterator_unix.o \ qfsfileengine_unix.o \ qlocale_unix.o QTSRCS = \ + $(SOURCE_PATH)/src/corelib/kernel/qcore_unix.cpp \ $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \ $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp \ $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp \ diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 929db259ec..2c8c4e8f9e 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -44,6 +44,7 @@ #include "qfile.h" #include +#include #include #include // for realpath() @@ -150,30 +151,8 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e //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 - if (len > 0) { + QByteArray s = qt_readlink(link.nativeFilePath().constData()); + if (s.length() > 0) { QString ret; if (!data.hasFlags(QFileSystemMetaData::DirectoryType)) fillMetaData(link, data, QFileSystemMetaData::DirectoryType); @@ -184,11 +163,7 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, 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 + ret += QFile::decodeName(s); if (!ret.startsWith(QLatin1Char('/'))) { const QString linkFilePath = link.filePath(); diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index f21aced87c..1ee8ce889c 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -260,15 +260,15 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) #elif defined(Q_OS_LINUX) if (!qt_haveLinuxProcfs()) return QString(); + char exePath[64]; - char buf[PATH_MAX + 1]; sprintf(exePath, "/proc/%lld/exe", pid); - size_t len = (size_t)readlink(exePath, buf, sizeof(buf)); - if (len >= sizeof(buf)) { + + QByteArray buf = qt_readlink(exePath); + if (buf.isEmpty()) { // The pid is gone. Return some invalid process name to fail the test. return QStringLiteral("/ERROR/"); } - buf[len] = 0; return QFileInfo(QFile::decodeName(buf)).fileName(); #elif defined(Q_OS_HAIKU) thread_info info; diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 686143f8c7..3b0da136ca 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -50,6 +50,37 @@ QT_BEGIN_NAMESPACE +QByteArray qt_readlink(const char *path) +{ +#ifndef PATH_MAX + // suitably large value that won't consume too much memory +# define PATH_MAX 1024*1024 +#endif + + QByteArray buf(256, Qt::Uninitialized); + + ssize_t len = ::readlink(path, buf.data(), buf.size()); + while (len == buf.size()) { + // readlink(2) will fill our buffer and not necessarily terminate with NUL; + if (buf.size() >= PATH_MAX) { + errno = ENAMETOOLONG; + return QByteArray(); + } + + // double the size and try again + buf.resize(buf.size() * 2); + len = ::readlink(path, buf.data(), buf.size()); + } + + if (len == -1) + return QByteArray(); + + buf.resize(len); + return buf; +} + +#ifndef QT_BOOTSTRAPPED + #if QT_CONFIG(poll_pollts) # define ppoll pollts #endif @@ -121,4 +152,6 @@ int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout } } +#endif // QT_BOOTSTRAPPED + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index ea5d98cbf3..9d2c4f6c31 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -55,6 +55,7 @@ #include #include "qplatformdefs.h" #include "qatomic.h" +#include "qbytearray.h" #ifndef Q_OS_UNIX # error "qcore_unix_p.h included on a non-Unix system" @@ -339,6 +340,7 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp timespec qt_gettime() Q_DECL_NOTHROW; void qt_nanosleep(timespec amount); +QByteArray qt_readlink(const char *path); /* non-static */ inline bool qt_haveLinuxProcfs() diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index b92e5bb82b..8882df9fc5 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -94,7 +94,8 @@ SOURCES += \ ../../xml/dom/qdom.cpp \ ../../xml/sax/qxml.cpp -unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \ +unix:SOURCES += ../../corelib/kernel/qcore_unix.cpp \ + ../../corelib/io/qfilesystemengine_unix.cpp \ ../../corelib/io/qfilesystemiterator_unix.cpp \ ../../corelib/io/qfsfileengine_unix.cpp