QFileSystemEngine::canonicalName: don't use malloc()'ing realpath()
It is available in POSIX.1-2008 but is not worth it. The Linux man page says it only works up to PATH_MAX anyway and the POSIX documentation says it's UB if PATH_MAX isn't defined. This cleans up the source code out of these messy #if and should be faster, because we avoid a heap allocation (stack is always faster). Instead, we only relegate the heap version to the case where PATH_MAX isn't defined (i.e., GNU HURD), because in that case the realpath() function can't be used with a stack allocation. Change-Id: Ie30a3caf09ef4176bb36fffd17cde1ed5c5dad59 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com> (cherry picked from commit e32009fc0d48411b835d81b36993828277b5042e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
3e5034794d
commit
76752235a0
@ -646,30 +646,17 @@ QFileSystemEntry QFileSystemEngine::getRawLinkPath(const QFileSystemEntry &link,
|
|||||||
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
|
QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
|
||||||
{
|
{
|
||||||
Q_CHECK_FILE_NAME(entry, entry);
|
Q_CHECK_FILE_NAME(entry, entry);
|
||||||
|
char *resolved_name = nullptr;
|
||||||
|
|
||||||
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_HAIKU) && _POSIX_VERSION < 200809L && !defined(Q_OS_VXWORKS)
|
#ifdef PATH_MAX
|
||||||
// realpath(X,0) is not supported
|
// use the stack to avoid the overhead of memory allocation
|
||||||
Q_UNUSED(data);
|
|
||||||
return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath()));
|
|
||||||
#else
|
|
||||||
# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
|
|
||||||
// used to store the result of realpath in case where realpath cannot allocate itself
|
|
||||||
char stack_result[PATH_MAX + 1];
|
char stack_result[PATH_MAX + 1];
|
||||||
#else
|
#else
|
||||||
// enables unconditionally passing stack_result below
|
// system with unlimited file paths -> must use heap
|
||||||
std::nullptr_t stack_result = nullptr;
|
std::nullptr_t stack_result = nullptr;
|
||||||
# endif
|
auto freer = qScopeGuard([&] { free(resolved_name); });
|
||||||
auto resolved_path_deleter = [&](char *ptr) {
|
#endif
|
||||||
// frees resolved_name if it was allocated by realpath
|
|
||||||
# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
|
|
||||||
// ptr is either null, or points to stack_result
|
|
||||||
Q_ASSERT(!ptr || ptr == stack_result);
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
free(ptr);
|
|
||||||
# endif
|
|
||||||
};
|
|
||||||
std::unique_ptr<char, decltype (resolved_path_deleter)> resolved_name {nullptr, resolved_path_deleter};
|
|
||||||
# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
|
# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
|
||||||
// On some Android and macOS versions, realpath() will return a path even if
|
// On some Android and macOS versions, realpath() will return a path even if
|
||||||
// it does not exist. To work around this, we check existence in advance.
|
// it does not exist. To work around this, we check existence in advance.
|
||||||
@ -679,14 +666,14 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
|
|||||||
if (!data.exists())
|
if (!data.exists())
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
else
|
else
|
||||||
resolved_name.reset(realpath(entry.nativeFilePath().constData(), stack_result));
|
resolved_name = realpath(entry.nativeFilePath().constData(), stack_result);
|
||||||
# else
|
# else
|
||||||
resolved_name.reset(realpath(entry.nativeFilePath().constData(), stack_result));
|
resolved_name = realpath(entry.nativeFilePath().constData(), stack_result);
|
||||||
# endif
|
# endif
|
||||||
if (resolved_name) {
|
if (resolved_name) {
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name.get()));
|
QString canonicalPath = QDir::cleanPath(QFile::decodeName(resolved_name));
|
||||||
return QFileSystemEntry(canonicalPath);
|
return QFileSystemEntry(canonicalPath);
|
||||||
} else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist
|
} else if (errno == ENOENT || errno == ENOTDIR) { // file doesn't exist
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
@ -694,7 +681,6 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
|
|||||||
return QFileSystemEntry();
|
return QFileSystemEntry();
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
|
Loading…
x
Reference in New Issue
Block a user