File indexing completed on 2024-05-12 03:54:55

0001 /*
0002     This software is a contribution of the LiMux project of the city of Munich.
0003     SPDX-FileCopyrightText: 2021 Robert Hoffmann <robert@roberthoffmann.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 #ifndef KNETWORKMOUNTS_H
0008 #define KNETWORKMOUNTS_H
0009 
0010 #include <memory>
0011 
0012 #include <QObject>
0013 #include <kcoreaddons_export.h>
0014 
0015 /**
0016  * \class KNetworkMounts knetworkmounts.h <KNetworkMounts>
0017  *
0018  * Performance control on network mounts.
0019  *
0020  * This class provides methods for deciding whether operations
0021  * on slow network mounts should be performed or not.
0022  *
0023  * Configuration is read from a configuration file network_mounts in
0024  * the user's QStandardPaths::ConfigLocation. This file can be filled by using
0025  * the network mounts performance configuration module or directly via @ref setEnabled,
0026  * @ref setPaths, @ref addPath and @ref setOption
0027  * @code
0028  *   KNetworkMounts::self()->setEnabled(true);
0029  *   KNetworkMounts::self()->setOption(KNetworkMounts::LowSideEffectsOptimizations, true);
0030  *   KNetworkMounts::self()->addPath(path1, KNetworkMounts::NfsPaths);
0031  *   KNetworkMounts::self()->addPath(path2, KNetworkMounts::NfsPaths);
0032  *   KNetworkMounts::self()->setPaths(listOfPaths, KNetworkMounts::SmbPaths);
0033  * @endcode
0034  *
0035  * Use KNetworkMounts like this to check if the given url is on a
0036  * configured slow path and the KNetworkMountOption LowSideEffectsOptimizations
0037  * is enabled:
0038  * @code
0039  *   if (KNetworkMounts::self()->isOptionEnabledForPath(url.toLocalFile(),
0040  *       KNetworkMounts::LowSideEffectsOptimizations))
0041  *   {
0042  *       // skip operations which are slow on the given url if
0043  *       // KNetworkMountOption LowSideEffectsOptimizations is enabled
0044  *   } else {
0045  *       // given url is not configured being slow or the KNetworkMountOption
0046  *       // LowSideEffectsOptimizations is not enabled
0047  *   }
0048  * @endcode
0049  *
0050  * If called for the first time, this creates a singleton instance and reads
0051  * the config file. Subsequent calls just use this instance without reading
0052  * the config file again.
0053  *
0054  * @author Robert Hoffmann <robert@roberthoffmann.de>
0055  *
0056  * @since 5.85
0057  **/
0058 class KCOREADDONS_EXPORT KNetworkMounts : public QObject
0059 {
0060     Q_OBJECT
0061 
0062 public:
0063     /**
0064      * Returns (and creates if necessary) the singleton instance
0065      *
0066      * @return the singleton instance
0067      */
0068     static KNetworkMounts *self();
0069 
0070     /**
0071      * The KNetworkMountOption enum
0072      *
0073      * Uses are:
0074      */
0075     enum KNetworkMountOption {
0076         LowSideEffectsOptimizations, ///< Don't run KDiskFreeSpaceInfo if slow path.<br>
0077                                      ///< Don't check for manually mounted drives.<br>
0078                                      ///< Don't check with QFileInfo::isWritable if it is writable, if not yet known, return true.<br>
0079                                      ///< Don't check with QFileInfo::isReadable if it is readable, return false.<br>
0080                                      ///< Don't check for desktop files just return false.<br>
0081                                      ///< Ignore .hidden files on slow paths.<br>
0082                                      ///< Don't read mime comment from .desktop or .directory files.<br>
0083                                      ///< Don't get the size with QFileInfo::size, just return 0, if not yet known.<br>
0084                                      ///< Don't determine mime type from file content, use file extension.<br>
0085                                      ///< Don't check for desktop files just return false.<br>
0086                                      ///< Don't call KFileSystemType::fileSystemType to check if the filesystem is slow, just return true.<br>
0087                                      ///< Don't count files/directories in subdirectories.<br>
0088                                      ///< Don't calculate sizes of subdirectories.<br>
0089                                      ///< Avoid check for dir at Kate startup
0090         MediumSideEffectsOptimizations, ///< Don't return project for dir, avoid QFileInfo().absoluteDir()<br>
0091                                         ///< Don't search for .kateconfig recursively<br>
0092                                         ///< Ignore recent files on slow paths
0093         StrongSideEffectsOptimizations, ///< Turn off symbolic link resolution
0094         KDirWatchDontAddWatches, ///< Disables dir watching completely for slow paths, avoids stat() calls on added dirs and subdirs
0095         SymlinkPathsUseCache ///< Cache resolved symlink paths
0096     };
0097     Q_ENUM(KNetworkMountOption)
0098 
0099     /**
0100      * The KNetworkMountsType enum
0101      */
0102     enum KNetworkMountsType {
0103         NfsPaths, ///< NFS paths
0104         SmbPaths, ///< SMB paths
0105         SymlinkDirectory, ///< Paths to directories which contain symbolic links to network mounts
0106         SymlinkToNetworkMount, ///< Paths which are symbolic links to network mounts
0107         Any ///< Any slow path type. Do not use with @ref setPaths or @ref addPath
0108     };
0109     Q_ENUM(KNetworkMountsType)
0110 
0111     /**
0112      * Query if @p path is configured to be a slow path of type @p type
0113      *
0114      * @param path the path to query
0115      * @param type the type to query. If omitted, any type matches
0116      * @return @c true if @p path is a configured slow path of type @p type
0117      *
0118      * This function is also used to determine the filesystem type in @ref KFileSystemType::fileSystemType
0119      * (KFileSystemType::Smb or KFileSystemType::Nfs) without an expensive call to stafs(). For this
0120      * to work the types of paths need to be correctly assigned in @ref setPath or @ref addPath
0121      */
0122     bool isSlowPath(const QString &path, KNetworkMountsType type = Any);
0123 
0124     /**
0125      * Query if @p path is configured to be a slow path and @p option is enabled
0126      *
0127      * @param path the path to query
0128      * @param option the option to query
0129      * @return @c true if @p path is a configured slow path and option @p option is enabled
0130      */
0131     bool isOptionEnabledForPath(const QString &path, KNetworkMountOption option);
0132 
0133     /**
0134      * Query if the performance optimizations are switched on
0135      *
0136      * @return @c true if on, @c false otherwise
0137      */
0138     bool isEnabled() const;
0139 
0140     /**
0141      * Switch the performance optimizations on or off
0142      *
0143      * @param value the value to set
0144      */
0145     void setEnabled(bool value);
0146 
0147     /**
0148      * Query a performance option
0149      *
0150      * @param option the option to query
0151      * @param defaultValue the value to return if the option is not configured
0152      * @return @c true if option is on, @c false if not
0153      * @see KNetworkMountOption
0154      */
0155     bool isOptionEnabled(const KNetworkMountOption option, const bool defaultValue = false) const;
0156 
0157     /**
0158      * Switch a performance option on or off
0159      *
0160      * @param option the option to change
0161      * @param value the value to set
0162      * @see KNetworkMountOption
0163      */
0164     void setOption(const KNetworkMountOption option, const bool value);
0165 
0166     /**
0167      * Query the configured paths for which optimizations are to take place
0168      *
0169      * @return a list of paths
0170      */
0171     QStringList paths(KNetworkMountsType type = Any) const;
0172 
0173     /**
0174      * Set the paths for which optimizations are to take place
0175      *
0176      * @param paths the paths to set
0177      * @param type the type of paths. Do not use @ref Any
0178      * @see KNetworkMountsType
0179      */
0180     void setPaths(const QStringList &paths, KNetworkMountsType type);
0181 
0182     /**
0183      * Add a path for which optimizations are to take place
0184      *
0185      * @param path the path to add
0186      * @param type the type of the path. Do not use @ref Any
0187      * @see KNetworkMountsType
0188      */
0189     void addPath(const QString &path, KNetworkMountsType type);
0190 
0191     /**
0192      * Resolves a @p path that may contain symbolic links to mounted network shares.
0193      *
0194      * A symlink path is either a directory which contains symbolic links to slow network mounts
0195      * (@ref SymlinkDirectory) or a direct symbolic link to a slow network mount (@ref
0196      * SymlinkToNfsOrSmbPaths).
0197      *
0198      * Example:
0199      * There are some Samba shares mounted below /mnt. These are @ref paths of type @ref SmbPaths
0200      * @code
0201      * /mnt/server1/share1
0202      * /mnt/server1/share2
0203      * /mnt/server2/share3
0204      * @endcode
0205      *
0206      * A (logged in) user may have symbolic links to them in his home directory below netshares. The
0207      * directory /home/user/netshares is a @ref SymlinkDirectory:
0208      * @code
0209      * /home/user/netshares/share1 -> /mnt/server1/share1
0210      * /home/user/netshares/share2 -> /mnt/server1/share2
0211      * /home/user/netshares/share3 -> /mnt/server2/share3
0212      * @endcode
0213      *
0214      * There is a direct symbolic link from /home/user/share1 to /mnt/server1/share1. This is of type
0215      * @ref SymlinkToNfsOrSmbPaths:
0216      * @code
0217      * /home/user/share1 -> /mnt/server1/share1
0218      * @endcode
0219      *
0220      * Both types of symbolic links from symlink paths to the real mounted shares are resolved even if
0221      * KNetworkMountOption @ref StrongSideEffectsOptimizations is enabled.
0222 
0223      * If the setup is like above a @p path
0224      * @code
0225      * /home/user/netshares/share1/Documents/file.txt
0226      * @endcode
0227      *
0228      * would be resolved to
0229      * @code
0230      * /mnt/server1/share1/Documents/file.txt
0231      * @endcode
0232      *
0233      * and a @p path
0234      * @code
0235      * /home/user/share1/Documents/file.txt
0236      * @endcode
0237      *
0238      * would also be resolved to
0239      * @code
0240      * /mnt/server1/share1/Documents/file.txt
0241      * @endcode
0242      *
0243      * Resolved paths are cached in a hash.
0244      *
0245      * @param path the path to resolve
0246      * @return the resolved path or @p path if @p path is not a symlink path or no symlink found
0247      * @see KNetworkMountsType
0248      * @see clearCache
0249      * @see isSlowPath
0250      */
0251     QString canonicalSymlinkPath(const QString &path);
0252 
0253     /**
0254      * Clears the canonical symlink path cache
0255      *
0256      * Call this if directory structures on mounted network drives changed. Don't enable the
0257      * cache (@ref SymlinkPathsUseCache) if this happens often and the drives are usually accessed
0258      * via the symlinks. This method exists mainly for the KCM.
0259      * @see canonicalSymlinkPath
0260      */
0261     void clearCache();
0262 
0263     /**
0264      * Synchronizes to config file
0265      *
0266      * QSettings synchronization also takes place automatically at regular intervals and from
0267      * QSettings destructor, see QSettings::sync() documentation.
0268      *
0269      * Calls QSettings::sync()
0270      */
0271     void sync();
0272 
0273 private:
0274     /// Creates a new KNetworkMounts object
0275     KCOREADDONS_NO_EXPORT KNetworkMounts();
0276 
0277     /// Destructor
0278     KCOREADDONS_NO_EXPORT ~KNetworkMounts() override;
0279 
0280     std::unique_ptr<class KNetworkMountsPrivate> const d;
0281 };
0282 
0283 #endif // KNETWORKMOUNTS_H