Rev 103 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 103 | Rev 106 | ||
---|---|---|---|
1 | 1 | ||
2 | /// inotify C++ interface implementation
|
2 | /// inotify C++ interface implementation
|
3 | /**
|
3 | /**
|
4 | * \file inotify-cxx.cpp
|
4 | * \file inotify-cxx.cpp
|
5 | *
|
5 | *
|
6 | * inotify C++ interface
|
6 | * inotify C++ interface
|
7 | *
|
7 | *
|
8 | * Copyright (C) 2006, 2007, 2009 Lukas Jelinek <lukas@aiken.cz>
|
8 | * Copyright (C) 2006, 2007, 2009, 2012 Lukas Jelinek <lukas@aiken.cz>
|
9 | *
|
9 | *
|
10 | * This program is free software; you can redistribute it and/or
|
10 | * This program is free software; you can redistribute it and/or
|
11 | * modify it under the terms of one of the following licenses:
|
11 | * modify it under the terms of one of the following licenses:
|
12 | *
|
12 | *
|
13 | * \li 1. X11-style license (see LICENSE-X11)
|
13 | * \li 1. X11-style license (see LICENSE-X11)
|
14 | * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
|
14 | * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
|
15 | * \li 3. GNU General Public License, version 2 (see LICENSE-GPL)
|
15 | * \li 3. GNU General Public License, version 2 (see LICENSE-GPL)
|
16 | *
|
16 | *
|
17 | * If you want to help with choosing the best license for you,
|
17 | * If you want to help with choosing the best license for you,
|
18 | * please visit http://www.gnu.org/licenses/license-list.html.
|
18 | * please visit http://www.gnu.org/licenses/license-list.html.
|
19 | *
|
19 | *
|
20 | * Credits:
|
20 | * Credits:
|
21 | * Mike Frysinger (cleanup of includes)
|
21 | * Mike Frysinger (cleanup of includes)
|
- | 22 | * Christian Ruppert (new include to build with GCC 4.4+)
|
|
22 | *
|
23 | *
|
23 | */
|
24 | */
|
24 | 25 | ||
25 | 26 | ||
26 | #include <errno.h>
|
27 | #include <errno.h>
|
27 | #include <unistd.h>
|
28 | #include <unistd.h>
|
28 | #include <fcntl.h>
|
29 | #include <fcntl.h>
|
29 | #include <fstream>
|
30 | #include <fstream>
|
- | 31 | #include <cstdio>
|
|
30 | 32 | ||
31 | #include <sys/syscall.h>
|
33 | #include <sys/syscall.h>
|
32 | 34 | ||
33 | // Use this if syscalls not defined
|
35 | // Use this if syscalls not defined
|
34 | #ifndef __NR_inotify_init
|
36 | #ifndef __NR_inotify_init
|
35 | #include <sys/inotify-syscalls.h>
|
37 | #include <sys/inotify-syscalls.h>
|
36 | #endif // __NR_inotify_init
|
38 | #endif // __NR_inotify_init
|
37 | 39 | ||
38 | #include "inotify-cxx.h"
|
40 | #include "inotify-cxx.h"
|
39 | 41 | ||
40 | /// procfs inotify base path
|
42 | /// procfs inotify base path
|
41 | #define PROCFS_INOTIFY_BASE "/proc/sys/fs/inotify/"
|
43 | #define PROCFS_INOTIFY_BASE "/proc/sys/fs/inotify/"
|
42 | 44 | ||
43 | /// dump separator (between particular entries)
|
45 | /// dump separator (between particular entries)
|
44 | #define DUMP_SEP \
|
46 | #define DUMP_SEP \
|
45 | ({ \
|
47 | ({ \
|
46 | if (!rStr.empty()) { \
|
48 | if (!rStr.empty()) { \
|
47 | rStr.append(","); \
|
49 | rStr.append(","); \
|
48 | } \
|
50 | } \
|
49 | })
|
51 | })
|
50 | 52 | ||
51 | 53 | ||
52 | 54 | ||
53 | int32_t InotifyEvent::GetDescriptor() const |
55 | int32_t InotifyEvent::GetDescriptor() const |
54 | {
|
56 | {
|
55 | return m_pWatch != NULL // if watch exists |
57 | return m_pWatch != NULL // if watch exists |
56 | ? m_pWatch->GetDescriptor() // return its descriptor |
58 | ? m_pWatch->GetDescriptor() // return its descriptor |
57 | : -1; // else return -1 |
59 | : -1; // else return -1 |
58 | }
|
60 | }
|
59 | 61 | ||
60 | uint32_t InotifyEvent::GetMaskByName(const std::string& rName) |
62 | uint32_t InotifyEvent::GetMaskByName(const std::string& rName) |
61 | {
|
63 | {
|
62 | if (rName == "IN_ACCESS") |
64 | if (rName == "IN_ACCESS") |
63 | return IN_ACCESS; |
65 | return IN_ACCESS; |
64 | else if (rName == "IN_MODIFY") |
66 | else if (rName == "IN_MODIFY") |
65 | return IN_MODIFY; |
67 | return IN_MODIFY; |
66 | else if (rName == "IN_ATTRIB") |
68 | else if (rName == "IN_ATTRIB") |
67 | return IN_ATTRIB; |
69 | return IN_ATTRIB; |
68 | else if (rName == "IN_CLOSE_WRITE") |
70 | else if (rName == "IN_CLOSE_WRITE") |
69 | return IN_CLOSE_WRITE; |
71 | return IN_CLOSE_WRITE; |
70 | else if (rName == "IN_CLOSE_NOWRITE") |
72 | else if (rName == "IN_CLOSE_NOWRITE") |
71 | return IN_CLOSE_NOWRITE; |
73 | return IN_CLOSE_NOWRITE; |
72 | else if (rName == "IN_OPEN") |
74 | else if (rName == "IN_OPEN") |
73 | return IN_OPEN; |
75 | return IN_OPEN; |
74 | else if (rName == "IN_MOVED_FROM") |
76 | else if (rName == "IN_MOVED_FROM") |
75 | return IN_MOVED_FROM; |
77 | return IN_MOVED_FROM; |
76 | else if (rName == "IN_MOVED_TO") |
78 | else if (rName == "IN_MOVED_TO") |
77 | return IN_MOVED_TO; |
79 | return IN_MOVED_TO; |
78 | else if (rName == "IN_CREATE") |
80 | else if (rName == "IN_CREATE") |
79 | return IN_CREATE; |
81 | return IN_CREATE; |
80 | else if (rName == "IN_DELETE") |
82 | else if (rName == "IN_DELETE") |
81 | return IN_DELETE; |
83 | return IN_DELETE; |
82 | else if (rName == "IN_DELETE_SELF") |
84 | else if (rName == "IN_DELETE_SELF") |
83 | return IN_DELETE_SELF; |
85 | return IN_DELETE_SELF; |
84 | else if (rName == "IN_UNMOUNT") |
86 | else if (rName == "IN_UNMOUNT") |
85 | return IN_UNMOUNT; |
87 | return IN_UNMOUNT; |
86 | else if (rName == "IN_Q_OVERFLOW") |
88 | else if (rName == "IN_Q_OVERFLOW") |
87 | return IN_Q_OVERFLOW; |
89 | return IN_Q_OVERFLOW; |
88 | else if (rName == "IN_IGNORED") |
90 | else if (rName == "IN_IGNORED") |
89 | return IN_IGNORED; |
91 | return IN_IGNORED; |
90 | else if (rName == "IN_CLOSE") |
92 | else if (rName == "IN_CLOSE") |
91 | return IN_CLOSE; |
93 | return IN_CLOSE; |
92 | else if (rName == "IN_MOVE") |
94 | else if (rName == "IN_MOVE") |
93 | return IN_MOVE; |
95 | return IN_MOVE; |
94 | else if (rName == "IN_ISDIR") |
96 | else if (rName == "IN_ISDIR") |
95 | return IN_ISDIR; |
97 | return IN_ISDIR; |
96 | else if (rName == "IN_ONESHOT") |
98 | else if (rName == "IN_ONESHOT") |
97 | return IN_ONESHOT; |
99 | return IN_ONESHOT; |
98 | else if (rName == "IN_ALL_EVENTS") |
100 | else if (rName == "IN_ALL_EVENTS") |
99 | return IN_ALL_EVENTS; |
101 | return IN_ALL_EVENTS; |
100 | 102 | ||
101 | #ifdef IN_DONT_FOLLOW
|
103 | #ifdef IN_DONT_FOLLOW
|
102 | else if (rName == "IN_DONT_FOLLOW") |
104 | else if (rName == "IN_DONT_FOLLOW") |
103 | return IN_DONT_FOLLOW; |
105 | return IN_DONT_FOLLOW; |
104 | #endif // IN_DONT_FOLLOW
|
106 | #endif // IN_DONT_FOLLOW
|
105 | 107 | ||
106 | #ifdef IN_ONLYDIR
|
108 | #ifdef IN_ONLYDIR
|
107 | else if (rName == "IN_ONLYDIR") |
109 | else if (rName == "IN_ONLYDIR") |
108 | return IN_ONLYDIR; |
110 | return IN_ONLYDIR; |
109 | #endif // IN_ONLYDIR
|
111 | #endif // IN_ONLYDIR
|
110 | 112 | ||
111 | #ifdef IN_MOVE_SELF
|
113 | #ifdef IN_MOVE_SELF
|
112 | else if (rName == "IN_MOVE_SELF") |
114 | else if (rName == "IN_MOVE_SELF") |
113 | return IN_MOVE_SELF; |
115 | return IN_MOVE_SELF; |
114 | #endif // IN_MOVE_SELF
|
116 | #endif // IN_MOVE_SELF
|
115 | 117 | ||
116 | return (uint32_t) 0; |
118 | return (uint32_t) 0; |
117 | }
|
119 | }
|
118 | 120 | ||
119 | void InotifyEvent::DumpTypes(uint32_t uValue, std::string& rStr) |
121 | void InotifyEvent::DumpTypes(uint32_t uValue, std::string& rStr) |
120 | {
|
122 | {
|
121 | rStr = ""; |
123 | rStr = ""; |
122 | 124 | ||
123 | if (IsType(uValue, IN_ALL_EVENTS)) { |
125 | if (IsType(uValue, IN_ALL_EVENTS)) { |
124 | rStr.append("IN_ALL_EVENTS"); |
126 | rStr.append("IN_ALL_EVENTS"); |
125 | }
|
127 | }
|
126 | else { |
128 | else { |
127 | if (IsType(uValue, IN_ACCESS)) { |
129 | if (IsType(uValue, IN_ACCESS)) { |
128 | DUMP_SEP;
|
130 | DUMP_SEP;
|
129 | rStr.append("IN_ACCESS"); |
131 | rStr.append("IN_ACCESS"); |
130 | }
|
132 | }
|
131 | if (IsType(uValue, IN_MODIFY)) { |
133 | if (IsType(uValue, IN_MODIFY)) { |
132 | DUMP_SEP;
|
134 | DUMP_SEP;
|
133 | rStr.append("IN_MODIFY"); |
135 | rStr.append("IN_MODIFY"); |
134 | }
|
136 | }
|
135 | if (IsType(uValue, IN_ATTRIB)) { |
137 | if (IsType(uValue, IN_ATTRIB)) { |
136 | DUMP_SEP;
|
138 | DUMP_SEP;
|
137 | rStr.append("IN_ATTRIB"); |
139 | rStr.append("IN_ATTRIB"); |
138 | }
|
140 | }
|
139 | if (IsType(uValue, IN_CREATE)) { |
141 | if (IsType(uValue, IN_CREATE)) { |
140 | DUMP_SEP;
|
142 | DUMP_SEP;
|
141 | rStr.append("IN_CREATE"); |
143 | rStr.append("IN_CREATE"); |
142 | }
|
144 | }
|
143 | if (IsType(uValue, IN_DELETE)) { |
145 | if (IsType(uValue, IN_DELETE)) { |
144 | DUMP_SEP;
|
146 | DUMP_SEP;
|
145 | rStr.append("IN_DELETE"); |
147 | rStr.append("IN_DELETE"); |
146 | }
|
148 | }
|
147 | if (IsType(uValue, IN_DELETE_SELF)) { |
149 | if (IsType(uValue, IN_DELETE_SELF)) { |
148 | DUMP_SEP;
|
150 | DUMP_SEP;
|
149 | rStr.append("IN_DELETE_SELF"); |
151 | rStr.append("IN_DELETE_SELF"); |
150 | }
|
152 | }
|
151 | if (IsType(uValue, IN_OPEN)) { |
153 | if (IsType(uValue, IN_OPEN)) { |
152 | DUMP_SEP;
|
154 | DUMP_SEP;
|
153 | rStr.append("IN_OPEN"); |
155 | rStr.append("IN_OPEN"); |
154 | }
|
156 | }
|
155 | if (IsType(uValue, IN_CLOSE)) { |
157 | if (IsType(uValue, IN_CLOSE)) { |
156 | DUMP_SEP;
|
158 | DUMP_SEP;
|
157 | rStr.append("IN_CLOSE"); |
159 | rStr.append("IN_CLOSE"); |
158 | }
|
160 | }
|
159 | 161 | ||
160 | #ifdef IN_MOVE_SELF
|
162 | #ifdef IN_MOVE_SELF
|
161 | if (IsType(uValue, IN_MOVE_SELF)) { |
163 | if (IsType(uValue, IN_MOVE_SELF)) { |
162 | DUMP_SEP;
|
164 | DUMP_SEP;
|
163 | rStr.append("IN_MOVE_SELF"); |
165 | rStr.append("IN_MOVE_SELF"); |
164 | }
|
166 | }
|
165 | #endif // IN_MOVE_SELF
|
167 | #endif // IN_MOVE_SELF
|
166 | 168 | ||
167 | else { |
169 | else { |
168 | if (IsType(uValue, IN_CLOSE_WRITE)) { |
170 | if (IsType(uValue, IN_CLOSE_WRITE)) { |
169 | DUMP_SEP;
|
171 | DUMP_SEP;
|
170 | rStr.append("IN_CLOSE_WRITE"); |
172 | rStr.append("IN_CLOSE_WRITE"); |
171 | }
|
173 | }
|
172 | if (IsType(uValue, IN_CLOSE_NOWRITE)) { |
174 | if (IsType(uValue, IN_CLOSE_NOWRITE)) { |
173 | DUMP_SEP;
|
175 | DUMP_SEP;
|
174 | rStr.append("IN_CLOSE_NOWRITE"); |
176 | rStr.append("IN_CLOSE_NOWRITE"); |
175 | }
|
177 | }
|
176 | }
|
178 | }
|
177 | if (IsType(uValue, IN_MOVE)) { |
179 | if (IsType(uValue, IN_MOVE)) { |
178 | DUMP_SEP;
|
180 | DUMP_SEP;
|
179 | rStr.append("IN_MOVE"); |
181 | rStr.append("IN_MOVE"); |
180 | }
|
182 | }
|
181 | else { |
183 | else { |
182 | if (IsType(uValue, IN_MOVED_FROM)) { |
184 | if (IsType(uValue, IN_MOVED_FROM)) { |
183 | DUMP_SEP;
|
185 | DUMP_SEP;
|
184 | rStr.append("IN_MOVED_FROM"); |
186 | rStr.append("IN_MOVED_FROM"); |
185 | }
|
187 | }
|
186 | if (IsType(uValue, IN_MOVED_TO)) { |
188 | if (IsType(uValue, IN_MOVED_TO)) { |
187 | DUMP_SEP;
|
189 | DUMP_SEP;
|
188 | rStr.append("IN_MOVED_TO"); |
190 | rStr.append("IN_MOVED_TO"); |
189 | }
|
191 | }
|
190 | }
|
192 | }
|
191 | }
|
193 | }
|
192 | if (IsType(uValue, IN_UNMOUNT)) { |
194 | if (IsType(uValue, IN_UNMOUNT)) { |
193 | DUMP_SEP;
|
195 | DUMP_SEP;
|
194 | rStr.append("IN_UNMOUNT"); |
196 | rStr.append("IN_UNMOUNT"); |
195 | }
|
197 | }
|
196 | if (IsType(uValue, IN_Q_OVERFLOW)) { |
198 | if (IsType(uValue, IN_Q_OVERFLOW)) { |
197 | DUMP_SEP;
|
199 | DUMP_SEP;
|
198 | rStr.append("IN_Q_OVERFLOW"); |
200 | rStr.append("IN_Q_OVERFLOW"); |
199 | }
|
201 | }
|
200 | if (IsType(uValue, IN_IGNORED)) { |
202 | if (IsType(uValue, IN_IGNORED)) { |
201 | DUMP_SEP;
|
203 | DUMP_SEP;
|
202 | rStr.append("IN_IGNORED"); |
204 | rStr.append("IN_IGNORED"); |
203 | }
|
205 | }
|
204 | if (IsType(uValue, IN_ISDIR)) { |
206 | if (IsType(uValue, IN_ISDIR)) { |
205 | DUMP_SEP;
|
207 | DUMP_SEP;
|
206 | rStr.append("IN_ISDIR"); |
208 | rStr.append("IN_ISDIR"); |
207 | }
|
209 | }
|
208 | if (IsType(uValue, IN_ONESHOT)) { |
210 | if (IsType(uValue, IN_ONESHOT)) { |
209 | DUMP_SEP;
|
211 | DUMP_SEP;
|
210 | rStr.append("IN_ONESHOT"); |
212 | rStr.append("IN_ONESHOT"); |
211 | }
|
213 | }
|
212 | 214 | ||
213 | #ifdef IN_DONT_FOLLOW
|
215 | #ifdef IN_DONT_FOLLOW
|
214 | if (IsType(uValue, IN_DONT_FOLLOW)) { |
216 | if (IsType(uValue, IN_DONT_FOLLOW)) { |
215 | DUMP_SEP;
|
217 | DUMP_SEP;
|
216 | rStr.append("IN_DONT_FOLLOW"); |
218 | rStr.append("IN_DONT_FOLLOW"); |
217 | }
|
219 | }
|
218 | #endif // IN_DONT_FOLLOW
|
220 | #endif // IN_DONT_FOLLOW
|
219 | 221 | ||
220 | #ifdef IN_ONLYDIR
|
222 | #ifdef IN_ONLYDIR
|
221 | if (IsType(uValue, IN_ONLYDIR)) { |
223 | if (IsType(uValue, IN_ONLYDIR)) { |
222 | DUMP_SEP;
|
224 | DUMP_SEP;
|
223 | rStr.append("IN_ONLYDIR"); |
225 | rStr.append("IN_ONLYDIR"); |
224 | }
|
226 | }
|
225 | #endif // IN_ONLYDIR
|
227 | #endif // IN_ONLYDIR
|
226 | }
|
228 | }
|
227 | 229 | ||
228 | void InotifyEvent::DumpTypes(std::string& rStr) const |
230 | void InotifyEvent::DumpTypes(std::string& rStr) const |
229 | {
|
231 | {
|
230 | DumpTypes(m_uMask, rStr); |
232 | DumpTypes(m_uMask, rStr); |
231 | }
|
233 | }
|
232 | 234 | ||
233 | 235 | ||
234 | void InotifyWatch::SetMask(uint32_t uMask) throw (InotifyException) |
236 | void InotifyWatch::SetMask(uint32_t uMask) throw (InotifyException) |
235 | {
|
237 | {
|
236 | IN_WRITE_BEGIN |
238 | IN_WRITE_BEGIN |
237 | 239 | ||
238 | if (m_wd != -1) { |
240 | if (m_wd != -1) { |
239 | int wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), uMask); |
241 | int wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), uMask); |
240 | if (wd != m_wd) { |
242 | if (wd != m_wd) { |
241 | IN_WRITE_END_NOTHROW |
243 | IN_WRITE_END_NOTHROW |
242 | throw InotifyException(IN_EXC_MSG("changing mask failed"), wd == -1 ? errno : EINVAL, this); |
244 | throw InotifyException(IN_EXC_MSG("changing mask failed"), wd == -1 ? errno : EINVAL, this); |
243 | }
|
245 | }
|
244 | }
|
246 | }
|
245 | 247 | ||
246 | m_uMask = uMask; |
248 | m_uMask = uMask; |
247 | 249 | ||
248 | IN_WRITE_END |
250 | IN_WRITE_END |
249 | }
|
251 | }
|
250 | 252 | ||
251 | void InotifyWatch::SetEnabled(bool fEnabled) throw (InotifyException) |
253 | void InotifyWatch::SetEnabled(bool fEnabled) throw (InotifyException) |
252 | {
|
254 | {
|
253 | IN_WRITE_BEGIN |
255 | IN_WRITE_BEGIN |
254 | 256 | ||
255 | if (fEnabled == m_fEnabled) { |
257 | if (fEnabled == m_fEnabled) { |
256 | IN_WRITE_END_NOTHROW |
258 | IN_WRITE_END_NOTHROW |
257 | return; |
259 | return; |
258 | }
|
260 | }
|
259 | 261 | ||
260 | if (m_pInotify != NULL) { |
262 | if (m_pInotify != NULL) { |
261 | if (fEnabled) { |
263 | if (fEnabled) { |
262 | m_wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), m_uMask); |
264 | m_wd = inotify_add_watch(m_pInotify->GetDescriptor(), m_path.c_str(), m_uMask); |
263 | if (m_wd == -1) { |
265 | if (m_wd == -1) { |
264 | IN_WRITE_END_NOTHROW |
266 | IN_WRITE_END_NOTHROW |
265 | throw InotifyException(IN_EXC_MSG("enabling watch failed"), errno, this); |
267 | throw InotifyException(IN_EXC_MSG("enabling watch failed"), errno, this); |
266 | }
|
268 | }
|
267 | m_pInotify->m_watches.insert(IN_WATCH_MAP::value_type(m_wd, this)); |
269 | m_pInotify->m_watches.insert(IN_WATCH_MAP::value_type(m_wd, this)); |
268 | }
|
270 | }
|
269 | else { |
271 | else { |
270 | if (inotify_rm_watch(m_pInotify->GetDescriptor(), m_wd) != 0) { |
272 | if (inotify_rm_watch(m_pInotify->GetDescriptor(), m_wd) != 0) { |
271 | IN_WRITE_END_NOTHROW |
273 | IN_WRITE_END_NOTHROW |
272 | throw InotifyException(IN_EXC_MSG("disabling watch failed"), errno, this); |
274 | throw InotifyException(IN_EXC_MSG("disabling watch failed"), errno, this); |
273 | }
|
275 | }
|
274 | m_pInotify->m_watches.erase(m_wd); |
276 | m_pInotify->m_watches.erase(m_wd); |
275 | m_wd = -1; |
277 | m_wd = -1; |
276 | }
|
278 | }
|
277 | }
|
279 | }
|
278 | 280 | ||
279 | m_fEnabled = fEnabled; |
281 | m_fEnabled = fEnabled; |
280 | 282 | ||
281 | IN_WRITE_END |
283 | IN_WRITE_END |
282 | }
|
284 | }
|
283 | 285 | ||
284 | void InotifyWatch::__Disable() |
286 | void InotifyWatch::__Disable() |
285 | {
|
287 | {
|
286 | IN_WRITE_BEGIN |
288 | IN_WRITE_BEGIN |
287 | 289 | ||
288 | if (!m_fEnabled) { |
290 | if (!m_fEnabled) { |
289 | IN_WRITE_END_NOTHROW |
291 | IN_WRITE_END_NOTHROW |
290 | throw InotifyException(IN_EXC_MSG("event cannot occur on disabled watch"), EINVAL, this); |
292 | throw InotifyException(IN_EXC_MSG("event cannot occur on disabled watch"), EINVAL, this); |
291 | }
|
293 | }
|
292 | 294 | ||
293 | if (m_pInotify != NULL) { |
295 | if (m_pInotify != NULL) { |
294 | m_pInotify->m_watches.erase(m_wd); |
296 | m_pInotify->m_watches.erase(m_wd); |
295 | m_wd = -1; |
297 | m_wd = -1; |
296 | }
|
298 | }
|
297 | 299 | ||
298 | m_fEnabled = false; |
300 | m_fEnabled = false; |
299 | 301 | ||
300 | IN_WRITE_END |
302 | IN_WRITE_END |
301 | }
|
303 | }
|
302 | 304 | ||
303 | 305 | ||
304 | Inotify::Inotify() throw (InotifyException) |
306 | Inotify::Inotify() throw (InotifyException) |
305 | {
|
307 | {
|
306 | IN_LOCK_INIT |
308 | IN_LOCK_INIT |
307 | 309 | ||
308 | m_fd = inotify_init(); |
310 | m_fd = inotify_init(); |
309 | if (m_fd == -1) { |
311 | if (m_fd == -1) { |
310 | IN_LOCK_DONE |
312 | IN_LOCK_DONE |
311 | throw InotifyException(IN_EXC_MSG("inotify init failed"), errno, NULL); |
313 | throw InotifyException(IN_EXC_MSG("inotify init failed"), errno, NULL); |
312 | }
|
314 | }
|
313 | }
|
315 | }
|
314 | 316 | ||
315 | Inotify::~Inotify() |
317 | Inotify::~Inotify() |
316 | {
|
318 | {
|
317 | Close(); |
319 | Close(); |
318 | 320 | ||
319 | IN_LOCK_DONE |
321 | IN_LOCK_DONE |
320 | }
|
322 | }
|
321 | 323 | ||
322 | void Inotify::Close() |
324 | void Inotify::Close() |
323 | {
|
325 | {
|
324 | IN_WRITE_BEGIN |
326 | IN_WRITE_BEGIN |
325 | 327 | ||
326 | if (m_fd != -1) { |
328 | if (m_fd != -1) { |
327 | RemoveAll(); |
329 | RemoveAll(); |
328 | close(m_fd); |
330 | close(m_fd); |
329 | m_fd = -1; |
331 | m_fd = -1; |
330 | }
|
332 | }
|
331 | 333 | ||
332 | IN_WRITE_END |
334 | IN_WRITE_END |
333 | }
|
335 | }
|
334 | 336 | ||
335 | void Inotify::Add(InotifyWatch* pWatch) throw (InotifyException) |
337 | void Inotify::Add(InotifyWatch* pWatch) throw (InotifyException) |
336 | {
|
338 | {
|
337 | IN_WRITE_BEGIN |
339 | IN_WRITE_BEGIN |
338 | 340 | ||
339 | // invalid descriptor - this case shouldn't occur - go away
|
341 | // invalid descriptor - this case shouldn't occur - go away
|
340 | if (m_fd == -1) { |
342 | if (m_fd == -1) { |
341 | IN_WRITE_END_NOTHROW |
343 | IN_WRITE_END_NOTHROW |
342 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
344 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
343 | }
|
345 | }
|
344 | 346 | ||
345 | // this path already watched - go away
|
347 | // this path already watched - go away
|
346 | if (FindWatch(pWatch->GetPath()) != NULL) { |
348 | if (FindWatch(pWatch->GetPath()) != NULL) { |
347 | IN_WRITE_END_NOTHROW |
349 | IN_WRITE_END_NOTHROW |
348 | throw InotifyException(IN_EXC_MSG("path already watched"), EBUSY, this); |
350 | throw InotifyException(IN_EXC_MSG("path already watched"), EBUSY, this); |
349 | }
|
351 | }
|
350 | 352 | ||
351 | // for enabled watch
|
353 | // for enabled watch
|
352 | if (pWatch->IsEnabled()) { |
354 | if (pWatch->IsEnabled()) { |
353 | 355 | ||
354 | // try to add watch to kernel
|
356 | // try to add watch to kernel
|
355 | int wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask()); |
357 | int wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask()); |
356 | 358 | ||
357 | // adding failed - go away
|
359 | // adding failed - go away
|
358 | if (wd == -1) { |
360 | if (wd == -1) { |
359 | IN_WRITE_END_NOTHROW |
361 | IN_WRITE_END_NOTHROW |
360 | throw InotifyException(IN_EXC_MSG("adding watch failed"), errno, this); |
362 | throw InotifyException(IN_EXC_MSG("adding watch failed"), errno, this); |
361 | }
|
363 | }
|
362 | 364 | ||
363 | // this path already watched (but defined another way)
|
365 | // this path already watched (but defined another way)
|
364 | InotifyWatch* pW = FindWatch(wd); |
366 | InotifyWatch* pW = FindWatch(wd); |
365 | if (pW != NULL) { |
367 | if (pW != NULL) { |
366 | 368 | ||
367 | // try to recover old watch because it may be modified - then go away
|
369 | // try to recover old watch because it may be modified - then go away
|
368 | if (inotify_add_watch(m_fd, pW->GetPath().c_str(), pW->GetMask()) < 0) { |
370 | if (inotify_add_watch(m_fd, pW->GetPath().c_str(), pW->GetMask()) < 0) { |
369 | IN_WRITE_END_NOTHROW |
371 | IN_WRITE_END_NOTHROW |
370 | throw InotifyException(IN_EXC_MSG("watch collision detected and recovery failed"), errno, this); |
372 | throw InotifyException(IN_EXC_MSG("watch collision detected and recovery failed"), errno, this); |
371 | }
|
373 | }
|
372 | else { |
374 | else { |
373 | // recovery failed - go away
|
375 | // recovery failed - go away
|
374 | IN_WRITE_END_NOTHROW |
376 | IN_WRITE_END_NOTHROW |
375 | throw InotifyException(IN_EXC_MSG("path already watched (but defined another way)"), EBUSY, this); |
377 | throw InotifyException(IN_EXC_MSG("path already watched (but defined another way)"), EBUSY, this); |
376 | }
|
378 | }
|
377 | }
|
379 | }
|
378 | 380 | ||
379 | pWatch->m_wd = wd; |
381 | pWatch->m_wd = wd; |
380 | m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch)); |
382 | m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch)); |
381 | }
|
383 | }
|
382 | 384 | ||
383 | m_paths.insert(IN_WP_MAP::value_type(pWatch->m_path, pWatch)); |
385 | m_paths.insert(IN_WP_MAP::value_type(pWatch->m_path, pWatch)); |
384 | pWatch->m_pInotify = this; |
386 | pWatch->m_pInotify = this; |
385 | 387 | ||
386 | IN_WRITE_END |
388 | IN_WRITE_END |
387 | }
|
389 | }
|
388 | 390 | ||
389 | void Inotify::Remove(InotifyWatch* pWatch) throw (InotifyException) |
391 | void Inotify::Remove(InotifyWatch* pWatch) throw (InotifyException) |
390 | {
|
392 | {
|
391 | IN_WRITE_BEGIN |
393 | IN_WRITE_BEGIN |
392 | 394 | ||
393 | // invalid descriptor - this case shouldn't occur - go away
|
395 | // invalid descriptor - this case shouldn't occur - go away
|
394 | if (m_fd == -1) { |
396 | if (m_fd == -1) { |
395 | IN_WRITE_END_NOTHROW |
397 | IN_WRITE_END_NOTHROW |
396 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
398 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
397 | }
|
399 | }
|
398 | 400 | ||
399 | // for enabled watch
|
401 | // for enabled watch
|
400 | if (pWatch->m_wd != -1) { |
402 | if (pWatch->m_wd != -1) { |
401 | 403 | ||
402 | // removing watch failed - go away
|
404 | // removing watch failed - go away
|
403 | if (inotify_rm_watch(m_fd, pWatch->m_wd) == -1) { |
405 | if (inotify_rm_watch(m_fd, pWatch->m_wd) == -1) { |
404 | IN_WRITE_END_NOTHROW |
406 | IN_WRITE_END_NOTHROW |
405 | throw InotifyException(IN_EXC_MSG("removing watch failed"), errno, this); |
407 | throw InotifyException(IN_EXC_MSG("removing watch failed"), errno, this); |
406 | }
|
408 | }
|
407 | m_watches.erase(pWatch->m_wd); |
409 | m_watches.erase(pWatch->m_wd); |
408 | pWatch->m_wd = -1; |
410 | pWatch->m_wd = -1; |
409 | }
|
411 | }
|
410 | 412 | ||
411 | m_paths.erase(pWatch->m_path); |
413 | m_paths.erase(pWatch->m_path); |
412 | pWatch->m_pInotify = NULL; |
414 | pWatch->m_pInotify = NULL; |
413 | 415 | ||
414 | IN_WRITE_END |
416 | IN_WRITE_END |
415 | }
|
417 | }
|
416 | 418 | ||
417 | void Inotify::RemoveAll() |
419 | void Inotify::RemoveAll() |
418 | {
|
420 | {
|
419 | IN_WRITE_BEGIN |
421 | IN_WRITE_BEGIN |
420 | 422 | ||
421 | IN_WP_MAP::iterator it = m_paths.begin(); |
423 | IN_WP_MAP::iterator it = m_paths.begin(); |
422 | while (it != m_paths.end()) { |
424 | while (it != m_paths.end()) { |
423 | InotifyWatch* pW = (*it).second; |
425 | InotifyWatch* pW = (*it).second; |
424 | if (pW->m_wd != -1) { |
426 | if (pW->m_wd != -1) { |
425 | inotify_rm_watch(m_fd, pW->m_wd); |
427 | inotify_rm_watch(m_fd, pW->m_wd); |
426 | pW->m_wd = -1; |
428 | pW->m_wd = -1; |
427 | }
|
429 | }
|
428 | pW->m_pInotify = NULL; |
430 | pW->m_pInotify = NULL; |
429 | it++; |
431 | it++; |
430 | }
|
432 | }
|
431 | 433 | ||
432 | m_watches.clear(); |
434 | m_watches.clear(); |
433 | m_paths.clear(); |
435 | m_paths.clear(); |
434 | 436 | ||
435 | IN_WRITE_END |
437 | IN_WRITE_END |
436 | }
|
438 | }
|
437 | 439 | ||
438 | void Inotify::WaitForEvents(bool fNoIntr) throw (InotifyException) |
440 | void Inotify::WaitForEvents(bool fNoIntr) throw (InotifyException) |
439 | {
|
441 | {
|
440 | ssize_t len = 0; |
442 | ssize_t len = 0; |
441 | 443 | ||
442 | do { |
444 | do { |
443 | len = read(m_fd, m_buf, INOTIFY_BUFLEN); |
445 | len = read(m_fd, m_buf, INOTIFY_BUFLEN); |
444 | } while (fNoIntr && len == -1 && errno == EINTR); |
446 | } while (fNoIntr && len == -1 && errno == EINTR); |
445 | 447 | ||
446 | if (len == -1 && !(errno == EWOULDBLOCK || errno == EINTR)) |
448 | if (len == -1 && !(errno == EWOULDBLOCK || errno == EINTR)) |
447 | throw InotifyException(IN_EXC_MSG("reading events failed"), errno, this); |
449 | throw InotifyException(IN_EXC_MSG("reading events failed"), errno, this); |
448 | 450 | ||
449 | if (len == -1) |
451 | if (len == -1) |
450 | return; |
452 | return; |
451 | 453 | ||
452 | IN_WRITE_BEGIN |
454 | IN_WRITE_BEGIN |
453 | 455 | ||
454 | ssize_t i = 0; |
456 | ssize_t i = 0; |
455 | while (i < len) { |
457 | while (i < len) { |
456 | struct inotify_event* pEvt = (struct inotify_event*) &m_buf[i]; |
458 | struct inotify_event* pEvt = (struct inotify_event*) &m_buf[i]; |
457 | InotifyWatch* pW = FindWatch(pEvt->wd); |
459 | InotifyWatch* pW = FindWatch(pEvt->wd); |
458 | if (pW != NULL) { |
460 | if (pW != NULL) { |
459 | InotifyEvent evt(pEvt, pW); |
461 | InotifyEvent evt(pEvt, pW); |
460 | if ( InotifyEvent::IsType(pW->GetMask(), IN_ONESHOT) |
462 | if ( InotifyEvent::IsType(pW->GetMask(), IN_ONESHOT) |
461 | || InotifyEvent::IsType(evt.GetMask(), IN_IGNORED)) |
463 | || InotifyEvent::IsType(evt.GetMask(), IN_IGNORED)) |
462 | pW->__Disable(); |
464 | pW->__Disable(); |
463 | m_events.push_back(evt); |
465 | m_events.push_back(evt); |
464 | }
|
466 | }
|
465 | i += INOTIFY_EVENT_SIZE + (ssize_t) pEvt->len; |
467 | i += INOTIFY_EVENT_SIZE + (ssize_t) pEvt->len; |
466 | }
|
468 | }
|
467 | 469 | ||
468 | IN_WRITE_END |
470 | IN_WRITE_END |
469 | }
|
471 | }
|
470 | 472 | ||
471 | bool Inotify::GetEvent(InotifyEvent* pEvt) throw (InotifyException) |
473 | bool Inotify::GetEvent(InotifyEvent* pEvt) throw (InotifyException) |
472 | {
|
474 | {
|
473 | if (pEvt == NULL) |
475 | if (pEvt == NULL) |
474 | throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this); |
476 | throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this); |
475 | 477 | ||
476 | IN_WRITE_BEGIN |
478 | IN_WRITE_BEGIN |
477 | 479 | ||
478 | bool b = !m_events.empty(); |
480 | bool b = !m_events.empty(); |
479 | if (b) { |
481 | if (b) { |
480 | *pEvt = m_events.front(); |
482 | *pEvt = m_events.front(); |
481 | m_events.pop_front(); |
483 | m_events.pop_front(); |
482 | }
|
484 | }
|
483 | 485 | ||
484 | IN_WRITE_END |
486 | IN_WRITE_END |
485 | 487 | ||
486 | return b; |
488 | return b; |
487 | }
|
489 | }
|
488 | 490 | ||
489 | bool Inotify::PeekEvent(InotifyEvent* pEvt) throw (InotifyException) |
491 | bool Inotify::PeekEvent(InotifyEvent* pEvt) throw (InotifyException) |
490 | {
|
492 | {
|
491 | if (pEvt == NULL) |
493 | if (pEvt == NULL) |
492 | throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this); |
494 | throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this); |
493 | 495 | ||
494 | IN_READ_BEGIN |
496 | IN_READ_BEGIN |
495 | 497 | ||
496 | bool b = !m_events.empty(); |
498 | bool b = !m_events.empty(); |
497 | if (b) { |
499 | if (b) { |
498 | *pEvt = m_events.front(); |
500 | *pEvt = m_events.front(); |
499 | }
|
501 | }
|
500 | 502 | ||
501 | IN_READ_END |
503 | IN_READ_END |
502 | 504 | ||
503 | return b; |
505 | return b; |
504 | }
|
506 | }
|
505 | 507 | ||
506 | InotifyWatch* Inotify::FindWatch(int iDescriptor) |
508 | InotifyWatch* Inotify::FindWatch(int iDescriptor) |
507 | {
|
509 | {
|
508 | IN_READ_BEGIN |
510 | IN_READ_BEGIN |
509 | 511 | ||
510 | IN_WATCH_MAP::iterator it = m_watches.find(iDescriptor); |
512 | IN_WATCH_MAP::iterator it = m_watches.find(iDescriptor); |
511 | InotifyWatch* pW = it == m_watches.end() ? NULL : (*it).second; |
513 | InotifyWatch* pW = it == m_watches.end() ? NULL : (*it).second; |
512 | 514 | ||
513 | IN_READ_END |
515 | IN_READ_END |
514 | 516 | ||
515 | return pW; |
517 | return pW; |
516 | }
|
518 | }
|
517 | 519 | ||
518 | InotifyWatch* Inotify::FindWatch(const std::string& rPath) |
520 | InotifyWatch* Inotify::FindWatch(const std::string& rPath) |
519 | {
|
521 | {
|
520 | IN_READ_BEGIN |
522 | IN_READ_BEGIN |
521 | 523 | ||
522 | IN_WP_MAP::iterator it = m_paths.find(rPath); |
524 | IN_WP_MAP::iterator it = m_paths.find(rPath); |
523 | InotifyWatch* pW = it == m_paths.end() ? NULL : (*it).second; |
525 | InotifyWatch* pW = it == m_paths.end() ? NULL : (*it).second; |
524 | 526 | ||
525 | IN_READ_END |
527 | IN_READ_END |
526 | 528 | ||
527 | return pW; |
529 | return pW; |
528 | }
|
530 | }
|
529 | 531 | ||
530 | void Inotify::SetNonBlock(bool fNonBlock) throw (InotifyException) |
532 | void Inotify::SetNonBlock(bool fNonBlock) throw (InotifyException) |
531 | {
|
533 | {
|
532 | IN_WRITE_BEGIN |
534 | IN_WRITE_BEGIN |
533 | 535 | ||
534 | if (m_fd == -1) { |
536 | if (m_fd == -1) { |
535 | IN_WRITE_END_NOTHROW |
537 | IN_WRITE_END_NOTHROW |
536 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
538 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
537 | }
|
539 | }
|
538 | 540 | ||
539 | int res = fcntl(m_fd, F_GETFL); |
541 | int res = fcntl(m_fd, F_GETFL); |
540 | if (res == -1) { |
542 | if (res == -1) { |
541 | IN_WRITE_END_NOTHROW |
543 | IN_WRITE_END_NOTHROW |
542 | throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this); |
544 | throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this); |
543 | }
|
545 | }
|
544 | 546 | ||
545 | if (fNonBlock) { |
547 | if (fNonBlock) { |
546 | res |= O_NONBLOCK; |
548 | res |= O_NONBLOCK; |
547 | }
|
549 | }
|
548 | else { |
550 | else { |
549 | res &= ~O_NONBLOCK; |
551 | res &= ~O_NONBLOCK; |
550 | }
|
552 | }
|
551 | 553 | ||
552 | if (fcntl(m_fd, F_SETFL, res) == -1) { |
554 | if (fcntl(m_fd, F_SETFL, res) == -1) { |
553 | IN_WRITE_END_NOTHROW |
555 | IN_WRITE_END_NOTHROW |
554 | throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this); |
556 | throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this); |
555 | }
|
557 | }
|
556 | 558 | ||
557 | IN_WRITE_END |
559 | IN_WRITE_END |
558 | }
|
560 | }
|
559 | 561 | ||
560 | void Inotify::SetCloseOnExec(bool fClOnEx) throw (InotifyException) |
562 | void Inotify::SetCloseOnExec(bool fClOnEx) throw (InotifyException) |
561 | {
|
563 | {
|
562 | IN_WRITE_BEGIN |
564 | IN_WRITE_BEGIN |
563 | 565 | ||
564 | if (m_fd == -1) { |
566 | if (m_fd == -1) { |
565 | IN_WRITE_END_NOTHROW |
567 | IN_WRITE_END_NOTHROW |
566 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
568 | throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this); |
567 | }
|
569 | }
|
568 | 570 | ||
569 | int res = fcntl(m_fd, F_GETFD); |
571 | int res = fcntl(m_fd, F_GETFD); |
570 | if (res == -1) { |
572 | if (res == -1) { |
571 | IN_WRITE_END_NOTHROW |
573 | IN_WRITE_END_NOTHROW |
572 | throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this); |
574 | throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this); |
573 | }
|
575 | }
|
574 | 576 | ||
575 | if (fClOnEx) { |
577 | if (fClOnEx) { |
576 | res |= FD_CLOEXEC; |
578 | res |= FD_CLOEXEC; |
577 | }
|
579 | }
|
578 | else { |
580 | else { |
579 | res &= ~FD_CLOEXEC; |
581 | res &= ~FD_CLOEXEC; |
580 | }
|
582 | }
|
581 | 583 | ||
582 | if (fcntl(m_fd, F_SETFD, res) == -1) { |
584 | if (fcntl(m_fd, F_SETFD, res) == -1) { |
583 | IN_WRITE_END_NOTHROW |
585 | IN_WRITE_END_NOTHROW |
584 | throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this); |
586 | throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this); |
585 | }
|
587 | }
|
586 | 588 | ||
587 | IN_WRITE_END |
589 | IN_WRITE_END |
588 | }
|
590 | }
|
589 | 591 | ||
590 | uint32_t Inotify::GetCapability(InotifyCapability_t cap) throw (InotifyException) |
592 | uint32_t Inotify::GetCapability(InotifyCapability_t cap) throw (InotifyException) |
591 | {
|
593 | {
|
592 | FILE* f = fopen(GetCapabilityPath(cap).c_str(), "r"); |
594 | FILE* f = fopen(GetCapabilityPath(cap).c_str(), "r"); |
593 | if (f == NULL) |
595 | if (f == NULL) |
594 | throw InotifyException(IN_EXC_MSG("cannot get capability"), errno, NULL); |
596 | throw InotifyException(IN_EXC_MSG("cannot get capability"), errno, NULL); |
595 | 597 | ||
596 | unsigned int val = 0; |
598 | unsigned int val = 0; |
597 | if (fscanf(f, "%u", &val) != 1) { |
599 | if (fscanf(f, "%u", &val) != 1) { |
598 | fclose(f); |
600 | fclose(f); |
599 | throw InotifyException(IN_EXC_MSG("cannot get capability"), EIO, NULL); |
601 | throw InotifyException(IN_EXC_MSG("cannot get capability"), EIO, NULL); |
600 | }
|
602 | }
|
601 | 603 | ||
602 | fclose(f); |
604 | fclose(f); |
603 | 605 | ||
604 | return (uint32_t) val; |
606 | return (uint32_t) val; |
605 | }
|
607 | }
|
606 | 608 | ||
607 | void Inotify::SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException) |
609 | void Inotify::SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException) |
608 | {
|
610 | {
|
609 | FILE* f = fopen(GetCapabilityPath(cap).c_str(), "w"); |
611 | FILE* f = fopen(GetCapabilityPath(cap).c_str(), "w"); |
610 | if (f == NULL) |
612 | if (f == NULL) |
611 | throw InotifyException(IN_EXC_MSG("cannot set capability"), errno, NULL); |
613 | throw InotifyException(IN_EXC_MSG("cannot set capability"), errno, NULL); |
612 | 614 | ||
613 | if (fprintf(f, "%u", (unsigned int) val) <= 0) { |
615 | if (fprintf(f, "%u", (unsigned int) val) <= 0) { |
614 | fclose(f); |
616 | fclose(f); |
615 | throw InotifyException(IN_EXC_MSG("cannot set capability"), EIO, NULL); |
617 | throw InotifyException(IN_EXC_MSG("cannot set capability"), EIO, NULL); |
616 | }
|
618 | }
|
617 | 619 | ||
618 | fclose(f); |
620 | fclose(f); |
619 | }
|
621 | }
|
620 | 622 | ||
621 | std::string Inotify::GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException) |
623 | std::string Inotify::GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException) |
622 | {
|
624 | {
|
623 | std::string path(PROCFS_INOTIFY_BASE); |
625 | std::string path(PROCFS_INOTIFY_BASE); |
624 | 626 | ||
625 | switch (cap) { |
627 | switch (cap) { |
626 | case IN_MAX_EVENTS: |
628 | case IN_MAX_EVENTS: |
627 | path.append("max_queued_events"); |
629 | path.append("max_queued_events"); |
628 | break; |
630 | break; |
629 | case IN_MAX_INSTANCES: |
631 | case IN_MAX_INSTANCES: |
630 | path.append("max_user_instances"); |
632 | path.append("max_user_instances"); |
631 | break; |
633 | break; |
632 | case IN_MAX_WATCHES: |
634 | case IN_MAX_WATCHES: |
633 | path.append("max_user_watches"); |
635 | path.append("max_user_watches"); |
634 | break; |
636 | break; |
635 | default: |
637 | default: |
636 | throw InotifyException(IN_EXC_MSG("unknown capability type"), EINVAL, NULL); |
638 | throw InotifyException(IN_EXC_MSG("unknown capability type"), EINVAL, NULL); |
637 | }
|
639 | }
|
638 | 640 | ||
639 | return path; |
641 | return path; |
640 | }
|
642 | }
|
641 | 643 | ||
642 | 644 |