summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qlocalserver_unix.cpp
diff options
context:
space:
mode:
authorAndrew Stanley-Jones <andrew.stanley-jones@nokia.com>2012-02-06 18:36:06 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-10 03:02:07 +0100
commit49b53061550c15ce3b9cc38ee5e82e970f75d5ea (patch)
tree8b6ea732d514b0220d11062d256351145d8837cb /src/network/socket/qlocalserver_unix.cpp
parent8522cb5c97e092d83484768152704f7d9a69901d (diff)
Add socketOptions flags to QLocalServer
QLocalServer had no way to set socket options that more complicated servers require. The first set of options allow setting of access control on the sockets. Change-Id: If4268c66462fc2e6cf1e70b1d5f56c76d2c69228 Reviewed-by: Harald Fernengel <harald.fernengel@nokia.com>
Diffstat (limited to 'src/network/socket/qlocalserver_unix.cpp')
-rw-r--r--src/network/socket/qlocalserver_unix.cpp65
1 files changed, 63 insertions, 2 deletions
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index c4482dadfc..ce0c283f0b 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -44,6 +44,7 @@
#include "qlocalsocket.h"
#include "qlocalsocket_p.h"
#include "qnet_unix_p.h"
+#include "qtemporarydir.h"
#ifndef QT_NO_LOCALSERVER
@@ -92,6 +93,20 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
}
serverName = requestedServerName;
+ QString tempPath;
+ QScopedPointer<QTemporaryDir> tempDir;
+
+ // Check any of the flags
+ if (socketOptions & QLocalServer::WorldAccessOption) {
+ tempDir.reset(new QTemporaryDir(fullServerName));
+ if (!tempDir->isValid()) {
+ setError(QLatin1String("QLocalServer::listen"));
+ return false;
+ }
+ tempPath = tempDir->path();
+ tempPath += QLatin1Char('/') + requestedServerName;
+ }
+
// create the unix socket
listenSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0);
if (-1 == listenSocket) {
@@ -108,8 +123,26 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
closeServer();
return false;
}
- ::memcpy(addr.sun_path, fullServerName.toLatin1().data(),
- fullServerName.toLatin1().size() + 1);
+
+ if (socketOptions & QLocalServer::WorldAccessOption) {
+ if (sizeof(addr.sun_path) < (uint)tempPath.toLatin1().size() + 1) {
+ setError(QLatin1String("QLocalServer::listen"));
+ closeServer();
+ return false;
+ }
+ ::memcpy(addr.sun_path, tempPath.toLatin1().data(),
+ tempPath.toLatin1().size() + 1);
+
+ if (-1 == ::fchmod(listenSocket, 0)) {
+ setError(QLatin1String("QLocalServer::listen"));
+ closeServer();
+ return false;
+ }
+
+ } else {
+ ::memcpy(addr.sun_path, fullServerName.toLatin1().data(),
+ fullServerName.toLatin1().size() + 1);
+ }
// bind
if(-1 == QT_SOCKET_BIND(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) {
@@ -133,6 +166,34 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
QFile::remove(fullServerName);
return false;
}
+
+ if (socketOptions & QLocalServer::WorldAccessOption) {
+ mode_t mode = 000;
+
+ if (socketOptions & QLocalServer::UserAccessOption) {
+ mode |= S_IRWXU;
+ }
+ if (socketOptions & QLocalServer::GroupAccessOption) {
+ mode |= S_IRWXG;
+ }
+ if (socketOptions & QLocalServer::OtherAccessOption) {
+ mode |= S_IRWXO;
+ }
+
+ if (mode) {
+ if (-1 == ::chmod(tempPath.toLatin1(), mode)) {
+ setError(QLatin1String("QLocalServer::listen"));
+ closeServer();
+ return false;
+ }
+ }
+ if (-1 == ::rename(tempPath.toLatin1(), fullServerName.toLatin1())){
+ setError(QLatin1String("QLocalServer::listen"));
+ closeServer();
+ return false;
+ }
+ }
+
Q_ASSERT(!socketNotifier);
socketNotifier = new QSocketNotifier(listenSocket,
QSocketNotifier::Read, q);