Changeset View
Standalone View
src/server/utils.cpp
Show All 15 Lines | |||||
16 | * along with this library; see the file COPYING.LIB. If not, write to | 16 | * along with this library; see the file COPYING.LIB. If not, write to | ||
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | * Boston, MA 02110-1301, USA. | 18 | * Boston, MA 02110-1301, USA. | ||
19 | * | 19 | * | ||
20 | */ | 20 | */ | ||
21 | 21 | | |||
22 | #include "utils.h" | 22 | #include "utils.h" | ||
23 | #include "akonadiserver_debug.h" | 23 | #include "akonadiserver_debug.h" | ||
24 | #include "instance_p.h" | ||||
24 | 25 | | |||
25 | #include <private/standarddirs_p.h> | 26 | #include <private/standarddirs_p.h> | ||
26 | 27 | | |||
27 | #include <QDir> | 28 | #include <QDir> | ||
28 | #include <QFileInfo> | 29 | #include <QFileInfo> | ||
29 | #include <QSettings> | 30 | #include <QSettings> | ||
30 | #include <QHostInfo> | 31 | #include <QHostInfo> | ||
31 | 32 | | |||
32 | #if !defined(Q_OS_WIN) | 33 | #if !defined(Q_OS_WIN) | ||
33 | #include <cstdlib> | 34 | #include <cstdlib> | ||
34 | #include <sys/types.h> | 35 | #include <sys/types.h> | ||
36 | #include <sys/un.h> | ||||
35 | #include <cerrno> | 37 | #include <cerrno> | ||
36 | #include <pwd.h> | | |||
37 | #include <unistd.h> | 38 | #include <unistd.h> | ||
38 | 39 | | |||
39 | static QString akonadiSocketDirectory(); | 40 | static QString akonadiSocketDirectory(); | ||
40 | static bool checkSocketDirectory(const QString &path); | 41 | static bool checkSocketDirectory(const QString &path); | ||
41 | static bool createSocketDirectory(const QString &link, const QString &tmpl); | 42 | static bool createSocketDirectory(const QString &link, const QString &identifier); | ||
42 | #endif | 43 | #endif | ||
43 | 44 | | |||
44 | #ifdef Q_OS_LINUX | 45 | #ifdef Q_OS_LINUX | ||
45 | #include <stdio.h> | 46 | #include <stdio.h> | ||
46 | #include <mntent.h> | 47 | #include <mntent.h> | ||
47 | #include <sys/ioctl.h> | 48 | #include <sys/ioctl.h> | ||
48 | #include <fcntl.h> | 49 | #include <fcntl.h> | ||
49 | #endif | 50 | #endif | ||
50 | 51 | | |||
51 | using namespace Akonadi; | 52 | using namespace Akonadi; | ||
52 | using namespace Akonadi::Server; | 53 | using namespace Akonadi::Server; | ||
53 | 54 | | |||
54 | QString Utils::preferredSocketDirectory(const QString &defaultDirectory) | 55 | QString Utils::preferredSocketDirectory(const QString &defaultDirectory, int fnLengthHint) | ||
55 | { | 56 | { | ||
56 | const QString serverConfigFile = StandardDirs::serverConfigFile(StandardDirs::ReadWrite); | 57 | const QString serverConfigFile = StandardDirs::serverConfigFile(StandardDirs::ReadWrite); | ||
57 | const QSettings serverSettings(serverConfigFile, QSettings::IniFormat); | 58 | const QSettings serverSettings(serverConfigFile, QSettings::IniFormat); | ||
58 | 59 | | |||
59 | #if defined(Q_OS_WIN) | 60 | #if defined(Q_OS_WIN) | ||
60 | const QString socketDir = serverSettings.value(QLatin1String("Connection/SocketDirectory"), defaultDirectory).toString(); | 61 | const QString socketDir = serverSettings.value(QLatin1String("Connection/SocketDirectory"), defaultDirectory).toString(); | ||
61 | #else | 62 | #else | ||
62 | QString socketDir = defaultDirectory; | 63 | QString socketDir = defaultDirectory; | ||
63 | if (!serverSettings.contains(QStringLiteral("Connection/SocketDirectory"))) { | 64 | if (!serverSettings.contains(QStringLiteral("Connection/SocketDirectory"))) { | ||
64 | // if no socket directory is defined, use the symlinked from /tmp | 65 | // if no socket directory is defined, use the symlinked from /tmp | ||
65 | socketDir = akonadiSocketDirectory(); | 66 | socketDir = akonadiSocketDirectory(); | ||
66 | 67 | | |||
67 | if (socketDir.isEmpty()) { // if that does not work, fall back on default | 68 | if (socketDir.isEmpty()) { // if that does not work, fall back on default | ||
68 | socketDir = defaultDirectory; | 69 | socketDir = defaultDirectory; | ||
69 | } | 70 | } | ||
70 | } else { | 71 | } else { | ||
71 | socketDir = serverSettings.value(QStringLiteral("Connection/SocketDirectory"), defaultDirectory).toString(); | 72 | socketDir = serverSettings.value(QStringLiteral("Connection/SocketDirectory"), defaultDirectory).toString(); | ||
dfaure: should be >=, you need room for the trailing NUL character as well. | |||||
72 | } | 73 | } | ||
73 | 74 | | |||
dfaure: Let's hope that one does fit in the length limit :-) | |||||
74 | if (socketDir.contains(QLatin1String("$USER"))) { | 75 | if (socketDir.contains(QLatin1String("$USER"))) { | ||
75 | const QString userName = QString::fromLocal8Bit(qgetenv("USER")); | 76 | const QString userName = QString::fromLocal8Bit(qgetenv("USER")); | ||
76 | if (!userName.isEmpty()) { | 77 | if (!userName.isEmpty()) { | ||
77 | socketDir.replace(QLatin1String("$USER"), userName); | 78 | socketDir.replace(QLatin1String("$USER"), userName); | ||
78 | } | 79 | } | ||
79 | } | 80 | } | ||
80 | 81 | | |||
81 | if (socketDir[0] != QLatin1Char('/')) { | 82 | if (socketDir[0] != QLatin1Char('/')) { | ||
82 | QDir::home().mkdir(socketDir); | 83 | QDir::home().mkdir(socketDir); | ||
83 | socketDir = QDir::homePath() + QLatin1Char('/') + socketDir; | 84 | socketDir = QDir::homePath() + QLatin1Char('/') + socketDir; | ||
84 | } | 85 | } | ||
85 | 86 | | |||
86 | QFileInfo dirInfo(socketDir); | 87 | QFileInfo dirInfo(socketDir); | ||
87 | if (!dirInfo.exists()) { | 88 | if (!dirInfo.exists()) { | ||
88 | QDir::home().mkpath(dirInfo.absoluteFilePath()); | 89 | QDir::home().mkpath(dirInfo.absoluteFilePath()); | ||
89 | } | 90 | } | ||
91 | | ||||
92 | if (socketDir.length() + 1 + fnLengthHint >= static_cast<int>(sizeof(sockaddr_un::sun_path))) { | ||||
93 | qCCritical(AKONADISERVER_LOG) << "akonadiSocketDirectory() length is too long to be used by the system."; | ||||
94 | } | ||||
90 | #endif | 95 | #endif | ||
91 | return socketDir; | 96 | return socketDir; | ||
92 | } | 97 | } | ||
93 | 98 | | |||
94 | #if !defined(Q_OS_WIN) | 99 | #if !defined(Q_OS_WIN) | ||
95 | QString akonadiSocketDirectory() | 100 | QString akonadiSocketDirectory() | ||
96 | { | 101 | { | ||
97 | const QString hostname = QHostInfo::localHostName(); | 102 | const QString hostname = QHostInfo::localHostName(); | ||
98 | 103 | | |||
99 | if (hostname.isEmpty()) { | 104 | if (hostname.isEmpty()) { | ||
100 | qCCritical(AKONADISERVER_LOG) << "QHostInfo::localHostName() failed"; | 105 | qCCritical(AKONADISERVER_LOG) << "QHostInfo::localHostName() failed"; | ||
101 | return QString(); | 106 | return QString(); | ||
102 | } | 107 | } | ||
103 | 108 | | |||
104 | const uid_t uid = getuid(); | 109 | const QString identifier = Instance::hasIdentifier() ? Instance::identifier() : QLatin1String("default"); | ||
Since on Linux you are now creating the directory in /var/run/user/<uid>/, I'd very much prefer to keep akonadi in the name... Actually, since you cannot have two same instances of Akonadi running at the same time, it should be perfectly fine to call the folder akonadi for the default instance and akonadi-<instancename> when Akonadi::Instance::hasIdentifier() is true, no more random strings. This would make the directory deterministic for each instance, simplifying the code. dvratil: Since on Linux you are now creating the directory in `/var/run/user/<uid>/`, I'd very much… | |||||
createSocketDirectory is calling saveDir("runtime"), which already append "akonadi" tho the runtime path, ie "/path/to/runtime/akonadi", which result to path like "path/tp/runtime/akonadi/TMPL". I could then just use fixed (no) template name like 'default' and 'identifier Name' in this folder then ? fazevedo: createSocketDirectory is calling saveDir("runtime"), which already append "akonadi" tho the… | |||||
105 | const struct passwd *pw_ent = getpwuid(uid); | 110 | const QString link = StandardDirs::saveDir("data") + QStringLiteral("/socket-%1-%2").arg(hostname, identifier); | ||
dfaure: This line is no longer necessary. | |||||
Don't use QDir::separator(). That's '\' on Windows, while all this code uses '/' everywhere. Just make it "/socket..." (the existing code is the result of automated conversion) dfaure: Don't use QDir::separator(). That's '\' on Windows, while all this code uses '/' everywhere. | |||||
106 | if (!pw_ent) { | | |||
107 | qCCritical(AKONADISERVER_LOG) << "Could not get passwd entry for user id" << uid; | | |||
108 | return QString(); | | |||
109 | } | | |||
110 | | ||||
111 | const QString link = StandardDirs::saveDir("data") + QLatin1Char('/') + QLatin1String("socket-") + hostname; | | |||
112 | QString tmpl = QLatin1String("akonadi-") + QString::fromLocal8Bit(pw_ent->pw_name) + QLatin1String(".XXXXXX"); | | |||
113 | | ||||
114 | // Workaround for QLocalServer encoding bug | | |||
115 | // basically replace non-latin characters | | |||
116 | tmpl = QString::fromLatin1(tmpl.toLatin1()); | | |||
117 | 111 | | |||
118 | if (checkSocketDirectory(link)) { | 112 | if (checkSocketDirectory(link)) { | ||
119 | return QFileInfo(link).symLinkTarget(); | 113 | return QFileInfo(link).symLinkTarget(); | ||
120 | } | 114 | } | ||
121 | 115 | | |||
122 | if (createSocketDirectory(link, tmpl)) { | 116 | if (createSocketDirectory(link, identifier)) { | ||
123 | return QFileInfo(link).symLinkTarget(); | 117 | return QFileInfo(link).symLinkTarget(); | ||
124 | } | 118 | } | ||
125 | 119 | | |||
126 | qCCritical(AKONADISERVER_LOG) << "Could not create socket directory for Akonadi."; | 120 | qCCritical(AKONADISERVER_LOG) << "Could not create socket directory for Akonadi."; | ||
127 | return QString(); | 121 | return QString(); | ||
128 | } | 122 | } | ||
129 | 123 | | |||
130 | static bool checkSocketDirectory(const QString &path) | 124 | static bool checkSocketDirectory(const QString &path) | ||
Show All 14 Lines | 125 | { | |||
145 | 139 | | |||
146 | if (info.ownerId() != getuid()) { | 140 | if (info.ownerId() != getuid()) { | ||
147 | return false; | 141 | return false; | ||
148 | } | 142 | } | ||
149 | 143 | | |||
150 | return true; | 144 | return true; | ||
151 | } | 145 | } | ||
152 | 146 | | |||
153 | static bool createSocketDirectory(const QString &link, const QString &tmpl) | 147 | static bool createSocketDirectory(const QString &link, const QString &identifier) | ||
154 | { | 148 | { | ||
155 | QString directory = QStringLiteral("%1%2%3").arg(QDir::tempPath()).arg(QDir::separator()).arg(tmpl); | 149 | const QString directory = QStringLiteral("%1/%2").arg(StandardDirs::saveDir("runtime"), identifier); | ||
dfaure: %1/%2, no need for QDir::separator, this uses Qt APIs, not native APIs. | |||||
156 | 150 | | |||
157 | QByteArray directoryString = directory.toLocal8Bit(); | 151 | if (!QDir().mkpath(directory)) { | ||
Once you change to the deterministic format, mkdtemp can be switched to QDir::mkpath() dvratil: Once you change to the deterministic format, `mkdtemp ` can be switched to `QDir::mkpath()` | |||||
158 | 152 | qCCritical(AKONADISERVER_LOG) << "Creating socket directory with name" << directory << "failed:" << strerror(errno); | |||
159 | if (!mkdtemp(directoryString.data())) { | | |||
160 | qCCritical(AKONADISERVER_LOG) << "Creating socket directory with template" << directoryString << "failed:" << strerror(errno); | | |||
161 | return false; | 153 | return false; | ||
162 | } | 154 | } | ||
163 | 155 | | |||
164 | directory = QString::fromLocal8Bit(directoryString); | | |||
165 | | ||||
166 | QFile::remove(link); | 156 | QFile::remove(link); | ||
167 | 157 | | |||
168 | if (!QFile::link(directory, link)) { | 158 | if (!QFile::link(directory, link)) { | ||
169 | qCCritical(AKONADISERVER_LOG) << "Creating symlink from" << directory << "to" << link << "failed"; | 159 | qCCritical(AKONADISERVER_LOG) << "Creating symlink from" << directory << "to" << link << "failed"; | ||
170 | return false; | 160 | return false; | ||
171 | } | 161 | } | ||
172 | 162 | | |||
173 | return true; | 163 | return true; | ||
174 | } | 164 | } | ||
175 | #endif | 165 | #endif | ||
176 | 166 | | |||
177 | QString Utils::getDirectoryFileSystem(const QString &directory) | 167 | QString Utils::getDirectoryFileSystem(const QString &directory) | ||
178 | { | 168 | { | ||
179 | #ifndef Q_OS_LINUX | 169 | #ifndef Q_OS_LINUX | ||
170 | Q_UNUSED(directory); | ||||
180 | return QString(); | 171 | return QString(); | ||
181 | #else | 172 | #else | ||
182 | QString bestMatchPath; | 173 | QString bestMatchPath; | ||
183 | QString bestMatchFS; | 174 | QString bestMatchFS; | ||
184 | 175 | | |||
185 | FILE *mtab = setmntent("/etc/mtab", "r"); | 176 | FILE *mtab = setmntent("/etc/mtab", "r"); | ||
186 | if (!mtab) { | 177 | if (!mtab) { | ||
187 | return QString(); | 178 | return QString(); | ||
▲ Show 20 Lines • Show All 64 Lines • Show Last 20 Lines |
should be >=, you need room for the trailing NUL character as well.