KCoreAddons

knetworkmounts.cpp
1/*
2 This software is a contribution of the LiMux project of the city of Munich.
3 SPDX-FileCopyrightText: 2021 Robert Hoffmann <robert@roberthoffmann.de>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "knetworkmounts.h"
9#include "knetworkmounts_p.h"
10
11#include <QCoreApplication>
12#include <QGlobalStatic>
13
14#include <QDebug>
15#include <QDir>
16#include <QStandardPaths>
17
18KNetworkMountsPrivate::KNetworkMountsPrivate(KNetworkMounts *qq)
19 : q(qq)
20{
21}
22
23KNetworkMounts *KNetworkMounts::self()
24{
25 static KNetworkMounts s_self;
26 return &s_self;
27}
28
29KNetworkMounts::KNetworkMounts()
30 : d(new KNetworkMountsPrivate(this))
31{
32 const QString configFileName = QStringLiteral("%1/network_mounts").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation));
33 d->m_settings = new QSettings(configFileName, QSettings::Format::IniFormat, this);
34
36 QString typeStr = enumToString(type);
37 QStringList slowPaths = d->m_settings->value(typeStr, QStringList()).toStringList();
38
39 if (ensureTrailingSlashes(&slowPaths)) {
40 d->m_settings->setValue(typeStr, slowPaths);
41 }
42 }
43}
44
45KNetworkMounts::~KNetworkMounts()
46{
47}
48
50{
51 return !getMatchingPath(path, paths(type)).isEmpty();
52}
53
55{
56 if (!isEnabled()) {
57 return false;
58 }
59
60 if (!isSlowPath(path)) {
61 return false;
62 }
63
64 return isOptionEnabled(option, true);
65}
66
68{
69 return d->m_settings->value(QStringLiteral("EnableOptimizations"), false).toBool();
70}
71
72void KNetworkMounts::setEnabled(const bool value)
73{
74 d->m_settings->setValue(QStringLiteral("EnableOptimizations"), value);
75}
76
77bool KNetworkMounts::isOptionEnabled(const KNetworkMountOption option, const bool defaultValue) const
78{
79 return d->m_settings->value(enumToString(option), defaultValue).toBool();
80}
81
82void KNetworkMounts::setOption(const KNetworkMountOption option, const bool value)
83{
84 d->m_settings->setValue(enumToString(option), value);
85}
86
88{
89 if (type == Any) {
91 paths.reserve(4);
92 for (const auto networkMountType :
94 paths.append(d->m_settings->value(enumToString(networkMountType), QStringList()).toStringList());
95 }
96 return paths;
97 } else {
98 return d->m_settings->value(enumToString(type), QStringList()).toStringList();
99 }
100}
101
103{
104 QStringList _paths(paths);
105 ensureTrailingSlashes(&_paths);
106 d->m_settings->setValue(enumToString(type), _paths);
107}
108
110{
111 QString _path(path);
112 ensureTrailingSlash(&_path);
113 QStringList newPaths = paths(type);
114 newPaths.append(_path);
115 d->m_settings->setValue(enumToString(type), newPaths);
116}
117
118typedef QHash<QString /*symlink*/, QString /*canonical path*/> symlinkCanonicalPathHash;
119Q_GLOBAL_STATIC(symlinkCanonicalPathHash, s_canonicalLinkSpacePaths)
120
121QString KNetworkMounts::canonicalSymlinkPath(const QString &path)
122{
124 if (useCache) {
125 const QString resolved = s_canonicalLinkSpacePaths->value(path);
126
127 if (!resolved.isEmpty()) {
128 return resolved;
129 }
130 }
131
132 QString symlinkPath = getMatchingPath(path, paths(KNetworkMountsType::SymlinkToNetworkMount));
133 if (!symlinkPath.isEmpty()) {
134 // remove trailing slash
135 symlinkPath.chop(1);
136
137 QFileInfo link(symlinkPath);
138 QString linkPath(path);
139 QString target = link.symLinkTarget();
140
141 if (target.isEmpty()) {
142 // not a symlink
143 if (useCache) {
144 s_canonicalLinkSpacePaths->insert(path, path);
145 }
146 return path;
147 } else {
148 // symlink
149 // replace only the first occurence of symlinkPath in linkPath with the link target
150 // linkPath.startsWith(symlinkPath) because of getMatchingPath
151 linkPath.replace(0, symlinkPath.size(), target);
152
153 if (useCache) {
154 s_canonicalLinkSpacePaths->insert(path, linkPath);
155 }
156 return linkPath;
157 }
158 }
159
160 QString linkSpacePath = getMatchingPath(path, paths(KNetworkMountsType::SymlinkDirectory));
161 if (!linkSpacePath.isEmpty()) {
162 QString _path = path;
163 if (!_path.endsWith(QLatin1Char('/'))) {
164 _path.append(QLatin1Char('/'));
165 }
166
167 if (_path == linkSpacePath) {
168 if (useCache) {
169 s_canonicalLinkSpacePaths->insert(path, path);
170 }
171 return path;
172 }
173
174 // search for symlink, linkSpacePath always ends with '/'
175 int linkIndex = path.indexOf(QLatin1Char('/'), linkSpacePath.length());
176 const QString symlink = path.left(linkIndex);
177
178 if (useCache && s_canonicalLinkSpacePaths->contains(symlink)) {
179 QString linkPath(path);
180 // replace only the first occurence of symlink in linkPath
181 linkPath.replace(0, symlink.size(), s_canonicalLinkSpacePaths->value(symlink));
182 s_canonicalLinkSpacePaths->insert(path, linkPath);
183 return linkPath;
184 } else {
185 QFileInfo link(symlink);
186
187 if (link.isSymLink()) {
188 QString linkPath(path);
189 // replace only the first occurence of symlink in linkPath
190 linkPath.replace(0, symlink.size(), link.symLinkTarget());
191
192 if (useCache) {
193 s_canonicalLinkSpacePaths->insert(path, linkPath);
194 }
195 return linkPath;
196 } else {
197 if (useCache) {
198 s_canonicalLinkSpacePaths->insert(path, path);
199 }
200 }
201 }
202 }
203
204 return path;
205}
206
208{
209 if (s_canonicalLinkSpacePaths.exists()) {
210 s_canonicalLinkSpacePaths->clear();
211 }
212}
213
215{
216 d->m_settings->sync();
217}
218
219#include "moc_knetworkmounts.cpp"
Performance control on network mounts.
QString canonicalSymlinkPath(const QString &path)
Resolves a path that may contain symbolic links to mounted network shares.
static KNetworkMounts * self()
Returns (and creates if necessary) the singleton instance.
void setEnabled(bool value)
Switch the performance optimizations on or off.
KNetworkMountOption
The KNetworkMountOption enum.
@ SymlinkPathsUseCache
Cache resolved symlink paths.
void sync()
Synchronizes to config file.
bool isOptionEnabled(const KNetworkMountOption option, const bool defaultValue=false) const
Query a performance option.
KNetworkMountsType
The KNetworkMountsType enum.
@ SmbPaths
SMB paths.
@ Any
Any slow path type. Do not use with setPaths or addPath.
@ NfsPaths
NFS paths.
@ SymlinkToNetworkMount
Paths which are symbolic links to network mounts.
@ SymlinkDirectory
Paths to directories which contain symbolic links to network mounts.
bool isSlowPath(const QString &path, KNetworkMountsType type=Any)
Query if path is configured to be a slow path of type type.
void setOption(const KNetworkMountOption option, const bool value)
Switch a performance option on or off.
bool isOptionEnabledForPath(const QString &path, KNetworkMountOption option)
Query if path is configured to be a slow path and option is enabled.
bool isEnabled() const
Query if the performance optimizations are switched on.
void setPaths(const QStringList &paths, KNetworkMountsType type)
Set the paths for which optimizations are to take place.
void addPath(const QString &path, KNetworkMountsType type)
Add a path for which optimizations are to take place.
QStringList paths(KNetworkMountsType type=Any) const
Query the configured paths for which optimizations are to take place.
void clearCache()
Clears the canonical symlink path cache.
void append(QList< T > &&value)
QString writableLocation(StandardLocation type)
QString & append(QChar ch)
QString arg(Args &&... args) const const
void chop(qsizetype n)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:55:52 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.