IPC: move makePlatformSafeKey to qtipccommon.cpp
This removes the second portion of the #if mess of shared code between QSharedMemory and QSystemSemaphore for SystemV. Change-Id: Id8d5e3999fe94b03acc1fffd171c073c2873206e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
461463b75d
commit
7809caa924
@ -110,6 +110,7 @@ qt_internal_add_module(Core
|
|||||||
global/qxptype_traits.h
|
global/qxptype_traits.h
|
||||||
ipc/qsharedmemory.cpp ipc/qsharedmemory.h ipc/qsharedmemory_p.h
|
ipc/qsharedmemory.cpp ipc/qsharedmemory.h ipc/qsharedmemory_p.h
|
||||||
ipc/qsystemsemaphore.cpp ipc/qsystemsemaphore.h ipc/qsystemsemaphore_p.h
|
ipc/qsystemsemaphore.cpp ipc/qsystemsemaphore.h ipc/qsystemsemaphore_p.h
|
||||||
|
ipc/qtipccommon.cpp ipc/qtipccommon_p.h
|
||||||
io/qabstractfileengine.cpp io/qabstractfileengine_p.h
|
io/qabstractfileengine.cpp io/qabstractfileengine_p.h
|
||||||
io/qbuffer.cpp io/qbuffer.h
|
io/qbuffer.cpp io/qbuffer.h
|
||||||
io/qdataurl.cpp io/qdataurl_p.h
|
io/qdataurl.cpp io/qdataurl_p.h
|
||||||
|
@ -3,81 +3,19 @@
|
|||||||
|
|
||||||
#include "qsharedmemory.h"
|
#include "qsharedmemory.h"
|
||||||
#include "qsharedmemory_p.h"
|
#include "qsharedmemory_p.h"
|
||||||
|
|
||||||
|
#include "qtipccommon_p.h"
|
||||||
#include "qsystemsemaphore.h"
|
#include "qsystemsemaphore.h"
|
||||||
#include <qdir.h>
|
|
||||||
#include <qcryptographichash.h>
|
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
# include <qt_windows.h>
|
# include <qt_windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_DARWIN)
|
|
||||||
# include "qcore_mac_p.h"
|
|
||||||
# if !defined(SHM_NAME_MAX)
|
|
||||||
// Based on PSEMNAMLEN in XNU's posix_sem.c, which would
|
|
||||||
// indicate the max length is 31, _excluding_ the zero
|
|
||||||
// terminator. But in practice (possibly due to an off-
|
|
||||||
// by-one bug in the kernel) the usable bytes are only 30.
|
|
||||||
# define SHM_NAME_MAX 30
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
|
|
||||||
Generate a string from the key which can be any unicode string into
|
|
||||||
the subset that the win/unix kernel allows.
|
|
||||||
|
|
||||||
On Unix this will be a file name
|
|
||||||
*/
|
|
||||||
QString
|
|
||||||
QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
|
|
||||||
const QString &prefix)
|
|
||||||
{
|
|
||||||
if (key.isEmpty())
|
|
||||||
return QString();
|
|
||||||
|
|
||||||
QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
|
|
||||||
|
|
||||||
#if defined(Q_OS_DARWIN) && defined(QT_POSIX_IPC)
|
|
||||||
if (qt_apple_isSandboxed()) {
|
|
||||||
// Sandboxed applications on Apple platforms require the shared memory name
|
|
||||||
// to be in the form <application group identifier>/<custom identifier>.
|
|
||||||
// Since we don't know which application group identifier the user wants
|
|
||||||
// to apply, we instead document that requirement, and use the key directly.
|
|
||||||
return key;
|
|
||||||
} else {
|
|
||||||
// The shared memory name limit on Apple platforms is very low (30 characters),
|
|
||||||
// so we can't use the logic below of combining the prefix, key, and a hash,
|
|
||||||
// to ensure a unique and valid name. Instead we use the first part of the
|
|
||||||
// hash, which should still long enough to avoid collisions in practice.
|
|
||||||
return u'/' + hex.left(SHM_NAME_MAX - 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QString result = prefix;
|
|
||||||
for (QChar ch : key) {
|
|
||||||
if ((ch >= u'a' && ch <= u'z') ||
|
|
||||||
(ch >= u'A' && ch <= u'Z'))
|
|
||||||
result += ch;
|
|
||||||
}
|
|
||||||
result.append(QLatin1StringView(hex));
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
return result;
|
|
||||||
#elif defined(QT_POSIX_IPC)
|
|
||||||
return u'/' + result;
|
|
||||||
#else
|
|
||||||
return QDir::tempPath() + u'/' + result;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
|
|
||||||
|
|
||||||
#if QT_CONFIG(sharedmemory)
|
#if QT_CONFIG(sharedmemory)
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -306,14 +244,16 @@ QSharedMemory::~QSharedMemory()
|
|||||||
void QSharedMemory::setKey(const QString &key)
|
void QSharedMemory::setKey(const QString &key)
|
||||||
{
|
{
|
||||||
Q_D(QSharedMemory);
|
Q_D(QSharedMemory);
|
||||||
if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey)
|
QString newNativeKey =
|
||||||
|
QtIpcCommon::legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SharedMemory);
|
||||||
|
if (key == d->key && newNativeKey == d->nativeKey)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isAttached())
|
if (isAttached())
|
||||||
detach();
|
detach();
|
||||||
d->cleanHandle();
|
d->cleanHandle();
|
||||||
d->key = key;
|
d->key = key;
|
||||||
d->nativeKey = d->makePlatformSafeKey(key);
|
d->nativeKey = newNativeKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -19,22 +19,7 @@
|
|||||||
|
|
||||||
#include <QtCore/qstring.h>
|
#include <QtCore/qstring.h>
|
||||||
|
|
||||||
#if !QT_CONFIG(sharedmemory)
|
#if QT_CONFIG(sharedmemory)
|
||||||
# if QT_CONFIG(systemsemaphore)
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
namespace QSharedMemoryPrivate
|
|
||||||
{
|
|
||||||
QString makePlatformSafeKey(const QString &key,
|
|
||||||
const QString &prefix = QStringLiteral("qipc_sharedmemory_"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "qsystemsemaphore.h"
|
#include "qsystemsemaphore.h"
|
||||||
#include "private/qobject_p.h"
|
#include "private/qobject_p.h"
|
||||||
|
|
||||||
@ -92,8 +77,6 @@ public:
|
|||||||
bool lockedByMe = false;
|
bool lockedByMe = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static QString makePlatformSafeKey(const QString &key,
|
|
||||||
const QString &prefix = QStringLiteral("qipc_sharedmemory_"));
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
Qt::HANDLE handle();
|
Qt::HANDLE handle();
|
||||||
#elif defined(QT_POSIX_IPC)
|
#elif defined(QT_POSIX_IPC)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "qsharedmemory.h"
|
#include "qsharedmemory.h"
|
||||||
#include "qsharedmemory_p.h"
|
#include "qsharedmemory_p.h"
|
||||||
#include "qsystemsemaphore.h"
|
#include "qtipccommon_p.h"
|
||||||
#include <qfile.h>
|
#include <qfile.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -26,11 +26,12 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
|
using namespace QtIpcCommon;
|
||||||
|
|
||||||
int QSharedMemoryPrivate::handle()
|
int QSharedMemoryPrivate::handle()
|
||||||
{
|
{
|
||||||
// don't allow making handles on empty keys
|
// don't allow making handles on empty keys
|
||||||
const QString safeKey = makePlatformSafeKey(key);
|
const QString safeKey = legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SharedMemory);
|
||||||
if (safeKey.isEmpty()) {
|
if (safeKey.isEmpty()) {
|
||||||
errorString = QSharedMemory::tr("%1: key is empty").arg("QSharedMemory::handle"_L1);
|
errorString = QSharedMemory::tr("%1: key is empty").arg("QSharedMemory::handle"_L1);
|
||||||
error = QSharedMemory::KeyError;
|
error = QSharedMemory::KeyError;
|
||||||
@ -53,7 +54,7 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
if (!handle())
|
if (!handle())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
|
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(key, IpcType::SharedMemory));
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
#ifdef O_CLOEXEC
|
#ifdef O_CLOEXEC
|
||||||
@ -94,7 +95,7 @@ bool QSharedMemoryPrivate::create(qsizetype size)
|
|||||||
|
|
||||||
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
|
||||||
{
|
{
|
||||||
const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
|
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(key, IpcType::SharedMemory));
|
||||||
|
|
||||||
const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
|
const int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR);
|
||||||
const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
|
const mode_t omode = (mode == QSharedMemory::ReadOnly ? 0400 : 0600);
|
||||||
@ -180,7 +181,7 @@ bool QSharedMemoryPrivate::detach()
|
|||||||
|
|
||||||
// if there are no attachments then unlink the shared memory
|
// if there are no attachments then unlink the shared memory
|
||||||
if (shm_nattch == 0) {
|
if (shm_nattch == 0) {
|
||||||
const QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key));
|
const QByteArray shmName = QFile::encodeName(legacyPlatformSafeKey(key, IpcType::SharedMemory));
|
||||||
if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
|
if (::shm_unlink(shmName.constData()) == -1 && errno != ENOENT)
|
||||||
setErrorString("QSharedMemory::detach (shm_unlink)"_L1);
|
setErrorString("QSharedMemory::detach (shm_unlink)"_L1);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
#include "qcoreapplication.h"
|
#include "qcoreapplication.h"
|
||||||
#include "qtipccommon_p.h"
|
#include "qtipccommon_p.h"
|
||||||
#include "qsharedmemory_p.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef QT_POSIX_IPC
|
#ifdef QT_POSIX_IPC
|
||||||
@ -37,7 +36,7 @@ public:
|
|||||||
|
|
||||||
QString makeKeyFileName()
|
QString makeKeyFileName()
|
||||||
{
|
{
|
||||||
return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1StringView("qipc_systemsem_"));
|
return QtIpcCommon::legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SystemSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
|
inline void setError(QSystemSemaphore::SystemSemaphoreError e, const QString &message)
|
||||||
|
89
src/corelib/ipc/qtipccommon.cpp
Normal file
89
src/corelib/ipc/qtipccommon.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (C) 2022 Intel Corporation.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include "qtipccommon_p.h"
|
||||||
|
|
||||||
|
#include <qcryptographichash.h>
|
||||||
|
#include <qdir.h>
|
||||||
|
|
||||||
|
#if defined(Q_OS_DARWIN)
|
||||||
|
# include "private/qcore_mac_p.h"
|
||||||
|
# if !defined(SHM_NAME_MAX)
|
||||||
|
// Based on PSEMNAMLEN in XNU's posix_sem.c, which would
|
||||||
|
// indicate the max length is 31, _excluding_ the zero
|
||||||
|
// terminator. But in practice (possibly due to an off-
|
||||||
|
// by-one bug in the kernel) the usable bytes are only 30.
|
||||||
|
# define SHM_NAME_MAX 30
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
|
||||||
|
Legacy: this exists for compatibility with QSharedMemory and
|
||||||
|
QSystemSemaphore between 4.4 and 6.6.
|
||||||
|
|
||||||
|
Generate a string from the key which can be any unicode string into
|
||||||
|
the subset that the win/unix kernel allows.
|
||||||
|
|
||||||
|
On Unix this will be a file name
|
||||||
|
*/
|
||||||
|
QString QtIpcCommon::legacyPlatformSafeKey(const QString &key, QtIpcCommon::IpcType ipcType)
|
||||||
|
{
|
||||||
|
if (key.isEmpty())
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
|
||||||
|
|
||||||
|
#if defined(Q_OS_DARWIN) && defined(QT_POSIX_IPC)
|
||||||
|
if (qt_apple_isSandboxed()) {
|
||||||
|
// Sandboxed applications on Apple platforms require the shared memory name
|
||||||
|
// to be in the form <application group identifier>/<custom identifier>.
|
||||||
|
// Since we don't know which application group identifier the user wants
|
||||||
|
// to apply, we instead document that requirement, and use the key directly.
|
||||||
|
return key;
|
||||||
|
} else {
|
||||||
|
// The shared memory name limit on Apple platforms is very low (30 characters),
|
||||||
|
// so we can't use the logic below of combining the prefix, key, and a hash,
|
||||||
|
// to ensure a unique and valid name. Instead we use the first part of the
|
||||||
|
// hash, which should still long enough to avoid collisions in practice.
|
||||||
|
return u'/' + hex.left(SHM_NAME_MAX - 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QString result;
|
||||||
|
result.reserve(1 + 18 + key.size() + 40);
|
||||||
|
switch (ipcType) {
|
||||||
|
case IpcType::SharedMemory:
|
||||||
|
result += "qipc_sharedmemory_"_L1;
|
||||||
|
break;
|
||||||
|
case IpcType::SystemSemaphore:
|
||||||
|
result += "qipc_systemsem_"_L1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QChar ch : key) {
|
||||||
|
if ((ch >= u'a' && ch <= u'z') ||
|
||||||
|
(ch >= u'A' && ch <= u'Z'))
|
||||||
|
result += ch;
|
||||||
|
}
|
||||||
|
result.append(QLatin1StringView(hex));
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
return result;
|
||||||
|
#elif defined(QT_POSIX_IPC)
|
||||||
|
return u'/' + result;
|
||||||
|
#else
|
||||||
|
return QDir::tempPath() + u'/' + result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
|
@ -27,6 +27,13 @@
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QtIpcCommon {
|
namespace QtIpcCommon {
|
||||||
|
enum class IpcType {
|
||||||
|
SharedMemory,
|
||||||
|
SystemSemaphore
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_AUTOTEST_EXPORT QString legacyPlatformSafeKey(const QString &key, IpcType ipcType);
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
// Convenience function to create the file if needed
|
// Convenience function to create the file if needed
|
||||||
inline int createUnixKeyFile(const QByteArray &fileName)
|
inline int createUnixKeyFile(const QByteArray &fileName)
|
||||||
|
@ -135,7 +135,7 @@ void tst_QSharedMemory::cleanup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
#include <private/qsharedmemory_p.h>
|
#include <private/qtipccommon_p.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifndef QT_POSIX_IPC
|
#ifndef QT_POSIX_IPC
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
@ -157,7 +157,7 @@ int tst_QSharedMemory::remove(const QString &key)
|
|||||||
if (key.isEmpty())
|
if (key.isEmpty())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
QString fileName = QSharedMemoryPrivate::makePlatformSafeKey(key);
|
QString fileName = QtIpcCommon::legacyPlatformSafeKey(key, QtIpcCommon::IpcType::SharedMemory);
|
||||||
|
|
||||||
#ifndef QT_POSIX_IPC
|
#ifndef QT_POSIX_IPC
|
||||||
// ftok requires that an actual file exists somewhere
|
// ftok requires that an actual file exists somewhere
|
||||||
|
Loading…
Reference in New Issue
Block a user