Move the readlink(2) wrapper to qcore_unix.cpp

This deduplicates the code between QFileSystemEngine and QLockFile.

Change-Id: I1eba2b016de74620bfc8fffd14cd005d5fd9beaa
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@qt.io>
This commit is contained in:
Thiago Macieira 2017-06-30 13:30:52 -07:00
parent 3c689c4b3f
commit 80c152d689
7 changed files with 50 additions and 34 deletions

View File

@ -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) $<

View File

@ -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 \

View File

@ -44,6 +44,7 @@
#include "qfile.h"
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/private/qcore_unix_p.h>
#include <QtCore/qvarlengtharray.h>
#include <stdlib.h> // 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();

View File

@ -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;

View File

@ -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

View File

@ -55,6 +55,7 @@
#include <QtCore/private/qglobal_p.h>
#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()

View File

@ -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