1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 2007-2010 Sebastian Trueg <trueg@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #ifndef KINOTIFY_H_ |
9 | #define KINOTIFY_H_ |
10 | |
11 | #include <QObject> |
12 | |
13 | namespace Baloo { |
14 | class FileIndexerConfig; |
15 | } |
16 | |
17 | /** |
18 | * A simple wrapper around inotify which only allows |
19 | * to add folders recursively. |
20 | * |
21 | * Warning: moving of top-level folders is not supported and |
22 | * results in undefined behaviour. |
23 | */ |
24 | class KInotify : public QObject |
25 | { |
26 | Q_OBJECT |
27 | |
28 | public: |
29 | explicit KInotify(Baloo::FileIndexerConfig* config, QObject* parent = nullptr); |
30 | ~KInotify() override; |
31 | |
32 | /** |
33 | * Inotify events that can occur. Use with addWatch |
34 | * to define the events that should be watched. |
35 | * |
36 | * These flags correspond to the native Linux inotify flags. |
37 | */ |
38 | enum WatchEvent { |
39 | EventAccess = 0x00000001, /**< File was accessed (read, compare inotify's IN_ACCESS) */ |
40 | EventAttributeChange = 0x00000004, /**< Metadata changed (permissions, timestamps, extended attributes, etc., compare inotify's IN_ATTRIB) */ |
41 | EventCloseWrite = 0x00000008, /**< File opened for writing was closed (compare inotify's IN_CLOSE_WRITE) */ |
42 | EventCloseRead = 0x00000010, /**< File not opened for writing was closed (compare inotify's IN_CLOSE_NOWRITE) */ |
43 | EventCreate = 0x00000100, /** File/directory created in watched directory (compare inotify's IN_CREATE) */ |
44 | EventDelete = 0x00000200, /**< File/directory deleted from watched directory (compare inotify's IN_DELETE) */ |
45 | EventDeleteSelf = 0x00000400, /**< Watched file/directory was itself deleted (compare inotify's IN_DELETE_SELF) */ |
46 | EventModify = 0x00000002, /**< File was modified (compare inotify's IN_MODIFY) */ |
47 | EventMoveSelf = 0x00000800, /**< Watched file/directory was itself moved (compare inotify's IN_MOVE_SELF) */ |
48 | EventMoveFrom = 0x00000040, /**< File moved out of watched directory (compare inotify's IN_MOVED_FROM) */ |
49 | EventMoveTo = 0x00000080, /**< File moved into watched directory (compare inotify's IN_MOVED_TO) */ |
50 | EventOpen = 0x00000020, /**< File was opened (compare inotify's IN_OPEN) */ |
51 | EventUnmount = 0x00002000, /**< Backing fs was unmounted (compare inotify's IN_UNMOUNT) */ |
52 | EventQueueOverflow = 0x00004000, /**< Event queued overflowed (compare inotify's IN_Q_OVERFLOW) */ |
53 | EventIgnored = 0x00008000, /**< File was ignored (compare inotify's IN_IGNORED) */ |
54 | EventMove = (EventMoveFrom | EventMoveTo), |
55 | EventAll = (EventAccess | |
56 | EventAttributeChange | |
57 | EventCloseWrite | |
58 | EventCloseRead | |
59 | EventCreate | |
60 | EventDelete | |
61 | EventDeleteSelf | |
62 | EventModify | |
63 | EventMoveSelf | |
64 | EventMoveFrom | |
65 | EventMoveTo | |
66 | EventOpen), |
67 | }; |
68 | Q_DECLARE_FLAGS(WatchEvents, WatchEvent) |
69 | |
70 | /** |
71 | * Watch flags |
72 | * |
73 | * These flags correspond to the native Linux inotify flags. |
74 | */ |
75 | enum WatchFlag { |
76 | FlagOnlyDir = 0x01000000, /**< Only watch the path if it is a directory (IN_ONLYDIR) */ |
77 | FlagDoNotFollow = 0x02000000, /**< Don't follow a sym link (IN_DONT_FOLLOW) */ |
78 | FlagOneShot = 0x80000000, /**< Only send event once (IN_ONESHOT) */ |
79 | FlagExclUnlink = 0x04000000, /**< Do not generate events for unlinked files (IN_EXCL_UNLINK) */ |
80 | }; |
81 | Q_DECLARE_FLAGS(WatchFlags, WatchFlag) |
82 | |
83 | bool watchingPath(const QString& path) const; |
84 | |
85 | /** |
86 | * Call this when the inotify limit has been increased. |
87 | */ |
88 | void resetUserLimit(); |
89 | |
90 | public Q_SLOTS: |
91 | bool addWatch(const QString& path, WatchEvents modes, WatchFlags flags = WatchFlags()); |
92 | bool removeWatch(const QString& path); |
93 | |
94 | Q_SIGNALS: |
95 | /** |
96 | * Emitted if a file is accessed (KInotify::EventAccess) |
97 | */ |
98 | void accessed(const QString& file); |
99 | |
100 | /** |
101 | * Emitted if file attributes are changed (KInotify::EventAttributeChange) |
102 | */ |
103 | void attributeChanged(const QString& file); |
104 | |
105 | /** |
106 | * Emitted if FIXME (KInotify::EventCloseWrite) |
107 | */ |
108 | void closedWrite(const QString& file); |
109 | |
110 | /** |
111 | * Emitted if FIXME (KInotify::EventCloseRead) |
112 | */ |
113 | void closedRead(const QString& file); |
114 | |
115 | /** |
116 | * Emitted if a new file has been created in one of the watched |
117 | * folders (KInotify::EventCreate) |
118 | */ |
119 | void created(const QString& file, bool isDir); |
120 | |
121 | /** |
122 | * Emitted if a watched file or folder has been deleted. |
123 | * This includes files in watched folders (KInotify::EventDelete and KInotify::EventDeleteSelf) |
124 | */ |
125 | void deleted(const QString& file, bool isDir); |
126 | |
127 | /** |
128 | * Emitted if a watched file is modified (KInotify::EventModify) |
129 | */ |
130 | void modified(const QString& file); |
131 | |
132 | /** |
133 | * Emitted if a file or folder has been moved or renamed. |
134 | * |
135 | * \warning The moved signal will only be emitted if both the source and target folder |
136 | * are being watched. |
137 | */ |
138 | void moved(const QString& oldName, const QString& newName); |
139 | |
140 | /** |
141 | * Emitted if a file is opened (KInotify::EventOpen) |
142 | */ |
143 | void opened(const QString& file); |
144 | |
145 | /** |
146 | * Emitted if a watched path has been unmounted (KInotify::EventUnmount) |
147 | */ |
148 | void unmounted(const QString& file); |
149 | |
150 | /** |
151 | * Emitted if during updating the internal watch structures (recursive watches) |
152 | * the inotify user watch limit was reached. |
153 | * |
154 | * This means that not all requested paths can be watched until the user watch |
155 | * limit is increased. |
156 | * |
157 | * The argument is the path being added when the limit was reached. |
158 | * |
159 | * This signal will only be emitted once until resetUserLimit is called. |
160 | */ |
161 | void watchUserLimitReached(const QString& path); |
162 | |
163 | /** |
164 | * This is emitted once watches have been installed in all the directories |
165 | * indicated by addWatch |
166 | */ |
167 | void installedWatches(); |
168 | |
169 | private Q_SLOTS: |
170 | void slotEvent(int); |
171 | void slotClearCookies(); |
172 | |
173 | private: |
174 | class Private; |
175 | Private* const d; |
176 | |
177 | /** |
178 | * Recursively iterates over all files/folders inside @param path |
179 | * (that are not excluded by the config); |
180 | * emits created() signal for each entry (excluding @param path) |
181 | * and installs watches for all subdirectories (including @param path) |
182 | */ |
183 | void handleDirCreated(const QString& path); |
184 | }; |
185 | |
186 | #endif |
187 | |