summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qlocalserver_unix.cpp
diff options
context:
space:
mode:
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);