summaryrefslogtreecommitdiffstats
path: root/src/dbus
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-04-18 16:08:32 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-04-18 16:08:32 (GMT)
commita359d21a84acc4b7eb73931e47acd4440327be19 (patch)
treed0c549db270c356211cd8eb78a48ba29a401c860 /src/dbus
parent6814998ab4d9c6b0990b0bf01119ace69363ce3e (diff)
parentd0245f57d1b617a61bb7472c232be5b974892369 (diff)
downloadQt-a359d21a84acc4b7eb73931e47acd4440327be19.zip
Qt-a359d21a84acc4b7eb73931e47acd4440327be19.tar.gz
Qt-a359d21a84acc4b7eb73931e47acd4440327be19.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1: (29 commits) Use s/static/Q_GLOBAL_STATIC/g in QScroller Alternative fix to the strict-aliasing violation warnings Revert "Fix strict-alias breaking warnings with GCC." Fix warning about vSize not being used in this function Do not try to test UnixFDs with the system API because it may be too old L10n: German translations for Qt 4.8 Compile with namespace support. Replace the handcoded math and change the timer buckets again. Move the constants up, preparing for refactoring Fix strict-alias breaking warnings with GCC. Fix compilation if D-Bus 1.4 isn't present. Change the number of entries in the first timer bucket. Change the error message in the timer ID deallocator. Add a benchmark for testing our QtDBus type-validation Move the QDBusPerformance test to the tests/benchmark dir Use the Qt code for validating types in QtDBus Add routines to validate D-Bus signature in QtDBus Remove the unused QDBusUnixFileDescriptor::isShared function Doc: document the QDBusUnixFileDescriptor class Autotest: really ensure that two fds are equal ...
Diffstat (limited to 'src/dbus')
-rw-r--r--src/dbus/dbus.pro6
-rw-r--r--src/dbus/qdbus_symbols_p.h26
-rw-r--r--src/dbus/qdbusargument.cpp28
-rw-r--r--src/dbus/qdbusargument.h4
-rw-r--r--src/dbus/qdbusargument_p.h8
-rw-r--r--src/dbus/qdbusdemarshaller.cpp17
-rw-r--r--src/dbus/qdbusintegrator.cpp26
-rw-r--r--src/dbus/qdbusmarshaller.cpp24
-rw-r--r--src/dbus/qdbusmetatype.cpp16
-rw-r--r--src/dbus/qdbusmetatype_p.h1
-rw-r--r--src/dbus/qdbusunixfiledescriptor.cpp316
-rw-r--r--src/dbus/qdbusunixfiledescriptor.h103
-rw-r--r--src/dbus/qdbusutil.cpp100
-rw-r--r--src/dbus/qdbusutil_p.h4
14 files changed, 659 insertions, 20 deletions
diff --git a/src/dbus/dbus.pro b/src/dbus/dbus.pro
index 52ed217..08c9ea1 100644
--- a/src/dbus/dbus.pro
+++ b/src/dbus/dbus.pro
@@ -59,7 +59,8 @@ HEADERS += $$PUB_HEADERS \
qdbusintegrator_p.h \
qdbuspendingcall_p.h \
qdbus_symbols_p.h \
- qdbusservicewatcher.h
+ qdbusservicewatcher.h \
+ qdbusunixfiledescriptor.h
SOURCES += qdbusconnection.cpp \
qdbusconnectioninterface.cpp \
qdbuserror.cpp \
@@ -85,4 +86,5 @@ SOURCES += qdbusconnection.cpp \
qdbuspendingcall.cpp \
qdbuspendingreply.cpp \
qdbus_symbols.cpp \
- qdbusservicewatcher.cpp
+ qdbusservicewatcher.cpp \
+ qdbusunixfiledescriptor.cpp
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index c5f55af..039657e 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -296,6 +296,12 @@ DEFINEFUNC(dbus_bool_t , dbus_message_set_sender, (DBusMessage *message,
DEFINEFUNC(void , dbus_message_unref, (DBusMessage *message),
(message), )
+/* dbus-misc.h */
+DEFINEFUNC(void , dbus_get_version , (int *major_version_p,
+ int *minor_version_p,
+ int *micro_version_p),
+ (major_version_p, minor_version_p, micro_version_p), )
+
/* dbus-pending-call.h */
DEFINEFUNC(dbus_bool_t , dbus_pending_call_set_notify, (DBusPendingCall *pending,
DBusPendingCallNotifyFunction function,
@@ -352,21 +358,17 @@ DEFINEFUNC(dbus_bool_t , dbus_server_set_watch_functions, (DBusServer
DEFINEFUNC(void , dbus_server_unref, (DBusServer *server),
(server), )
-/* dbus-signature.h */
-DEFINEFUNC(dbus_bool_t , dbus_signature_validate, (const char *signature,
- DBusError *error),
- (signature, error), return)
-DEFINEFUNC(dbus_bool_t , dbus_signature_validate_single, (const char *signature,
- DBusError *error),
- (signature, error), return)
-DEFINEFUNC(dbus_bool_t , dbus_type_is_basic, (int typecode),
- (typecode), return)
-DEFINEFUNC(dbus_bool_t , dbus_type_is_fixed, (int typecode),
- (typecode), return)
-
/* dbus-thread.h */
DEFINEFUNC(dbus_bool_t , dbus_threads_init_default, (), (), return)
+
+/* D-Bus 1.4 symbols */
+#if !defined(QT_LINKED_LIBDBUS) || (DBUS_VERSION >= 0x010400)
+DEFINEFUNC(dbus_bool_t , dbus_connection_can_send_type , (DBusConnection *connection,
+ int type),
+ (connection, type), return)
+#endif
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/dbus/qdbusargument.cpp b/src/dbus/qdbusargument.cpp
index 09f0e82..806b7fe 100644
--- a/src/dbus/qdbusargument.cpp
+++ b/src/dbus/qdbusargument.cpp
@@ -487,6 +487,20 @@ QDBusArgument &QDBusArgument::operator<<(const QDBusSignature &arg)
/*!
\overload
+ \since 4.8
+ \internal
+ Appends the primitive value \a arg of type \c{UNIX_FILE_DESCRIPTOR} (Unix
+ File Descriptor) to the D-Bus stream.
+*/
+QDBusArgument &QDBusArgument::operator<<(const QDBusUnixFileDescriptor &arg)
+{
+ if (QDBusArgumentPrivate::checkWrite(d))
+ d->marshaller()->append(arg);
+ return *this;
+}
+
+/*!
+ \overload
Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream.
A D-Bus variant type can contain any type, including other
@@ -729,6 +743,20 @@ const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const
/*!
\overload
+ \since 4.8
+ \internal
+ Extracts one D-Bus primitive argument of type \c{UNIX_FILE_DESCRIPTOR}
+ (Unix file descriptor) from the D-Bus stream.
+*/
+const QDBusArgument &QDBusArgument::operator>>(QDBusUnixFileDescriptor &arg) const
+{
+ if (QDBusArgumentPrivate::checkReadAndDetach(d))
+ arg = d->demarshaller()->toUnixFileDescriptor();
+ return *this;
+}
+
+/*!
+ \overload
Extracts one D-Bus primitive argument of type \c{VARIANT} from the
D-Bus stream.
diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h
index e331d8f..f80723e 100644
--- a/src/dbus/qdbusargument.h
+++ b/src/dbus/qdbusargument.h
@@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE
QT_MODULE(DBus)
+class QDBusUnixFileDescriptor;
+
class QDBusArgumentPrivate;
class QDBusDemarshaller;
class QDBusMarshaller;
@@ -96,6 +98,7 @@ public:
QDBusArgument &operator<<(const QDBusVariant &arg);
QDBusArgument &operator<<(const QDBusObjectPath &arg);
QDBusArgument &operator<<(const QDBusSignature &arg);
+ QDBusArgument &operator<<(const QDBusUnixFileDescriptor &arg);
QDBusArgument &operator<<(const QStringList &arg);
QDBusArgument &operator<<(const QByteArray &arg);
@@ -127,6 +130,7 @@ public:
const QDBusArgument &operator>>(QDBusVariant &arg) const;
const QDBusArgument &operator>>(QDBusObjectPath &arg) const;
const QDBusArgument &operator>>(QDBusSignature &arg) const;
+ const QDBusArgument &operator>>(QDBusUnixFileDescriptor &arg) const;
const QDBusArgument &operator>>(QStringList &arg) const;
const QDBusArgument &operator>>(QByteArray &arg) const;
diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h
index 89a383f..1c713a3 100644
--- a/src/dbus/qdbusargument_p.h
+++ b/src/dbus/qdbusargument_p.h
@@ -54,10 +54,16 @@
//
#include <qdbusargument.h>
+#include "qdbusunixfiledescriptor.h"
#include "qdbus_symbols_p.h"
#ifndef QT_NO_DBUS
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
+#endif
+
QT_BEGIN_NAMESPACE
class QDBusMarshaller;
@@ -117,6 +123,7 @@ public:
void append(const QString &arg);
void append(const QDBusObjectPath &arg);
void append(const QDBusSignature &arg);
+ void append(const QDBusUnixFileDescriptor &arg);
void append(const QStringList &arg);
void append(const QByteArray &arg);
bool append(const QDBusVariant &arg); // this one can fail
@@ -172,6 +179,7 @@ public:
QString toString();
QDBusObjectPath toObjectPath();
QDBusSignature toSignature();
+ QDBusUnixFileDescriptor toUnixFileDescriptor();
QDBusVariant toVariant();
QStringList toStringList();
QByteArray toByteArray();
diff --git a/src/dbus/qdbusdemarshaller.cpp b/src/dbus/qdbusdemarshaller.cpp
index 111122e..3910381 100644
--- a/src/dbus/qdbusdemarshaller.cpp
+++ b/src/dbus/qdbusdemarshaller.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qdbusargument_p.h"
+#include "qdbusconnection.h"
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -126,6 +127,13 @@ inline QDBusSignature QDBusDemarshaller::toSignature()
return QDBusSignature(QString::fromUtf8(qIterGet<char *>(&iterator)));
}
+inline QDBusUnixFileDescriptor QDBusDemarshaller::toUnixFileDescriptor()
+{
+ QDBusUnixFileDescriptor fd;
+ fd.giveFileDescriptor(qIterGet<dbus_int32_t>(&iterator));
+ return fd;
+}
+
inline QDBusVariant QDBusDemarshaller::toVariant()
{
QDBusDemarshaller sub(capabilities);
@@ -173,6 +181,10 @@ QDBusArgument::ElementType QDBusDemarshaller::currentType()
case DBUS_TYPE_DICT_ENTRY:
return QDBusArgument::MapEntryType;
+ case DBUS_TYPE_UNIX_FD:
+ return capabilities & QDBusConnection::UnixFileDescriptorPassing ?
+ QDBusArgument::BasicType : QDBusArgument::UnknownType;
+
case DBUS_TYPE_INVALID:
return QDBusArgument::UnknownType;
@@ -231,6 +243,11 @@ QVariant QDBusDemarshaller::toVariantInternal()
case DBUS_TYPE_STRUCT:
return QVariant::fromValue(duplicate());
+ case DBUS_TYPE_UNIX_FD:
+ if (capabilities & QDBusConnection::UnixFileDescriptorPassing)
+ return qVariantFromValue(toUnixFileDescriptor());
+ // fall through
+
default:
// qWarning("QDBusDemarshaller: Found unknown D-Bus type %d '%c'",
// q_dbus_message_iter_get_arg_type(&iterator),
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 5f4dadd..5d53390 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -1666,6 +1666,31 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection);
}
+static QDBusConnection::ConnectionCapabilities connectionCapabilies(DBusConnection *connection)
+{
+ QDBusConnection::ConnectionCapabilities result = 0;
+
+#if defined(QT_LINKED_LIBDBUS) && DBUS_VERSION < 0x010400
+ // no capabilities are possible
+#else
+# if !defined(QT_LINKED_LIBDBUS)
+ // run-time check if the next functions are available
+ int major, minor, micro;
+ q_dbus_get_version(&major, &minor, &micro);
+ if (major == 1 && minor < 4)
+ return result;
+# endif
+
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+#endif
+ if (q_dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
+ result |= QDBusConnection::UnixFileDescriptorPassing;
+#endif
+
+ return result;
+}
+
void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusErrorInternal &error)
{
if (!dbc) {
@@ -1679,6 +1704,7 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError
const char *service = q_dbus_bus_get_unique_name(connection);
Q_ASSERT(service);
baseService = QString::fromUtf8(service);
+ capabilities = connectionCapabilies(connection);
q_dbus_connection_set_exit_on_disconnect(connection, false);
q_dbus_connection_set_watch_functions(connection, qDBusAddWatch, qDBusRemoveWatch,
diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp
index 76d76cc..6dec359 100644
--- a/src/dbus/qdbusmarshaller.cpp
+++ b/src/dbus/qdbusmarshaller.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qdbusargument_p.h"
+#include "qdbusconnection.h"
#include "qdbusmetatype_p.h"
#include "qdbusutil_p.h"
@@ -138,6 +139,16 @@ inline void QDBusMarshaller::append(const QDBusSignature &arg)
qIterAppend(&iterator, ba, DBUS_TYPE_SIGNATURE, &cdata);
}
+inline void QDBusMarshaller::append(const QDBusUnixFileDescriptor &arg)
+{
+ int fd = arg.fileDescriptor();
+ if (!ba && fd == -1) {
+ error(QLatin1String("Invalid file descriptor passed in arguments"));
+ } else {
+ qIterAppend(&iterator, ba, DBUS_TYPE_UNIX_FD, &fd);
+ }
+}
+
inline void QDBusMarshaller::append(const QByteArray &arg)
{
if (ba) {
@@ -243,7 +254,7 @@ inline QDBusMarshaller *QDBusMarshaller::beginMap(int kid, int vid)
.arg(QLatin1String(QVariant::typeToName(QVariant::Type(kid)))));
return this;
}
- if (ksignature[1] != 0 || !q_dbus_type_is_basic(*ksignature)) {
+ if (ksignature[1] != 0 || !QDBusUtil::isValidBasicType(*ksignature)) {
qWarning("QDBusMarshaller: type '%s' (%d) cannot be used as the key type in a D-BUS map.",
QVariant::typeToName( QVariant::Type(kid) ), kid);
error(QString::fromLatin1("Type %1 passed in arguments cannot be used as a key in a map")
@@ -474,6 +485,13 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg)
qFatal("QDBusMarshaller::appendVariantInternal got a DICT_ENTRY!");
return false;
+ case DBUS_TYPE_UNIX_FD:
+ if (capabilities & QDBusConnection::UnixFileDescriptorPassing || ba) {
+ append(qvariant_cast<QDBusUnixFileDescriptor>(arg));
+ return true;
+ }
+ // fall through
+
default:
qWarning("QDBusMarshaller::appendVariantInternal: Found unknown D-BUS type '%s'",
signature);
@@ -493,7 +511,7 @@ bool QDBusMarshaller::appendRegisteredType(const QVariant &arg)
bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller)
{
int code = q_dbus_message_iter_get_arg_type(&demarshaller->iterator);
- if (q_dbus_type_is_basic(code)) {
+ if (QDBusUtil::isValidBasicType(code)) {
// easy: just append
// do exactly like the D-BUS docs suggest
// (see apidocs for q_dbus_message_iter_get_basic)
@@ -507,7 +525,7 @@ bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller)
if (code == DBUS_TYPE_ARRAY) {
int element = q_dbus_message_iter_get_element_type(&demarshaller->iterator);
- if (q_dbus_type_is_fixed(element)) {
+ if (QDBusUtil::isValidFixedType(element) && element != DBUS_TYPE_UNIX_FD) {
// another optimization: fixed size arrays
// code is exactly like QDBusDemarshaller::toByteArray
DBusMessageIter sub;
diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp
index 9f29205..9d9112c 100644
--- a/src/dbus/qdbusmetatype.cpp
+++ b/src/dbus/qdbusmetatype.cpp
@@ -50,12 +50,18 @@
#include <qvector.h>
#include "qdbusmessage.h"
+#include "qdbusunixfiledescriptor.h"
#include "qdbusutil_p.h"
#include "qdbusmetatype_p.h"
#include "qdbusargument_p.h"
#ifndef QT_NO_DBUS
+#ifndef DBUS_TYPE_UNIX_FD
+# define DBUS_TYPE_UNIX_FD int('h')
+# define DBUS_TYPE_UNIX_FD_AS_STRING "h"
+#endif
+
Q_DECLARE_METATYPE(QList<bool>)
Q_DECLARE_METATYPE(QList<short>)
Q_DECLARE_METATYPE(QList<ushort>)
@@ -96,6 +102,7 @@ int QDBusMetaTypeId::variant;
int QDBusMetaTypeId::objectpath;
int QDBusMetaTypeId::signature;
int QDBusMetaTypeId::error;
+int QDBusMetaTypeId::unixfd;
void QDBusMetaTypeId::init()
{
@@ -110,7 +117,8 @@ void QDBusMetaTypeId::init()
variant = qRegisterMetaType<QDBusVariant>("QDBusVariant");
objectpath = qRegisterMetaType<QDBusObjectPath>("QDBusObjectPath");
signature = qRegisterMetaType<QDBusSignature>("QDBusSignature");
- error = qRegisterMetaType<QDBusError>("QDBusError");
+ error = qRegisterMetaType<QDBusError>("QDBusError");
+ unixfd = qRegisterMetaType<QDBusUnixFileDescriptor>("QDBusUnixFileDescriptor");
#ifndef QDBUS_NO_SPECIALTYPES
// and register QtCore's with us
@@ -139,6 +147,7 @@ void QDBusMetaTypeId::init()
qDBusRegisterMetaType<QList<double> >();
qDBusRegisterMetaType<QList<QDBusObjectPath> >();
qDBusRegisterMetaType<QList<QDBusSignature> >();
+ qDBusRegisterMetaType<QList<QDBusUnixFileDescriptor> >();
#endif
initialized = true;
@@ -343,6 +352,9 @@ int QDBusMetaType::signatureToType(const char *signature)
case DBUS_TYPE_SIGNATURE:
return QDBusMetaTypeId::signature;
+ case DBUS_TYPE_UNIX_FD:
+ return QDBusMetaTypeId::unixfd;
+
case DBUS_TYPE_VARIANT:
return QDBusMetaTypeId::variant;
@@ -432,6 +444,8 @@ const char *QDBusMetaType::typeToSignature(int type)
return DBUS_TYPE_OBJECT_PATH_AS_STRING;
else if (type == QDBusMetaTypeId::signature)
return DBUS_TYPE_SIGNATURE_AS_STRING;
+ else if (type == QDBusMetaTypeId::unixfd)
+ return DBUS_TYPE_UNIX_FD_AS_STRING;
// try the database
QVector<QDBusCustomTypeInfo> *ct = customTypes();
diff --git a/src/dbus/qdbusmetatype_p.h b/src/dbus/qdbusmetatype_p.h
index 2fce133..b931c75 100644
--- a/src/dbus/qdbusmetatype_p.h
+++ b/src/dbus/qdbusmetatype_p.h
@@ -65,6 +65,7 @@ struct QDBusMetaTypeId
static int objectpath; // QDBusObjectPath
static int signature; // QDBusSignature
static int error; // QDBusError
+ static int unixfd; // QDBusUnixFileDescriptor
static void init();
};
diff --git a/src/dbus/qdbusunixfiledescriptor.cpp b/src/dbus/qdbusunixfiledescriptor.cpp
new file mode 100644
index 0000000..f45b6cc
--- /dev/null
+++ b/src/dbus/qdbusunixfiledescriptor.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qdbusunixfiledescriptor.h"
+#include <QSharedData>
+
+#ifdef Q_OS_UNIX
+# include <private/qcore_unix_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDBusUnixFileDescriptor
+ \inmodule QtDBus
+ \since 4.8
+
+ \brief The QDBusUnixFileDescriptor class holds one Unix file descriptor.
+
+ The QDBusUnixFileDescriptor class is used to hold one Unix file
+ descriptor for use with the QtDBus module. This allows applications to
+ send and receive Unix file descriptors over the D-Bus connection, mapping
+ automatically to the D-Bus type 'h'.
+
+ Objects of type QDBusUnixFileDescriptors can be used also as parameters
+ in signals and slots that get exported to D-Bus by registering with
+ QDBusConnection::registerObject.
+
+ QDBusUnixFileDescriptor does not take ownership of the file descriptor.
+ Instead, it will use the Unix system call \c dup(2) to make a copy of the
+ file descriptor. This file descriptor belongs to the
+ QDBusUnixFileDescriptor object and should not be stored or closed by the
+ user. Instead, you should make your own copy if you need that.
+
+ \section2 Availability
+
+ Unix file descriptor passing is not available in all D-Bus connections.
+ This feature is present with D-Bus library and bus daemon version 1.4 and
+ upwards on Unix systems. QtDBus automatically enables the feature if such
+ a version was found at compile-time and run-time.
+
+ To verify that your connection does support passing file descriptors,
+ check if the QDBusConnection::UnixFileDescriptorPassing capability is set
+ with QDBusConnection::connectionCapabilities(). If the flag is not
+ active, then you will not be able to make calls to methods that have
+ QDBusUnixFileDescriptor as arguments or even embed such a type in a
+ variant. You will also not receive calls containing that type.
+
+ Note also that remote applications may not have support for Unix file
+ descriptor passing. If you make a D-Bus to a remote application that
+ cannot receive such a type, you will receive an error reply. If you try
+ to send a signal containing a D-Bus file descriptor or return one from a
+ method call, the message will be silently dropped.
+
+ Even if the feature is not available, QDBusUnixFileDescriptor will
+ continue to operate, so code need not have compile-time checks for the
+ availability of this feature.
+
+ On non-Unix systems, QDBusUnixFileDescriptor will always report an
+ invalid state and QDBusUnixFileDescriptor::isSupported() will return
+ false.
+
+ \sa QDBusConnection::ConnectionCapabilities, QDBusConnection::connectionCapabilities
+*/
+
+class QDBusUnixFileDescriptorPrivate : public QSharedData {
+public:
+ QDBusUnixFileDescriptorPrivate() : fd(-1) { }
+ QDBusUnixFileDescriptorPrivate(const QDBusUnixFileDescriptorPrivate &other)
+ : QSharedData(other), fd(-1)
+ { }
+ ~QDBusUnixFileDescriptorPrivate();
+
+ QAtomicInt fd;
+};
+
+template<> inline
+QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate>::~QExplicitlySharedDataPointer()
+{ if (d && !d->ref.deref()) delete d; }
+
+/*!
+ Constructs a QDBusUnixFileDescriptor without a wrapped file descriptor.
+ This is equivalent to constructing the object with an invalid file
+ descriptor (like -1).
+
+ \sa fileDescriptor, isValid
+*/
+QDBusUnixFileDescriptor::QDBusUnixFileDescriptor()
+ : d(0)
+{
+}
+
+/*!
+ Constructs a QDBusUnixFileDescriptor object by copying the \a
+ fileDescriptor parameter. The original file descriptor is not touched and
+ must be closed by the user.
+
+ Note that the value returned by fileDescriptor() will be different from
+ the \a fileDescriptor parameter passed.
+
+ If the \a fileDescriptor parameter is not valid, isValid() will return
+ false and fileDescriptor() will return -1.
+
+ \sa setFileDescriptor, fileDescriptor
+*/
+QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(int fileDescriptor)
+ : d(0)
+{
+ if (fileDescriptor != -1)
+ setFileDescriptor(fileDescriptor);
+}
+
+/*!
+ Constructs a QDBusUnixFileDescriptor object by copying \a other.
+*/
+QDBusUnixFileDescriptor::QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other)
+ : d(other.d)
+{
+}
+
+/*!
+ Copies the Unix file descriptor from the \a other QDBusUnixFileDescriptor
+ object. If the current object contained a file descriptor, it will be
+ properly disposed of before.
+*/
+QDBusUnixFileDescriptor &QDBusUnixFileDescriptor::operator=(const QDBusUnixFileDescriptor &other)
+{
+ if (this != &other)
+ d.operator=(other.d);
+ return *this;
+}
+
+/*!
+ Destroys this QDBusUnixFileDescriptor object and disposes of the Unix file descriptor that it contained.
+*/
+QDBusUnixFileDescriptor::~QDBusUnixFileDescriptor()
+{
+}
+
+/*!
+ Returns true if this Unix file descriptor is valid. A valid Unix file
+ descriptor is not -1.
+
+ \sa fileDescriptor()
+*/
+bool QDBusUnixFileDescriptor::isValid() const
+{
+ return d ? d->fd != -1 : false;
+}
+
+/*!
+ Returns the Unix file descriptor contained by this
+ QDBusUnixFileDescriptor object. An invalid file descriptor is represented
+ by the value -1.
+
+ Note that the file descriptor returned by this function is owned by the
+ QDBusUnixFileDescriptor object and must not be stored past the lifetime
+ of this object. It is ok to use it while this object is valid, but if one
+ wants to store it for longer use, the file descriptor should be cloned
+ using the Unix \c dup(2), \c dup2(2) or \c dup3(2) functions.
+
+ \sa isValid()
+*/
+int QDBusUnixFileDescriptor::fileDescriptor() const
+{
+ return d ? d->fd.operator int() : -1;
+}
+
+// actual implementation
+#ifdef Q_OS_UNIX
+
+// qdoc documentation is generated on Unix
+
+/*!
+ Returns true if Unix file descriptors are supported on this platform. In
+ other words, this function returns true if this is a Unix platform.
+
+ Note that QDBusUnixFileDescriptor continues to operate even if this
+ function returns false. The only difference is that the
+ QDBusUnixFileDescriptor objects will always be in the isValid() == false
+ state and fileDescriptor() will always return -1. The class will not
+ consume any operating system resources.
+*/
+bool QDBusUnixFileDescriptor::isSupported()
+{
+ return true;
+}
+
+/*!
+ Sets the file descriptor that this QDBusUnixFileDescriptor object holds
+ to a copy of \a fileDescriptor.T he original file descriptor is not
+ touched and must be closed by the user.
+
+ Note that the value returned by fileDescriptor() will be different from
+ the \a fileDescriptor parameter passed.
+
+ If the \a fileDescriptor parameter is not valid, isValid() will return
+ false and fileDescriptor() will return -1.
+
+ \sa isValid(), fileDescriptor()
+*/
+void QDBusUnixFileDescriptor::setFileDescriptor(int fileDescriptor)
+{
+ if (fileDescriptor != -1)
+ giveFileDescriptor(qt_safe_dup(fileDescriptor));
+}
+
+/*!
+ \internal
+ Sets the Unix file descriptor to \a fileDescriptor without copying.
+
+ \sa setFileDescriptor()
+*/
+void QDBusUnixFileDescriptor::giveFileDescriptor(int fileDescriptor)
+{
+ // if we are the sole ref, d remains unchanged
+ // if detaching happens, d->fd will be -1
+ if (d)
+ d.detach();
+ else
+ d = new QDBusUnixFileDescriptorPrivate;
+
+ if (d->fd != -1)
+ qt_safe_close(d->fd);
+
+ if (fileDescriptor != -1)
+ d->fd = fileDescriptor;
+}
+
+/*!
+ \internal
+ Extracts the Unix file descriptor from the QDBusUnixFileDescriptor object
+ and transfers ownership.
+
+ Note: since QDBusUnixFileDescriptor is implicitly shared, this function
+ is inherently racy and should be avoided.
+*/
+int QDBusUnixFileDescriptor::takeFileDescriptor()
+{
+ if (!d)
+ return -1;
+
+ return d->fd.fetchAndStoreRelaxed(-1);
+}
+
+QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
+{
+ if (fd != -1)
+ qt_safe_close(fd);
+}
+
+#else
+bool QDBusUnixFileDescriptor::isSupported()
+{
+ return false;
+}
+
+void QDBusUnixFileDescriptor::setFileDescriptor(int)
+{
+}
+
+void QDBusUnixFileDescriptor::giveFileDescriptor(int)
+{
+}
+
+int QDBusUnixFileDescriptor::takeFileDescriptor()
+{
+ return -1;
+}
+
+QDBusUnixFileDescriptorPrivate::~QDBusUnixFileDescriptorPrivate()
+{
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/dbus/qdbusunixfiledescriptor.h b/src/dbus/qdbusunixfiledescriptor.h
new file mode 100644
index 0000000..d0a2f3c
--- /dev/null
+++ b/src/dbus/qdbusunixfiledescriptor.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the FOO module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QDBUSUNIXFILEDESCRIPTOR_H
+#define QDBUSUNIXFILEDESCRIPTOR_H
+
+#include <QtCore/QSharedDataPointer>
+#include <QtDBus/qdbusmacros.h>
+
+#ifndef QT_NO_DBUS
+
+#ifdef Q_COMPILER_RVALUE_REFS
+# include <utility>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(DBus)
+
+class QDBusUnixFileDescriptorPrivate;
+template<> QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate>::~QExplicitlySharedDataPointer();
+
+class Q_DBUS_EXPORT QDBusUnixFileDescriptor
+{
+public:
+ QDBusUnixFileDescriptor();
+ explicit QDBusUnixFileDescriptor(int fileDescriptor);
+ QDBusUnixFileDescriptor(const QDBusUnixFileDescriptor &other);
+ QDBusUnixFileDescriptor &operator=(const QDBusUnixFileDescriptor &other);
+ ~QDBusUnixFileDescriptor();
+
+ bool isValid() const;
+
+ int fileDescriptor() const;
+ void setFileDescriptor(int fileDescriptor);
+
+ void giveFileDescriptor(int fileDescriptor);
+ int takeFileDescriptor();
+
+ static bool isSupported();
+
+#if defined(Q_COMPILER_RVALUE_REFS)
+ QDBusUnixFileDescriptor(QDBusUnixFileDescriptor &&other) : d(static_cast<Data &&>(other.d))
+ { }
+ inline QDBusUnixFileDescriptor &operator=(QDBusUnixFileDescriptor &&other)
+ { d.swap(other.d); return *this; }
+#endif
+
+protected:
+ typedef QExplicitlySharedDataPointer<QDBusUnixFileDescriptorPrivate> Data;
+ Data d;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QDBusUnixFileDescriptor)
+Q_DECLARE_METATYPE(QList<QDBusUnixFileDescriptor>)
+
+QT_END_HEADER
+
+#endif // QT_NO_DBUS
+#endif // QDBUSUNIXFILEDESCRIPTOR_H
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp
index 9730f54..a4bd168 100644
--- a/src/dbus/qdbusutil.cpp
+++ b/src/dbus/qdbusutil.cpp
@@ -46,6 +46,7 @@
#include <QtCore/qstringlist.h>
#include "qdbusargument.h"
+#include "qdbusunixfiledescriptor.h"
#ifndef QT_NO_DBUS
@@ -130,6 +131,10 @@ static bool variantToString(const QVariant &arg, QString &out)
} else if (argType == qMetaTypeId<QDBusSignature>()) {
out += QLatin1String("[Signature: ") + qvariant_cast<QDBusSignature>(arg).signature();
out += QLatin1Char(']');
+ } else if (argType == qMetaTypeId<QDBusUnixFileDescriptor>()) {
+ out += QLatin1String("[Unix FD: ");
+ out += QLatin1String(qvariant_cast<QDBusUnixFileDescriptor>(arg).isValid() ? "valid" : "not valid");
+ out += QLatin1Char(']');
} else if (argType == qMetaTypeId<QDBusVariant>()) {
const QVariant v = qvariant_cast<QDBusVariant>(arg).variant();
out += QLatin1String("[Variant");
@@ -233,6 +238,68 @@ bool argToString(const QDBusArgument &busArg, QString &out)
return true;
}
+//------- D-Bus Types --------
+static const char oneLetterTypes[] = "vsogybnqiuxtdh";
+static const char basicTypes[] = "sogybnqiuxtdh";
+static const char fixedTypes[] = "ybnqiuxtdh";
+
+static bool isBasicType(int c)
+{
+ return c != DBUS_TYPE_INVALID && strchr(basicTypes, c) != NULL;
+}
+
+static bool isFixedType(int c)
+{
+ return c != DBUS_TYPE_INVALID && strchr(fixedTypes, c) != NULL;
+}
+
+// Returns a pointer to one-past-end of this type if it's valid;
+// returns NULL if it isn't valid.
+static const char *validateSingleType(const char *signature)
+{
+ register char c = *signature;
+ if (c == DBUS_TYPE_INVALID)
+ return false;
+
+ // is it one of the one-letter types?
+ if (strchr(oneLetterTypes, c) != NULL)
+ return signature + 1;
+
+ // is it an array?
+ if (c == DBUS_TYPE_ARRAY) {
+ // then it's valid if the next type is valid
+ // or if it's a dict-entry
+ c = *++signature;
+ if (c == DBUS_DICT_ENTRY_BEGIN_CHAR) {
+ // beginning of a dictionary entry
+ // a dictionary entry has a key which is of basic types
+ // and a free value
+ c = *++signature;
+ if (!isBasicType(c))
+ return 0;
+ signature = validateSingleType(signature + 1);
+ return signature && *signature == DBUS_DICT_ENTRY_END_CHAR ? signature + 1 : 0;
+ }
+
+ return validateSingleType(signature);
+ }
+
+ if (c == DBUS_STRUCT_BEGIN_CHAR) {
+ // beginning of a struct
+ ++signature;
+ while (true) {
+ signature = validateSingleType(signature);
+ if (!signature)
+ return 0;
+ if (*signature == DBUS_STRUCT_END_CHAR)
+ return signature + 1;
+ }
+ }
+
+ // invalid/unknown type
+ return 0;
+}
+
/*!
\namespace QDBusUtil
\inmodule QtDBus
@@ -442,6 +509,25 @@ namespace QDBusUtil
}
/*!
+ \fn bool QDBusUtil::isValidBasicType(int type)
+ Returns true if \a c is a valid, basic D-Bus type.
+ */
+ bool isValidBasicType(int c)
+ {
+ return isBasicType(c);
+ }
+
+ /*!
+ \fn bool QDBusUtil::isValidFixedType(int type)
+ Returns true if \a c is a valid, fixed D-Bus type.
+ */
+ bool isValidFixedType(int c)
+ {
+ return isFixedType(c);
+ }
+
+
+ /*!
\fn bool QDBusUtil::isValidSignature(const QString &signature)
Returns true if \a signature is a valid D-Bus type signature for one or more types.
This function returns true if it can all of \a signature into valid, individual types and no
@@ -451,7 +537,15 @@ namespace QDBusUtil
*/
bool isValidSignature(const QString &signature)
{
- return q_dbus_signature_validate(signature.toUtf8(), 0);
+ QByteArray ba = signature.toLatin1();
+ const char *data = ba.constData();
+ while (true) {
+ data = validateSingleType(data);
+ if (!data)
+ return false;
+ if (*data == '\0')
+ return true;
+ }
}
/*!
@@ -462,7 +556,9 @@ namespace QDBusUtil
*/
bool isValidSingleSignature(const QString &signature)
{
- return q_dbus_signature_validate_single(signature.toUtf8(), 0);
+ QByteArray ba = signature.toLatin1();
+ const char *data = validateSingleType(ba.constData());
+ return data && *data == '\0';
}
} // namespace QDBusUtil
diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h
index 3721e98..24b5cea 100644
--- a/src/dbus/qdbusutil_p.h
+++ b/src/dbus/qdbusutil_p.h
@@ -81,6 +81,10 @@ namespace QDBusUtil
Q_DBUS_EXPORT bool isValidObjectPath(const QString &path);
+ Q_DBUS_EXPORT bool isValidFixedType(int c);
+
+ Q_DBUS_EXPORT bool isValidBasicType(int c);
+
Q_DBUS_EXPORT bool isValidSignature(const QString &signature);
Q_DBUS_EXPORT bool isValidSingleSignature(const QString &signature);