1// Copyright (C) 2022 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QTIPCCOMMON_P_H
5#define QTIPCCOMMON_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qtipccommon.h"
19#include <private/qglobal_p.h>
20#include <private/qtcore-config_p.h>
21
22#if QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
23
24#if defined(Q_OS_UNIX)
25# include <qfile.h>
26# include <private/qcore_unix_p.h>
27#endif
28
29QT_BEGIN_NAMESPACE
30
31class QNativeIpcKeyPrivate
32{
33public:
34 QString legacyKey_;
35
36 static QString legacyKey(const QNativeIpcKey &key)
37 {
38 if (key.isSlowPath())
39 return key.d->legacyKey_;
40 return QString();
41 }
42 static void setLegacyKey(QNativeIpcKey &key, const QString &legacyKey)
43 {
44 QNativeIpcKeyPrivate::makeExtended(key)->legacyKey_ = legacyKey;
45 }
46 static void setNativeAndLegacyKeys(QNativeIpcKey &key, const QString &nativeKey,
47 const QString &legacyKey)
48 {
49 key.setNativeKey(nativeKey);
50 setLegacyKey(key, legacyKey);
51 }
52
53private:
54 static QNativeIpcKeyPrivate *makeExtended(QNativeIpcKey &key)
55 {
56 if (!key.isSlowPath())
57 key.d = new QNativeIpcKeyPrivate;
58 return key.d;
59 }
60};
61
62namespace QtIpcCommon {
63enum class IpcType {
64 SharedMemory,
65 SystemSemaphore
66};
67
68static constexpr bool isIpcSupported(IpcType ipcType, QNativeIpcKey::Type type)
69{
70 switch (type) {
71 case QNativeIpcKey::Type::SystemV:
72 break;
73
74 case QNativeIpcKey::Type::PosixRealtime:
75 if (ipcType == IpcType::SharedMemory)
76 return QT_CONFIG(posix_shm);
77 return QT_CONFIG(posix_sem);
78
79 case QNativeIpcKey::Type::Windows:
80#ifdef Q_OS_WIN
81 return true;
82#else
83 return false;
84#endif
85 }
86
87 if (ipcType == IpcType::SharedMemory)
88 return QT_CONFIG(sysv_shm);
89 return QT_CONFIG(sysv_sem);
90}
91
92template <auto Member1, auto... Members> class IpcStorageVariant
93{
94 template <typename T, typename C> static C extractClass(T C::*);
95 template <typename T, typename C> static T extractObject(T C::*);
96
97 template <auto M>
98 static constexpr bool IsEnabled = decltype(extractObject(M))::Enabled;
99
100 static_assert(std::is_member_object_pointer_v<decltype(Member1)>);
101 using StorageType = decltype(extractClass(Member1));
102 StorageType d;
103
104public:
105 template <typename Lambda> static auto
106 visit_internal(StorageType &storage, QNativeIpcKey::Type keyType, const Lambda &lambda)
107 {
108 if constexpr ((IsEnabled<Member1> || ... || IsEnabled<Members>)) {
109 if constexpr (IsEnabled<Member1>) {
110 using MemberType1 = decltype(extractObject(Member1));
111 if (MemberType1::supports(keyType))
112 return lambda(&(storage.*Member1));
113 }
114 if constexpr ((... || IsEnabled<Members>))
115 return IpcStorageVariant<Members...>::visit_internal(storage, keyType, lambda);
116 Q_UNREACHABLE();
117 } else {
118 // no backends enabled, but we can't return void
119 return false;
120 }
121 }
122
123 template <typename Lambda> auto visit(QNativeIpcKey::Type keyType, const Lambda &lambda)
124 {
125 return visit_internal(d, keyType, lambda);
126 }
127
128 template <typename Lambda> static auto
129 staticVisit(QNativeIpcKey::Type keyType, const Lambda &lambda)
130 {
131 if constexpr ((IsEnabled<Member1> || ... || IsEnabled<Members>)) {
132 if constexpr (IsEnabled<Member1>) {
133 using MemberType1 = decltype(extractObject(Member1));
134 if (MemberType1::supports(keyType))
135 return lambda(static_cast<MemberType1 *>(nullptr));
136 }
137 if constexpr ((... || IsEnabled<Members>))
138 return IpcStorageVariant<Members...>::staticVisit(keyType, lambda);
139 Q_UNREACHABLE();
140 } else {
141 // no backends enabled, but we can't return void
142 return false;
143 }
144 }
145};
146
147QNativeIpcKey legacyPlatformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
148QNativeIpcKey platformSafeKey(const QString &key, IpcType ipcType, QNativeIpcKey::Type type);
149
150#ifdef Q_OS_UNIX
151// Convenience function to create the file if needed
152inline int createUnixKeyFile(const QByteArray &fileName)
153{
154 int fd = qt_safe_open(pathname: fileName.constData(), O_EXCL | O_CREAT | O_RDWR, mode: 0640);
155 if (fd < 0) {
156 if (errno == EEXIST)
157 return 0;
158 return -1;
159 } else {
160 close(fd: fd);
161 }
162 return 1;
163
164}
165#endif // Q_OS_UNIX
166} // namespace QtIpcCommon
167
168QT_END_NAMESPACE
169
170#endif // QT_CONFIG(sharedmemory) || QT_CONFIG(systemsemaphore)
171
172
173#endif // QTIPCCOMMON_P_H
174

source code of qtbase/src/corelib/ipc/qtipccommon_p.h