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 <[email protected]>
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 
18 KNetworkMountsPrivate::KNetworkMountsPrivate(KNetworkMounts *qq)
19  : q(qq)
20 {
21 }
22 
24 {
25  static KNetworkMounts s_self;
26  return &s_self;
27 }
28 
29 KNetworkMounts::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 
45 KNetworkMounts::~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 
72 void KNetworkMounts::setEnabled(const bool value)
73 {
74  d->m_settings->setValue(QStringLiteral("EnableOptimizations"), value);
75 }
76 
77 bool KNetworkMounts::isOptionEnabled(const KNetworkMountOption option, const bool defaultValue) const
78 {
79  return d->m_settings->value(enumToString(option), defaultValue).toBool();
80 }
81 
82 void 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 
118 typedef QHash<QString /*symlink*/, QString /*canonical path*/> symlinkCanonicalPathHash;
119 Q_GLOBAL_STATIC(symlinkCanonicalPathHash, s_canonicalLinkSpacePaths);
120 
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 }
void append(const T &value)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
static KNetworkMounts * self()
Returns (and creates if necessary) the singleton instance.
int size() const const
QString canonicalSymlinkPath(const QString &path)
Resolves a path that may contain symbolic links to mounted network shares.
bool isOptionEnabled(const KNetworkMountOption option, const bool defaultValue=false) const
Query a performance option.
void sync()
Synchronizes to config file.
QStringList paths(KNetworkMountsType type=Any) const
Query the configured paths for which optimizations are to take place.
void chop(int n)
@ SmbPaths
SMB paths.
QString writableLocation(QStandardPaths::StandardLocation type)
void setOption(const KNetworkMountOption option, const bool value)
Switch a performance option on or off.
@ Any
Any slow path type. Do not use with setPaths or addPath.
void reserve(int alloc)
KNetworkMountsType
The KNetworkMountsType enum.
bool isEmpty() const const
int length() const const
@ SymlinkToNetworkMount
Paths which are symbolic links to network mounts.
KNetworkMountOption
The KNetworkMountOption enum.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
bool isEnabled() const
Query if the performance optimizations are switched on.
QString & replace(int position, int n, QChar after)
bool isOptionEnabledForPath(const QString &path, KNetworkMountOption option)
Query if path is configured to be a slow path and option is enabled.
void clearCache()
Clears the canonical symlink path cache.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString & insert(int position, QChar ch)
QString left(int n) const const
void setEnabled(bool value)
Switch the performance optimizations on or off.
@ SymlinkDirectory
Paths to directories which contain symbolic links to network mounts.
@ NfsPaths
NFS paths.
void setPaths(const QStringList &paths, KNetworkMountsType type)
Set the paths for which optimizations are to take place.
bool isSlowPath(const QString &path, KNetworkMountsType type=Any)
Query if path is configured to be a slow path of type type.
QString & append(QChar ch)
void addPath(const QString &path, KNetworkMountsType type)
Add a path for which optimizations are to take place.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 03:59:35 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.