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