Merge remote-tracking branch 'origin/api_changes'
[profile/ivi/qtbase.git] / src / dbus / qdbusunixfiledescriptor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the FOO module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include "qdbusunixfiledescriptor.h"
44 #include <QSharedData>
45
46 #ifdef Q_OS_UNIX
47 # include <private/qcore_unix_p.h>
48 #endif
49
50 QT_BEGIN_NAMESPACE
51
52 /*!
53     \class QDBusUnixFileDescriptor
54     \inmodule QtDBus
55     \since 4.8
56
57     \brief The QDBusUnixFileDescriptor class holds one Unix file descriptor.
58
59     The QDBusUnixFileDescriptor class is used to hold one Unix file
60     descriptor for use with the QtDBus module. This allows applications to
61     send and receive Unix file descriptors over the D-Bus connection, mapping
62     automatically to the D-Bus type 'h'.
63
64     Objects of type QDBusUnixFileDescriptors can be used also as parameters
65     in signals and slots that get exported to D-Bus by registering with
66     QDBusConnection::registerObject.
67
68     QDBusUnixFileDescriptor does not take ownership of the file descriptor.
69     Instead, it will use the Unix system call \c dup(2) to make a copy of the
70     file descriptor. This file descriptor belongs to the
71     QDBusUnixFileDescriptor object and should not be stored or closed by the
72     user. Instead, you should make your own copy if you need that.
73
74     \section2 Availability
75
76     Unix file descriptor passing is not available in all D-Bus connections.
77     This feature is present with D-Bus library and bus daemon version 1.4 and
78     upwards on Unix systems. QtDBus automatically enables the feature if such
79     a version was found at compile-time and run-time.
80
81     To verify that your connection does support passing file descriptors,
82     check if the QDBusConnection::UnixFileDescriptorPassing capability is set
83     with QDBusConnection::connectionCapabilities(). If the flag is not
84     active, then you will not be able to make calls to methods that have
85     QDBusUnixFileDescriptor as arguments or even embed such a type in a
86     variant. You will also not receive calls containing that type.
87
88     Note also that remote applications may not have support for Unix file
89     descriptor passing. If you make a D-Bus to a remote application that
90     cannot receive such a type, you will receive an error reply. If you try
91     to send a signal containing a D-Bus file descriptor or return one from a
92     method call, the message will be silently dropped.
93
94     Even if the feature is not available, QDBusUnixFileDescriptor will
95     continue to operate, so code need not have compile-time checks for the
96     availability of this feature.
97
98     On non-Unix systems, QDBusUnixFileDescriptor will always report an
99     invalid state and QDBusUnixFileDescriptor::isSupported() will return
100     false.
101
102     \sa QDBusConnection::ConnectionCapabilities, QDBusConnection::connectionCapabilities()
103 */
104
105 /*!
106     \typedef QDBusUnixFileDescriptor::Data
107     \internal
108 */
109
110 /*!
111     \variable QDBusUnixFileDescriptor::d
112     \internal
113 */
114
115 class QDBusUnixFileDescriptorPrivate : public QSharedData {
116 public:
117     QDBusUnixFileDescriptorPrivate() : fd(-1) { }
118     QDBusUnixFileDescriptorPrivate(const QDBusUnixFileDescriptorPrivate &other)
119         : QSharedData(other), fd(-1)
120     {  }
121     ~QDBusUnixFileDescriptorPrivate();
122
123     QAtomicInt fd;
124 };
125
126 template<> inline
127 QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate>::~QExplicitlySharedDataPointer()
128 { if (d && !d->ref.deref()) delete d; }
129
130 /*!
131     Constructs a QDBusUnixFileDescriptor without a wrapped file descriptor.
132     This is equivalent to constructing the object with an invalid file
133     descriptor (like -1).
134
135     \sa fileDescriptor(), isValid()
136 */
137 QDBusUnixFileDescriptor::QDBusUnixFileDescriptor()
138     : d(0)
139 {
140 }
141
142 /*!
143     Constructs a QDBusUnixFileDescriptor object by copying the \a
144     fileDescriptor parameter. The original file descriptor is not touched and
145     must be closed by the user.
146
147     Note that the value returned by fileDescriptor() will be different from
148     the \a fileDescriptor parameter passed.
149
150     If the \a fileDescriptor parameter is not valid, isValid() will return
151     false and fileDescriptor() will return -1.
152
153     \sa setFileDescriptor(), fileDescriptor()
154 */
155 QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(int fileDescriptor)
156     : d(0)
157 {
158     if (fileDescriptor != -1)
159         setFileDescriptor(fileDescriptor);
160 }
161
162 /*!
163     Constructs a QDBusUnixFileDescriptor object by copying \a other.
164 */
165 QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other)
166     : d(other.d)
167 {
168 }
169
170 /*!
171     Copies the Unix file descriptor from the \a other QDBusUnixFileDescriptor
172     object. If the current object contained a file descriptor, it will be
173     properly disposed of before.
174 */
175 QDBusUnixFileDescriptor &QDBusUnixFileDescriptor::operator=(const QDBusUnixFileDescriptor &other)
176 {
177     if (this != &other)
178         d.operator=(other.d);
179     return *this;
180 }
181
182 /*!
183     Destroys this QDBusUnixFileDescriptor object and disposes of the Unix file descriptor that it contained.
184 */
185 QDBusUnixFileDescriptor::~QDBusUnixFileDescriptor()
186 {
187 }
188
189 /*!
190     Returns true if this Unix file descriptor is valid. A valid Unix file
191     descriptor is not -1.
192
193     \sa fileDescriptor()
194 */
195 bool QDBusUnixFileDescriptor::isValid() const
196 {
197     return d ? d->fd.load() != -1 : false;
198 }
199
200 /*!
201     Returns the Unix file descriptor contained by this
202     QDBusUnixFileDescriptor object. An invalid file descriptor is represented
203     by the value -1.
204
205     Note that the file descriptor returned by this function is owned by the
206     QDBusUnixFileDescriptor object and must not be stored past the lifetime
207     of this object. It is ok to use it while this object is valid, but if one
208     wants to store it for longer use, the file descriptor should be cloned
209     using the Unix \c dup(2), \c dup2(2) or \c dup3(2) functions.
210
211     \sa isValid()
212 */
213 int QDBusUnixFileDescriptor::fileDescriptor() const
214 {
215     return d ? d->fd.load() : -1;
216 }
217
218 // actual implementation
219 #ifdef Q_OS_UNIX
220
221 // qdoc documentation is generated on Unix
222
223 /*!
224     Returns true if Unix file descriptors are supported on this platform. In
225     other words, this function returns true if this is a Unix platform.
226
227     Note that QDBusUnixFileDescriptor continues to operate even if this
228     function returns false. The only difference is that the
229     QDBusUnixFileDescriptor objects will always be in the isValid() == false
230     state and fileDescriptor() will always return -1. The class will not
231     consume any operating system resources.
232 */
233 bool QDBusUnixFileDescriptor::isSupported()
234 {
235     return true;
236 }
237
238 /*!
239     Sets the file descriptor that this QDBusUnixFileDescriptor object holds
240     to a copy of \a fileDescriptor. The original file descriptor is not
241     touched and must be closed by the user.
242
243     Note that the value returned by fileDescriptor() will be different from
244     the \a fileDescriptor parameter passed.
245
246     If the \a fileDescriptor parameter is not valid, isValid() will return
247     false and fileDescriptor() will return -1.
248
249     \sa isValid(), fileDescriptor()
250 */
251 void QDBusUnixFileDescriptor::setFileDescriptor(int fileDescriptor)
252 {
253     if (fileDescriptor != -1)
254         giveFileDescriptor(qt_safe_dup(fileDescriptor));
255 }
256
257 /*!
258     \internal
259     Sets the Unix file descriptor to \a fileDescriptor without copying.
260
261     \sa setFileDescriptor()
262 */
263 void QDBusUnixFileDescriptor::giveFileDescriptor(int fileDescriptor)
264 {
265     // if we are the sole ref, d remains unchanged
266     // if detaching happens, d->fd will be -1
267     if (d)
268         d.detach();
269     else
270         d = new QDBusUnixFileDescriptorPrivate;
271
272     const int fdl = d->fd.load();
273     if (fdl != -1)
274         qt_safe_close(fdl);
275
276     if (fileDescriptor != -1)
277         d->fd.store(fileDescriptor);
278 }
279
280 /*!
281     \internal
282     Extracts the Unix file descriptor from the QDBusUnixFileDescriptor object
283     and transfers ownership.
284
285     Note: since QDBusUnixFileDescriptor is implicitly shared, this function
286     is inherently racy and should be avoided.
287 */
288 int QDBusUnixFileDescriptor::takeFileDescriptor()
289 {
290     if (!d)
291         return -1;
292
293     return d->fd.fetchAndStoreRelaxed(-1);
294 }
295
296 QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
297 {
298     const int fdl = fd.load();
299     if (fdl != -1)
300         qt_safe_close(fdl);
301 }
302
303 #else
304 bool QDBusUnixFileDescriptor::isSupported()
305 {
306     return false;
307 }
308
309 void QDBusUnixFileDescriptor::setFileDescriptor(int)
310 {
311 }
312
313 void QDBusUnixFileDescriptor::giveFileDescriptor(int)
314 {
315 }
316
317 int QDBusUnixFileDescriptor::takeFileDescriptor()
318 {
319     return -1;
320 }
321
322 QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
323 {
324 }
325
326 #endif
327
328 QT_END_NAMESPACE