Revision control
Copy as Markdown
// 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
// Qt-Security score:significant reason:default
#ifndef QTIPCCOMMON_P_H
#define QTIPCCOMMON_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qtipccommon.h"
#include <private/qglobal_p.h>
#include <private/qtcore-config_p.h>
#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
#if defined(Q_OS_UNIX)
# include <qfile.h>
# include <private/qcore_unix_p.h>
#endif
QT_BEGIN_NAMESPACE
class QNativeIpcKeyPrivate
{
public:
QString legacyKey_;
static QString legacyKey(const QNativeIpcKey &key)
{
if (key.isSlowPath())
return key.d->legacyKey_;
return QString();
}
static void setLegacyKey(QNativeIpcKey &key, const QString &legacyKey)
{
QNativeIpcKeyPrivate::makeExtended(key)->legacyKey_ = legacyKey;
}
static void setNativeAndLegacyKeys(QNativeIpcKey &key, const QString &nativeKey,
const QString &legacyKey)
{
key.setNativeKey(nativeKey);
setLegacyKey(key, legacyKey);
}
private:
static QNativeIpcKeyPrivate *makeExtended(QNativeIpcKey &key)
{
if (!key.isSlowPath())
key.d = new QNativeIpcKeyPrivate;
return key.d;
}
};
namespace QtIpcCommon {
enum class IpcType {
SharedMemory,
SystemSemaphore
};
constexpr bool isIpcSupported(IpcType ipcType, QNativeIpcKey::Type type)
{
switch (type) {
case QNativeIpcKey::Type::SystemV:
#ifdef Q_OS_HARMONY
return false;
#else
break;
#endif
case QNativeIpcKey::Type::PosixRealtime:
if (ipcType == IpcType::SharedMemory)
return QT_CONFIG(posix_shm);
return QT_CONFIG(posix_sem);
case QNativeIpcKey::Type::Windows:
#ifdef Q_OS_WIN
return true;
#else
return false;
#endif
}
if (ipcType == IpcType::SharedMemory)
return QT_CONFIG(sysv_shm);
return QT_CONFIG(sysv_sem);
}
template <auto Member1, auto... Members> class IpcStorageVariant
{
template <typename T, typename C> static C extractClass(T C::*);
template <typename T, typename C> static T extractObject(T C::*);
template <auto M>
static constexpr bool IsEnabled = decltype(extractObject(M))::Enabled;
static_assert(std::is_member_object_pointer_v<decltype(Member1)>);
using StorageType = decltype(extractClass(Member1));
StorageType d;
public:
template <typename Lambda> static auto
visit_internal(StorageType &storage, QNativeIpcKey::Type keyType, const Lambda &lambda)
{
if constexpr ((IsEnabled<Member1> || ... || IsEnabled<Members>)) {
if constexpr (IsEnabled<Member1>) {
using MemberType1 = decltype(extractObject(Member1));
if (MemberType1::supports(keyType))
return lambda(&(storage.*Member1));
}
if constexpr ((... || IsEnabled<Members>))
return IpcStorageVariant<Members...>::visit_internal(storage, keyType, lambda);
Q_UNREACHABLE();
} else {
// no backends enabled, but we can't return void
return false;
}
}
template <typename Lambda> auto visit(QNativeIpcKey::Type keyType, const Lambda &lambda)
{
return visit_internal(d, keyType, lambda);
}
template <typename Lambda> static auto
staticVisit(QNativeIpcKey::Type keyType, const Lambda &lambda)
{
if constexpr ((IsEnabled<Member1> || ... || IsEnabled<Members>)) {
if constexpr (IsEnabled<Member1>) {
using MemberType1 = decltype(extractObject(Member1));
if (MemberType1::supports(keyType))
return lambda(static_cast<MemberType1 *>(nullptr));
}
if constexpr ((... || IsEnabled<Members>))
return IpcStorageVariant<Members...>::staticVisit(keyType, lambda);
Q_UNREACHABLE();
} else {
// no backends enabled, but we can't return void
return false;
}
}
};
QNativeIpcKey legacyPlatformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
QNativeIpcKey platformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
#ifdef Q_OS_UNIX
// Convenience function to create the file if needed
inline int createUnixKeyFile(const QByteArray &fileName)
{
int fd = qt_safe_open(fileName.constData(), O_EXCL | O_CREAT | O_RDWR, 0640);
if (fd < 0) {
if (errno == EEXIST)
return 0;
return -1;
} else {
close(fd);
}
return 1;
}
#endif // Q_OS_UNIX
} // namespace QtIpcCommon
QT_END_NAMESPACE
#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
#endif // QTIPCCOMMON_P_H