source: trunk/src/gui/embedded/qunixsocket.cpp@ 1016

Last change on this file since 1016 was 846, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 54.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qunixsocket_p.h"
43
44// #define QUNIXSOCKET_DEBUG 1
45
46#include <QtCore/qsocketnotifier.h>
47#include <QtCore/qqueue.h>
48#include <QtCore/qdatetime.h>
49#include "private/qcore_unix_p.h" // overrides QT_OPEN
50
51#ifdef QUNIXSOCKET_DEBUG
52#include <QtCore/qdebug.h>
53#endif
54
55extern "C" {
56#include <unistd.h>
57#include <string.h>
58#include <errno.h>
59#include <sys/socket.h>
60#include <sys/un.h>
61};
62
63#define UNIX_PATH_MAX 108 // From unix(7)
64
65#ifdef QT_LINUXBASE
66// LSB doesn't declare ucred
67struct ucred
68{
69 pid_t pid; /* PID of sending process. */
70 uid_t uid; /* UID of sending process. */
71 gid_t gid; /* GID of sending process. */
72};
73
74// LSB doesn't define the ones below
75#ifndef SO_PASSCRED
76# define SO_PASSCRED 16
77#endif
78#ifndef SCM_CREDENTIALS
79# define SCM_CREDENTIALS 0x02
80#endif
81#ifndef MSG_DONTWAIT
82# define MSG_DONTWAIT 0x40
83#endif
84#ifndef MSG_NOSIGNAL
85# define MSG_NOSIGNAL 0x4000
86#endif
87
88#endif // QT_LINUXBASE
89
90QT_BEGIN_NAMESPACE
91
92///////////////////////////////////////////////////////////////////////////////
93// class QUnixSocketRights
94///////////////////////////////////////////////////////////////////////////////
95/*!
96 \class QUnixSocketRights
97 \internal
98
99 \brief The QUnixSocketRights class encapsulates QUnixSocket rights data.
100 \omit
101 \ingroup Platform::DeviceSpecific
102 \ingroup Platform::OS
103 \ingroup Platform::Communications
104 \endomit
105 \ingroup qws
106
107 \l QUnixSocket allows you to transfer Unix file descriptors between processes.
108 A file descriptor is referred to as "rights data" as it allows one process to
109 transfer its right to access a resource to another.
110
111 The Unix system verifies resource permissions only when the resource is first
112 opened. For example, consider a file on disk readable only by the user "qt".
113 A process running as user "qt" will be able to open this file for reading.
114 If, while the process was still reading from the file, the ownership was
115 changed from user "qt" to user "root", the process would be allowed to
116 continue reading from the file, even though attempting to reopen the file
117 would be denied. Permissions are associated with special descriptors called
118 file descriptors which are returned to a process after it initially opens a
119 resource.
120
121 File descriptors can be duplicated within a process through the dup(2) system
122 call. File descriptors can be passed between processes using the
123 \l QUnixSocket class in the same way. Even though the receiving process never
124 opened the resource directly, it has the same permissions to access it as the
125 process that did.
126
127 \sa QUnixSocket
128 */
129struct QUnixSocketRightsPrivate : public QSharedData
130{
131 virtual ~QUnixSocketRightsPrivate() {
132#ifdef QUNIXSOCKET_DEBUG
133 int closerv =
134#endif
135 QT_CLOSE(fd);
136#ifdef QUNIXSOCKET_DEBUG
137 if(0 != closerv) {
138 qDebug() << "QUnixSocketRightsPrivate: Unable to close managed"
139 " file descriptor (" << ::strerror(errno) << ')';
140 }
141#endif
142 }
143
144 int fd;
145};
146
147/*!
148 Create a new QUnixSocketRights instance containing the file descriptor \a fd.
149 \a fd will be dup(2)'d internally, so the application is free to close \a fd
150 following this call.
151
152 If the dup(2) fails, or you pass an invalid \a fd, an
153 \l {QUnixSocketRights::isValid()}{invalid } object will be
154 constructed.
155
156 QUnixSocketRights instances are immutable and the internal file descriptor
157 will be shared between any copies made of this object. The system will
158 close(2) the file descriptor once it is no longer needed.
159 */
160QUnixSocketRights::QUnixSocketRights(int fd)
161{
162 d = new QUnixSocketRightsPrivate();
163 if(-1 == fd) {
164 d->fd = -1;
165 } else {
166 d->fd = qt_safe_dup(fd);
167#ifdef QUNIXSOCKET_DEBUG
168 if(-1 == d->fd) {
169 qDebug() << "QUnixSocketRights: Unable to duplicate fd "
170 << fd << " (" << ::strerror(errno) << ')';
171 }
172#endif
173 }
174}
175
176/*!
177 \internal
178
179 Construct a QUnixSocketRights instance on \a fd without dup(2)'ing the file
180 descriptor.
181 */
182QUnixSocketRights::QUnixSocketRights(int fd,int)
183{
184 Q_ASSERT(-1 != fd);
185 d = new QUnixSocketRightsPrivate();
186 d->fd = fd;
187}
188
189/*!
190 Destroys the QUnixSocketRights instance.
191 */
192QUnixSocketRights::~QUnixSocketRights()
193{
194}
195
196/*!
197 Create a copy of \a other.
198 */
199QUnixSocketRights &
200QUnixSocketRights::operator=(const QUnixSocketRights & other)
201{
202 d = other.d;
203 return *this;
204}
205
206/*!
207 Create a copy of \a other.
208 */
209QUnixSocketRights::QUnixSocketRights(const QUnixSocketRights & other)
210: d(other.d)
211{
212}
213
214/*!
215 Returns true if this QUnixSocketRights instance is managing a valid file
216 descriptor. This method is equivalent to (-1 != peekFd()).
217
218 \sa QUnixSocketRights::peekFd()
219 */
220bool QUnixSocketRights::isValid() const
221{
222 return d->fd != -1;
223}
224
225/*!
226 Return a duplicate of the file descriptor contained in this object. If this
227 is an \l {QUnixSocketRights::isValid()}{invalid } object, or the
228 dup(2) call fails, an invalid file descriptor (-1) will be returned.
229
230 \sa QUnixSocketRights::peekFd()
231 */
232int QUnixSocketRights::dupFd() const
233{
234 if(-1 == d->fd) return -1;
235
236 int rv = qt_safe_dup(d->fd);
237
238#ifdef QUNIXSOCKET_DEBUG
239 if(-1 == rv)
240 qDebug() << "QUnixSocketRights: Unable to duplicate managed file "
241 "descriptor (" << ::strerror(errno) << ')';
242#endif
243
244 return rv;
245}
246
247/*!
248 Returns the file descriptor contained in this object. If this
249 is an \l {QUnixSocketRights::isValid()}{invalid } object an invalid
250 file descriptor (-1) will be returned.
251
252 The lifetime of this file descriptor is tied to the lifetime of the
253 QUnixSocketRights instance. The file descriptor returned by this method
254 \e may be close(2)'d when the QUnixSocketRights instance is destroyed. If
255 you want to continue to use the file descriptor use
256 \l QUnixSocketRights::dupFd() instead.
257
258 \sa QUnixSocketRights::dupFd()
259 */
260int QUnixSocketRights::peekFd() const
261{
262 return d->fd;
263}
264
265///////////////////////////////////////////////////////////////////////////////
266// class QUnixSocketMessage
267///////////////////////////////////////////////////////////////////////////////
268struct QUnixSocketMessagePrivate : public QSharedData
269{
270 QUnixSocketMessagePrivate()
271 : state(Default), vec(0), iovecLen(0), dataSize(0) {}
272 QUnixSocketMessagePrivate(const QByteArray & b)
273 : bytes(b), state(Default), vec(0), iovecLen(0), dataSize(0) {}
274 QUnixSocketMessagePrivate(const QByteArray & b,
275 const QList<QUnixSocketRights> & r)
276 : bytes(b), rights(r), state(Default), vec(0), iovecLen(0), dataSize(0) {}
277
278 int size() const { return vec ? dataSize : bytes.size(); }
279 void removeBytes( unsigned int );
280
281 QByteArray bytes;
282 QList<QUnixSocketRights> rights;
283
284 enum AncillaryDataState {
285 Default = 0x00,
286 Truncated = 0x01,
287 Credential = 0x02
288 };
289 AncillaryDataState state;
290
291 pid_t pid;
292 gid_t gid;
293 uid_t uid;
294
295 ::iovec *vec;
296 int iovecLen; // number of vectors in array
297 int dataSize; // total size of vectors = payload
298};
299
300/*!
301 \internal
302 Remove \a bytesToDequeue bytes from the front of this message
303*/
304void QUnixSocketMessagePrivate::removeBytes( unsigned int bytesToDequeue )
305{
306 if ( vec )
307 {
308 ::iovec *vecPtr = vec;
309 if ( bytesToDequeue > (unsigned int)dataSize ) bytesToDequeue = dataSize;
310 while ( bytesToDequeue > 0 && iovecLen > 0 )
311 {
312 if ( vecPtr->iov_len > bytesToDequeue )
313 {
314 // dequeue the bytes by taking them off the front of the
315 // current vector. since we don't own the iovec, its okay
316 // to "leak" this away by pointing past it
317 char **base = reinterpret_cast<char**>(&(vecPtr->iov_base));
318 *base += bytesToDequeue;
319 vecPtr->iov_len -= bytesToDequeue;
320 bytesToDequeue = 0;
321 }
322 else
323 {
324 // dequeue bytes by skipping a whole vector. again, its ok
325 // to lose the pointers to this data
326 bytesToDequeue -= vecPtr->iov_len;
327 iovecLen--;
328 vecPtr++;
329 }
330 }
331 dataSize -= bytesToDequeue;
332 if ( iovecLen == 0 ) vec = 0;
333 }
334 else
335 {
336 bytes.remove(0, bytesToDequeue );
337 }
338}
339
340
341/*!
342 \class QUnixSocketMessage
343 \internal
344
345 \brief The QUnixSocketMessage class encapsulates a message sent or received
346 through the QUnixSocket class.
347 \omit
348 \ingroup Platform::DeviceSpecific
349 \ingroup Platform::OS
350 \ingroup Platform::Communications
351 \endomit
352 \ingroup qws
353
354 In addition to transmitting regular byte stream data, messages sent over Unix
355 domain sockets may have special ancillary properties. QUnixSocketMessage
356 instances allow programmers to retrieve and control these properties.
357
358 Every QUnixSocketMessage sent has an associated set of credentials. A
359 message's credentials consist of the process id, the user id and the group id
360 of the sending process. Normally these credentials are set automatically for
361 you by the QUnixSocketMessage class and can be queried by the receiving
362 process using the \l QUnixSocketMessage::processId(),
363 \l QUnixSocketMessage::userId() and \l QUnixSocketMessage::groupId() methods
364 respectively.
365
366 Advanced applications may wish to change the credentials that their message
367 is sent with, and may do so though the \l QUnixSocketMessage::setProcessId(),
368 \l QUnixSocketMessage::setUserId() and \l QUnixSocketMessage::setGroupId()
369 methods. The validity of these credentials is verified by the system kernel.
370 Only the root user can send messages with credentials that are not his own.
371 Sending of the message will fail for any non-root user who attempts to
372 fabricate credentials. Note that this failure is enforced by the system
373 kernel - receivers can trust the accuracy of credential data!
374
375 Unix domain socket messages may also be used to transmit Unix file descriptors
376 between processes. In this context, file descriptors are known as rights data
377 and are encapsulated by the \l QUnixSocketRights class. Senders can set the
378 file descriptors to transmit using the \l QUnixSocketMessage::setRights() and
379 receivers can retrieve this data through a call to
380 \l QUnixSocketMessage::rights(). \l QUnixSocket and \l QUnixSocketRights
381 discuss the specific copy and ordering semantic associated with rights data.
382
383 QUnixSocketMessage messages are sent by the \l QUnixSocket::write() method.
384 Like any normal network message, attempting to transmit an empty
385 QUnixSocketMessage will succeed, but result in a no-op. Limitations in the
386 Unix domain protocol semantic will cause a transmission of a
387 QUnixSocketMessage with rights data, but no byte data portion, to fail.
388
389 \sa QUnixSocket QUnixSocketRights
390 */
391
392/*!
393 Construct an empty QUnixSocketMessage. This instance will have not data and
394 no rights information. The message's credentials will be set to the
395 application's default credentials.
396 */
397QUnixSocketMessage::QUnixSocketMessage()
398: d(new QUnixSocketMessagePrivate())
399{
400}
401
402/*!
403 Construct a QUnixSocketMessage with an initial data payload of \a bytes. The
404 message's credentials will be set to the application's default credentials.
405 */
406QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes)
407: d(new QUnixSocketMessagePrivate(bytes))
408{