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
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{
123 bool useCache = isOptionEnabled(KNetworkMountOption::SymlinkPathsUseCache, true);
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.
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.
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)
void reserve(qsizetype size)
QString writableLocation(StandardLocation type)
QString & append(QChar ch)
QString arg(Args &&... args) const const
void chop(qsizetype n)
void clear()
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-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:31 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.