Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdbusunixfiledescriptor.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
7
8#ifdef Q_OS_UNIX
9# include <private/qcore_unix_p.h>
10#endif
11
12QT_BEGIN_NAMESPACE
13
14#ifndef QT_NO_DBUS
15
16QT_IMPL_METATYPE_EXTERN(QDBusUnixFileDescriptor)
17
18/*!
19 \class QDBusUnixFileDescriptor
20 \inmodule QtDBus
21 \ingroup shared
22 \since 4.8
23
24 \brief The QDBusUnixFileDescriptor class holds one Unix file descriptor.
25
26 The QDBusUnixFileDescriptor class is used to hold one Unix file
27 descriptor for use with the Qt D-Bus module. This allows applications to
28 send and receive Unix file descriptors over the D-Bus connection, mapping
29 automatically to the D-Bus type 'h'.
30
31 Objects of type QDBusUnixFileDescriptors can be used also as parameters
32 in signals and slots that get exported to D-Bus by registering with
33 QDBusConnection::registerObject.
34
35 QDBusUnixFileDescriptor does not take ownership of the file descriptor.
36 Instead, it will use the Unix system call \c dup(2) to make a copy of the
37 file descriptor. This file descriptor belongs to the
38 QDBusUnixFileDescriptor object and should not be stored or closed by the
39 user. Instead, you should make your own copy if you need that.
40
41 \section2 Availability
42
43 Unix file descriptor passing is not available in all D-Bus connections.
44 This feature is present with D-Bus library and bus daemon version 1.4 and
45 upwards on Unix systems. Qt D-Bus automatically enables the feature if such
46 a version was found at compile-time and run-time.
47
48 To verify that your connection does support passing file descriptors,
49 check if the QDBusConnection::UnixFileDescriptorPassing capability is set
50 with QDBusConnection::connectionCapabilities(). If the flag is not
51 active, then you will not be able to make calls to methods that have
52 QDBusUnixFileDescriptor as arguments or even embed such a type in a
53 variant. You will also not receive calls containing that type.
54
55 Note also that remote applications may not have support for Unix file
56 descriptor passing. If you make a D-Bus to a remote application that
57 cannot receive such a type, you will receive an error reply. If you try
58 to send a signal containing a D-Bus file descriptor or return one from a
59 method call, the message will be silently dropped.
60
61 Even if the feature is not available, QDBusUnixFileDescriptor will
62 continue to operate, so code need not have compile-time checks for the
63 availability of this feature.
64
65 On non-Unix systems, QDBusUnixFileDescriptor will always report an
66 invalid state and QDBusUnixFileDescriptor::isSupported() will return
67 false.
68
69 \sa QDBusConnection::ConnectionCapabilities, QDBusConnection::connectionCapabilities()
70*/
71
72/*!
73 \typedef QDBusUnixFileDescriptor::Data
74 \internal
75*/
76
77/*!
78 \variable QDBusUnixFileDescriptor::d
79 \internal
80*/
81
82class QDBusUnixFileDescriptorPrivate : public QSharedData {
83public:
84 QDBusUnixFileDescriptorPrivate() : fd(-1) { }
85 QDBusUnixFileDescriptorPrivate(const QDBusUnixFileDescriptorPrivate &other)
86 : QSharedData(other), fd(-1)
87 { }
88 ~QDBusUnixFileDescriptorPrivate();
89
90 QAtomicInt fd;
91};
92
93QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QDBusUnixFileDescriptorPrivate)
94
95/*!
96 Constructs a QDBusUnixFileDescriptor without a wrapped file descriptor.
97 This is equivalent to constructing the object with an invalid file
98 descriptor (like -1).
99
100 \sa fileDescriptor(), isValid()
101*/
102QDBusUnixFileDescriptor::QDBusUnixFileDescriptor()
103 : d(nullptr)
104{
105}
106
107/*!
108 Constructs a QDBusUnixFileDescriptor object by copying the \a
109 fileDescriptor parameter. The original file descriptor is not touched and
110 must be closed by the user.
111
112 Note that the value returned by fileDescriptor() will be different from
113 the \a fileDescriptor parameter passed.
114
115 If the \a fileDescriptor parameter is not valid, isValid() will return
116 false and fileDescriptor() will return -1.
117
118 \sa setFileDescriptor(), fileDescriptor()
119*/
120QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(int fileDescriptor)
121 : d(nullptr)
122{
123 if (fileDescriptor != -1)
124 setFileDescriptor(fileDescriptor);
125}
126
127/*!
128 Constructs a QDBusUnixFileDescriptor object by copying \a other.
129*/
130QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other)
131 : d(other.d)
132{
133}
134
135/*!
136 Copies the Unix file descriptor from the \a other QDBusUnixFileDescriptor
137 object. If the current object contained a file descriptor, it will be
138 properly disposed of before.
139*/
140QDBusUnixFileDescriptor &QDBusUnixFileDescriptor::operator=(const QDBusUnixFileDescriptor &other)
141{
142 if (this != &other)
143 d.operator=(other.d);
144 return *this;
145}
146
147/*!
148 \fn QDBusUnixFileDescriptor &QDBusUnixFileDescriptor::operator=(QDBusUnixFileDescriptor &&other)
149
150 Move-assigns \a other to this QDBusUnixFileDescriptor.
151*/
152
153/*!
154 Destroys this QDBusUnixFileDescriptor object and disposes of the Unix file descriptor that it contained.
155*/
156QDBusUnixFileDescriptor::~QDBusUnixFileDescriptor()
157{
158}
159
160/*!
161 \fn void QDBusUnixFileDescriptor::swap(QDBusUnixFileDescriptor &other)
162 \since 5.0
163 \memberswap{file descriptor instance}
164*/
165
166/*!
167 Returns \c true if this Unix file descriptor is valid. A valid Unix file
168 descriptor is not -1.
169
170 \sa fileDescriptor()
171*/
172bool QDBusUnixFileDescriptor::isValid() const
173{
174 return d ? d->fd.loadRelaxed() != -1 : false;
175}
176
177/*!
178 Returns the Unix file descriptor contained by this
179 QDBusUnixFileDescriptor object. An invalid file descriptor is represented
180 by the value -1.
181
182 Note that the file descriptor returned by this function is owned by the
183 QDBusUnixFileDescriptor object and must not be stored past the lifetime
184 of this object. It is ok to use it while this object is valid, but if one
185 wants to store it for longer use, the file descriptor should be cloned
186 using the Unix \c dup(2), \c dup2(2) or \c dup3(2) functions.
187
188 \sa isValid()
189*/
190int QDBusUnixFileDescriptor::fileDescriptor() const
191{
192 return d ? d->fd.loadRelaxed() : -1;
193}
194
195// actual implementation
196#ifdef Q_OS_UNIX
197
198// qdoc documentation is generated on Unix
199
200/*!
201 Returns \c true if Unix file descriptors are supported on this platform. In
202 other words, this function returns \c true if this is a Unix platform.
203
204 Note that QDBusUnixFileDescriptor continues to operate even if this
205 function returns \c false. The only difference is that the
206 QDBusUnixFileDescriptor objects will always be in the isValid() == false
207 state and fileDescriptor() will always return -1. The class will not
208 consume any operating system resources.
209*/
210bool QDBusUnixFileDescriptor::isSupported()
211{
212 return true;
213}
214
215/*!
216 Sets the file descriptor that this QDBusUnixFileDescriptor object holds
217 to a copy of \a fileDescriptor. The original file descriptor is not
218 touched and must be closed by the user.
219
220 Note that the value returned by fileDescriptor() will be different from
221 the \a fileDescriptor parameter passed.
222
223 If the \a fileDescriptor parameter is not valid, isValid() will return
224 false and fileDescriptor() will return -1.
225
226 \sa isValid(), fileDescriptor()
227*/
228void QDBusUnixFileDescriptor::setFileDescriptor(int fileDescriptor)
229{
230 if (fileDescriptor != -1)
231 giveFileDescriptor(qt_safe_dup(fileDescriptor));
232}
233
234/*!
235 \internal
236 Sets the Unix file descriptor to \a fileDescriptor without copying.
237
238 \sa setFileDescriptor()
239*/
240void QDBusUnixFileDescriptor::giveFileDescriptor(int fileDescriptor)
241{
242 // if we are the sole ref, d remains unchanged
243 // if detaching happens, d->fd will be -1
244 if (d)
245 d.detach();
246 else
247 d = new QDBusUnixFileDescriptorPrivate;
248
249 const int fdl = d->fd.loadRelaxed();
250 if (fdl != -1)
251 qt_safe_close(fdl);
252
253 if (fileDescriptor != -1)
254 d->fd.storeRelaxed(fileDescriptor);
255}
256
257/*!
258 \internal
259 Extracts the Unix file descriptor from the QDBusUnixFileDescriptor object
260 and transfers ownership.
261
262 Note: since QDBusUnixFileDescriptor is implicitly shared, this function
263 is inherently racy and should be avoided.
264*/
265int QDBusUnixFileDescriptor::takeFileDescriptor()
266{
267 if (!d)
268 return -1;
269
270 return d->fd.fetchAndStoreRelaxed(-1);
271}
272
273QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
274{
275 const int fdl = fd.loadRelaxed();
276 if (fdl != -1)
277 qt_safe_close(fdl);
278}
279
280#else
281bool QDBusUnixFileDescriptor::isSupported()
282{
283 return false;
284}
285
286void QDBusUnixFileDescriptor::setFileDescriptor(int)
287{
288}
289
290void QDBusUnixFileDescriptor::giveFileDescriptor(int)
291{
292}
293
294int QDBusUnixFileDescriptor::takeFileDescriptor()
295{
296 return -1;
297}
298
299QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
300{
301}
302
303#endif
304
305#endif // QT_NO_DBUS
306
307QT_END_NAMESPACE