File indexing completed on 2024-04-14 03:49:46

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2007-2010 Sebastian Trueg <trueg@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KINOTIFY_H_
0009 #define KINOTIFY_H_
0010 
0011 #include <QObject>
0012 
0013 namespace Baloo {
0014     class FileIndexerConfig;
0015 }
0016 
0017 /**
0018  * A simple wrapper around inotify which only allows
0019  * to add folders recursively.
0020  *
0021  * Warning: moving of top-level folders is not supported and
0022  * results in undefined behaviour.
0023  */
0024 class KInotify : public QObject
0025 {
0026     Q_OBJECT
0027 
0028 public:
0029     explicit KInotify(Baloo::FileIndexerConfig* config, QObject* parent = nullptr);
0030     ~KInotify() override;
0031 
0032     /**
0033      * Inotify events that can occur. Use with addWatch
0034      * to define the events that should be watched.
0035      *
0036      * These flags correspond to the native Linux inotify flags.
0037      */
0038     enum WatchEvent {
0039         EventAccess = 0x00000001, /**< File was accessed (read, compare inotify's IN_ACCESS) */
0040         EventAttributeChange = 0x00000004, /**< Metadata changed (permissions, timestamps, extended attributes, etc., compare inotify's IN_ATTRIB) */
0041         EventCloseWrite = 0x00000008, /**< File opened for writing was closed (compare inotify's IN_CLOSE_WRITE) */
0042         EventCloseRead = 0x00000010, /**< File not opened for writing was closed (compare inotify's IN_CLOSE_NOWRITE) */
0043         EventCreate = 0x00000100, /** File/directory created in watched directory (compare inotify's IN_CREATE) */
0044         EventDelete = 0x00000200, /**< File/directory deleted from watched directory (compare inotify's IN_DELETE) */
0045         EventDeleteSelf = 0x00000400, /**< Watched file/directory was itself deleted (compare inotify's IN_DELETE_SELF) */
0046         EventModify = 0x00000002, /**< File was modified (compare inotify's IN_MODIFY) */
0047         EventMoveSelf = 0x00000800, /**< Watched file/directory was itself moved (compare inotify's IN_MOVE_SELF) */
0048         EventMoveFrom = 0x00000040, /**< File moved out of watched directory (compare inotify's IN_MOVED_FROM) */
0049         EventMoveTo = 0x00000080, /**< File moved into watched directory (compare inotify's IN_MOVED_TO) */
0050         EventOpen = 0x00000020, /**< File was opened (compare inotify's IN_OPEN) */
0051         EventUnmount = 0x00002000, /**< Backing fs was unmounted (compare inotify's IN_UNMOUNT) */
0052         EventQueueOverflow = 0x00004000, /**< Event queued overflowed (compare inotify's IN_Q_OVERFLOW) */
0053         EventIgnored = 0x00008000, /**< File was ignored (compare inotify's IN_IGNORED) */
0054         EventMove = (EventMoveFrom | EventMoveTo),
0055         EventAll = (EventAccess |
0056                     EventAttributeChange |
0057                     EventCloseWrite |
0058                     EventCloseRead |
0059                     EventCreate |
0060                     EventDelete |
0061                     EventDeleteSelf |
0062                     EventModify |
0063                     EventMoveSelf |
0064                     EventMoveFrom |
0065                     EventMoveTo |
0066                     EventOpen),
0067     };
0068     Q_DECLARE_FLAGS(WatchEvents, WatchEvent)
0069 
0070     /**
0071      * Watch flags
0072      *
0073      * These flags correspond to the native Linux inotify flags.
0074      */
0075     enum WatchFlag {
0076         FlagOnlyDir = 0x01000000, /**< Only watch the path if it is a directory (IN_ONLYDIR) */
0077         FlagDoNotFollow = 0x02000000, /**< Don't follow a sym link (IN_DONT_FOLLOW) */
0078         FlagOneShot = 0x80000000, /**< Only send event once (IN_ONESHOT) */
0079         FlagExclUnlink = 0x04000000, /**< Do not generate events for unlinked files (IN_EXCL_UNLINK) */
0080     };
0081     Q_DECLARE_FLAGS(WatchFlags, WatchFlag)
0082 
0083     bool watchingPath(const QString& path) const;
0084 
0085     /**
0086      * Call this when the inotify limit has been increased.
0087      */
0088     void resetUserLimit();
0089 
0090 public Q_SLOTS:
0091     bool addWatch(const QString& path, WatchEvents modes, WatchFlags flags = WatchFlags());
0092     bool removeWatch(const QString& path);
0093 
0094 Q_SIGNALS:
0095     /**
0096      * Emitted if a file is accessed (KInotify::EventAccess)
0097      */
0098     void accessed(const QString& file);
0099 
0100     /**
0101      * Emitted if file attributes are changed (KInotify::EventAttributeChange)
0102      */
0103     void attributeChanged(const QString& file);
0104 
0105     /**
0106      * Emitted if FIXME (KInotify::EventCloseWrite)
0107      */
0108     void closedWrite(const QString& file);
0109 
0110     /**
0111      * Emitted if FIXME (KInotify::EventCloseRead)
0112      */
0113     void closedRead(const QString& file);
0114 
0115     /**
0116      * Emitted if a new file has been created in one of the watched
0117      * folders (KInotify::EventCreate)
0118      */
0119     void created(const QString& file, bool isDir);
0120 
0121     /**
0122      * Emitted if a watched file or folder has been deleted.
0123      * This includes files in watched folders (KInotify::EventDelete and KInotify::EventDeleteSelf)
0124      */
0125     void deleted(const QString& file, bool isDir);
0126 
0127     /**
0128      * Emitted if a watched file is modified (KInotify::EventModify)
0129      */
0130     void modified(const QString& file);
0131 
0132     /**
0133      * Emitted if a file or folder has been moved or renamed.
0134      *
0135      * \warning The moved signal will only be emitted if both the source and target folder
0136      * are being watched.
0137      */
0138     void moved(const QString& oldName, const QString& newName);
0139 
0140     /**
0141      * Emitted if a file is opened (KInotify::EventOpen)
0142      */
0143     void opened(const QString& file);
0144 
0145     /**
0146      * Emitted if a watched path has been unmounted (KInotify::EventUnmount)
0147      */
0148     void unmounted(const QString& file);
0149 
0150     /**
0151      * Emitted if during updating the internal watch structures (recursive watches)
0152      * the inotify user watch limit was reached.
0153      *
0154      * This means that not all requested paths can be watched until the user watch
0155      * limit is increased.
0156      *
0157      * The argument is the path being added when the limit was reached.
0158      *
0159      * This signal will only be emitted once until resetUserLimit is called.
0160      */
0161     void watchUserLimitReached(const QString& path);
0162 
0163     /**
0164      * This is emitted once watches have been installed in all the directories
0165      * indicated by addWatch
0166      */
0167     void installedWatches();
0168 
0169 private Q_SLOTS:
0170     void slotEvent(int);
0171     void slotClearCookies();
0172 
0173 private:
0174     class Private;
0175     Private* const d;
0176 
0177     /**
0178      * Recursively iterates over all files/folders inside @param path
0179      * (that are not excluded by the config);
0180      * emits created() signal for each entry (excluding @param path)
0181      * and installs watches for all subdirectories (including @param path)
0182      */
0183     void handleDirCreated(const QString& path);
0184 };
0185 
0186 #endif