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#ifndef KNETWORKMOUNTS_H
8#define KNETWORKMOUNTS_H
9
10#include <memory>
11
12#include <QObject>
13#include <kcoreaddons_export.h>
14
15/**
16 * \class KNetworkMounts knetworkmounts.h <KNetworkMounts>
17 *
18 * Performance control on network mounts.
19 *
20 * This class provides methods for deciding whether operations
21 * on slow network mounts should be performed or not.
22 *
23 * Configuration is read from a configuration file network_mounts in
24 * the user's QStandardPaths::ConfigLocation. This file can be filled by using
25 * the network mounts performance configuration module or directly via @ref setEnabled,
26 * @ref setPaths, @ref addPath and @ref setOption
27 * @code
28 * KNetworkMounts::self()->setEnabled(true);
29 * KNetworkMounts::self()->setOption(KNetworkMounts::LowSideEffectsOptimizations, true);
30 * KNetworkMounts::self()->addPath(path1, KNetworkMounts::NfsPaths);
31 * KNetworkMounts::self()->addPath(path2, KNetworkMounts::NfsPaths);
32 * KNetworkMounts::self()->setPaths(listOfPaths, KNetworkMounts::SmbPaths);
33 * @endcode
34 *
35 * Use KNetworkMounts like this to check if the given url is on a
36 * configured slow path and the KNetworkMountOption LowSideEffectsOptimizations
37 * is enabled:
38 * @code
39 * if (KNetworkMounts::self()->isOptionEnabledForPath(url.toLocalFile(),
40 * KNetworkMounts::LowSideEffectsOptimizations))
41 * {
42 * // skip operations which are slow on the given url if
43 * // KNetworkMountOption LowSideEffectsOptimizations is enabled
44 * } else {
45 * // given url is not configured being slow or the KNetworkMountOption
46 * // LowSideEffectsOptimizations is not enabled
47 * }
48 * @endcode
49 *
50 * If called for the first time, this creates a singleton instance and reads
51 * the config file. Subsequent calls just use this instance without reading
52 * the config file again.
53 *
54 * @author Robert Hoffmann <robert@roberthoffmann.de>
55 *
56 * @since 5.85
57 **/
58class KCOREADDONS_EXPORT KNetworkMounts : public QObject
59{
60 Q_OBJECT
61
62public:
63 /**
64 * Returns (and creates if necessary) the singleton instance
65 *
66 * @return the singleton instance
67 */
68 static KNetworkMounts *self();
69
70 /**
71 * The KNetworkMountOption enum
72 *
73 * Uses are:
74 */
75 enum KNetworkMountOption {
76 LowSideEffectsOptimizations, ///< Don't run KDiskFreeSpaceInfo if slow path.<br>
77 ///< Don't check for manually mounted drives.<br>
78 ///< Don't check with QFileInfo::isWritable if it is writable, if not yet known, return true.<br>
79 ///< Don't check with QFileInfo::isReadable if it is readable, return false.<br>
80 ///< Don't check for desktop files just return false.<br>
81 ///< Ignore .hidden files on slow paths.<br>
82 ///< Don't read mime comment from .desktop or .directory files.<br>
83 ///< Don't get the size with QFileInfo::size, just return 0, if not yet known.<br>
84 ///< Don't determine mime type from file content, use file extension.<br>
85 ///< Don't check for desktop files just return false.<br>
86 ///< Don't call KFileSystemType::fileSystemType to check if the filesystem is slow, just return true.<br>
87 ///< Don't count files/directories in subdirectories.<br>
88 ///< Don't calculate sizes of subdirectories.<br>
89 ///< Avoid check for dir at Kate startup
90 MediumSideEffectsOptimizations, ///< Don't return project for dir, avoid QFileInfo().absoluteDir()<br>
91 ///< Don't search for .kateconfig recursively<br>
92 ///< Ignore recent files on slow paths
93 StrongSideEffectsOptimizations, ///< Turn off symbolic link resolution
94 KDirWatchDontAddWatches, ///< Disables dir watching completely for slow paths, avoids stat() calls on added dirs and subdirs
95 SymlinkPathsUseCache ///< Cache resolved symlink paths
96 };
97 Q_ENUM(KNetworkMountOption)
98
99 /**
100 * The KNetworkMountsType enum
101 */
102 enum KNetworkMountsType {
103 NfsPaths, ///< NFS paths
104 SmbPaths, ///< SMB paths
105 SymlinkDirectory, ///< Paths to directories which contain symbolic links to network mounts
106 SymlinkToNetworkMount, ///< Paths which are symbolic links to network mounts
107 Any ///< Any slow path type. Do not use with @ref setPaths or @ref addPath
108 };
109 Q_ENUM(KNetworkMountsType)
110
111 /**
112 * Query if @p path is configured to be a slow path of type @p type
113 *
114 * @param path the path to query
115 * @param type the type to query. If omitted, any type matches
116 * @return @c true if @p path is a configured slow path of type @p type
117 *
118 * This function is also used to determine the filesystem type in @ref KFileSystemType::fileSystemType
119 * (KFileSystemType::Smb or KFileSystemType::Nfs) without an expensive call to stafs(). For this
120 * to work the types of paths need to be correctly assigned in @ref setPath or @ref addPath
121 */
122 bool isSlowPath(const QString &path, KNetworkMountsType type = Any);
123
124 /**
125 * Query if @p path is configured to be a slow path and @p option is enabled
126 *
127 * @param path the path to query
128 * @param option the option to query
129 * @return @c true if @p path is a configured slow path and option @p option is enabled
130 */
131 bool isOptionEnabledForPath(const QString &path, KNetworkMountOption option);
132
133 /**
134 * Query if the performance optimizations are switched on
135 *
136 * @return @c true if on, @c false otherwise
137 */
138 bool isEnabled() const;
139
140 /**
141 * Switch the performance optimizations on or off
142 *
143 * @param value the value to set
144 */
145 void setEnabled(bool value);
146
147 /**
148 * Query a performance option
149 *
150 * @param option the option to query
151 * @param defaultValue the value to return if the option is not configured
152 * @return @c true if option is on, @c false if not
153 * @see KNetworkMountOption
154 */
155 bool isOptionEnabled(const KNetworkMountOption option, const bool defaultValue = false) const;
156
157 /**
158 * Switch a performance option on or off
159 *
160 * @param option the option to change
161 * @param value the value to set
162 * @see KNetworkMountOption
163 */
164 void setOption(const KNetworkMountOption option, const bool value);
165
166 /**
167 * Query the configured paths for which optimizations are to take place
168 *
169 * @return a list of paths
170 */
171 QStringList paths(KNetworkMountsType type = Any) const;
172
173 /**
174 * Set the paths for which optimizations are to take place
175 *
176 * @param paths the paths to set
177 * @param type the type of paths. Do not use @ref Any
178 * @see KNetworkMountsType
179 */
180 void setPaths(const QStringList &paths, KNetworkMountsType type);
181
182 /**
183 * Add a path for which optimizations are to take place
184 *
185 * @param path the path to add
186 * @param type the type of the path. Do not use @ref Any
187 * @see KNetworkMountsType
188 */
189 void addPath(const QString &path, KNetworkMountsType type);
190
191 /**
192 * Resolves a @p path that may contain symbolic links to mounted network shares.
193 *
194 * A symlink path is either a directory which contains symbolic links to slow network mounts
195 * (@ref SymlinkDirectory) or a direct symbolic link to a slow network mount (@ref
196 * SymlinkToNfsOrSmbPaths).
197 *
198 * Example:
199 * There are some Samba shares mounted below /mnt. These are @ref paths of type @ref SmbPaths
200 * @code
201 * /mnt/server1/share1
202 * /mnt/server1/share2
203 * /mnt/server2/share3
204 * @endcode
205 *
206 * A (logged in) user may have symbolic links to them in his home directory below netshares. The
207 * directory /home/user/netshares is a @ref SymlinkDirectory:
208 * @code
209 * /home/user/netshares/share1 -> /mnt/server1/share1
210 * /home/user/netshares/share2 -> /mnt/server1/share2
211 * /home/user/netshares/share3 -> /mnt/server2/share3
212 * @endcode
213 *
214 * There is a direct symbolic link from /home/user/share1 to /mnt/server1/share1. This is of type
215 * @ref SymlinkToNfsOrSmbPaths:
216 * @code
217 * /home/user/share1 -> /mnt/server1/share1
218 * @endcode
219 *
220 * Both types of symbolic links from symlink paths to the real mounted shares are resolved even if
221 * KNetworkMountOption @ref StrongSideEffectsOptimizations is enabled.
222
223 * If the setup is like above a @p path
224 * @code
225 * /home/user/netshares/share1/Documents/file.txt
226 * @endcode
227 *
228 * would be resolved to
229 * @code
230 * /mnt/server1/share1/Documents/file.txt
231 * @endcode
232 *
233 * and a @p path
234 * @code
235 * /home/user/share1/Documents/file.txt
236 * @endcode
237 *
238 * would also be resolved to
239 * @code
240 * /mnt/server1/share1/Documents/file.txt
241 * @endcode
242 *
243 * Resolved paths are cached in a hash.
244 *
245 * @param path the path to resolve
246 * @return the resolved path or @p path if @p path is not a symlink path or no symlink found
247 * @see KNetworkMountsType
248 * @see clearCache
249 * @see isSlowPath
250 */
251 QString canonicalSymlinkPath(const QString &path);
252
253 /**
254 * Clears the canonical symlink path cache
255 *
256 * Call this if directory structures on mounted network drives changed. Don't enable the
257 * cache (@ref SymlinkPathsUseCache) if this happens often and the drives are usually accessed
258 * via the symlinks. This method exists mainly for the KCM.
259 * @see canonicalSymlinkPath
260 */
261 void clearCache();
262
263 /**
264 * Synchronizes to config file
265 *
266 * QSettings synchronization also takes place automatically at regular intervals and from
267 * QSettings destructor, see QSettings::sync() documentation.
268 *
269 * Calls QSettings::sync()
270 */
271 void sync();
272
273private:
274 /// Creates a new KNetworkMounts object
275 KCOREADDONS_NO_EXPORT KNetworkMounts();
276
277 /// Destructor
278 KCOREADDONS_NO_EXPORT ~KNetworkMounts() override;
279
280 std::unique_ptr<class KNetworkMountsPrivate> const d;
281};
282
283#endif // KNETWORKMOUNTS_H
284

source code of kcoreaddons/src/lib/io/knetworkmounts.h