Subversion Repositories public

Rev

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