Subversion Repositories public

Rev

Rev 11 | Go to most recent revision | Details | 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>
25
 
26
#include "inotify-cxx.h"
27
 
28
#define DUMP_SEP \
29
  ({ \
30
    if (!rStr.empty()) { \
31
      rStr.append(" "); \
32
    } \
33
  })
34
 
35
 
36
void InotifyEvent::DumpTypes(std::string& rStr) const
37
{
38
  rStr = "";
39
 
40
  if (IsType(IN_ACCESS)) {
41
    rStr.append("IN_ACCESS");
42
  }
43
  if (IsType(IN_MODIFY)) {
44
    DUMP_SEP;
45
    rStr.append("IN_MODIFY");
46
  }
47
  if (IsType(IN_ATTRIB)) {
48
    DUMP_SEP;
49
    rStr.append("IN_ATTRIB");
50
  }
51
  if (IsType(IN_CLOSE_WRITE)) {
52
    DUMP_SEP;
53
    rStr.append("IN_CLOSE_WRITE");
54
  }
55
  if (IsType(IN_CLOSE_NOWRITE)) {
56
    DUMP_SEP;
57
    rStr.append("IN_CLOSE_NOWRITE");
58
  }
59
  if (IsType(IN_OPEN)) {
60
    DUMP_SEP;
61
    rStr.append("IN_OPEN");
62
  }
63
  if (IsType(IN_MOVED_FROM)) {
64
    DUMP_SEP;
65
    rStr.append("IN_MOVED_FROM");
66
  }
67
  if (IsType(IN_MOVED_TO)) {
68
    DUMP_SEP;
69
    rStr.append("IN_MOVED_TO");
70
  }
71
  if (IsType(IN_CREATE)) {
72
    DUMP_SEP;
73
    rStr.append("IN_CREATE");
74
  }
75
  if (IsType(IN_DELETE)) {
76
    DUMP_SEP;
77
    rStr.append("IN_DELETE");
78
  }
79
  if (IsType(IN_DELETE_SELF)) {
80
    DUMP_SEP;
81
    rStr.append("IN_DELETE_SELF");
82
  }
83
  if (IsType(IN_UNMOUNT)) {
84
    DUMP_SEP;
85
    rStr.append("IN_UNMOUNT");
86
  }
87
  if (IsType(IN_Q_OVERFLOW)) {
88
    DUMP_SEP;
89
    rStr.append("IN_Q_OVERFLOW");
90
  }
91
  if (IsType(IN_IGNORED)) {
92
    DUMP_SEP;
93
    rStr.append("IN_IGNORED");
94
  }
95
  if (IsType(IN_CLOSE)) {
96
    DUMP_SEP;
97
    rStr.append("IN_CLOSE");
98
  }
99
  if (IsType(IN_MOVE)) {
100
    DUMP_SEP;
101
    rStr.append("IN_MOVE");
102
  }
103
  if (IsType(IN_ISDIR)) {
104
    DUMP_SEP;
105
    rStr.append("IN_ISDIR");
106
  }
107
  if (IsType(IN_ONESHOT)) {
108
    DUMP_SEP;
109
    rStr.append("IN_ONESHOT");
110
  }
111
}
112
 
113
 
114
Inotify::Inotify()
115
{
116
  m_fd = inotify_init();  
117
}
118
 
119
Inotify::~Inotify()
120
{
121
  Close();
122
}
123
 
124
void Inotify::Close()
125
{
126
  if (m_fd != -1) {
127
    RemoveAll();
128
    close(m_fd);
129
    m_fd = -1;
130
  }
131
}
132
 
133
bool Inotify::Add(InotifyWatch* pWatch)
134
{
135
  if (m_fd == -1)
136
    return false;
137
 
138
  pWatch->m_wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask());
139
  if (pWatch->m_wd != -1) {
140
    m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch));
141
    return true;
142
  }
143
 
144
  return false;
145
}
146
 
147
void Inotify::Remove(InotifyWatch* pWatch)
148
{
149
  if (m_fd == -1)
150
    return;
151
 
152
  if (inotify_rm_watch(m_fd, pWatch->GetMask()) != -1) {
153
    m_watches.erase(pWatch->m_wd);
154
    pWatch->m_wd = -1;
155
  }
156
}
157
 
158
void Inotify::RemoveAll()
159
{
160
  IN_WATCH_MAP::iterator it = m_watches.begin();
161
  while (it != m_watches.end()) {
162
    inotify_rm_watch(m_fd, (*it).second->GetMask());
163
    it++;
164
  }
165
 
166
  m_watches.clear();
167
}
168
 
169
bool Inotify::WaitForEvents(bool fNoIntr)
170
{
171
  ssize_t len = 0;
172
 
173
  do {
174
    len = read(m_fd, m_buf, INOTIFY_BUFLEN);
175
  } while (fNoIntr && len == -1 && errno == EINTR);
176
 
177
  if (len <= 0) {
178
    return false;
179
  }
180
 
181
  ssize_t i = 0;
182
  while (i < len) {
183
    InotifyEvent evt((struct inotify_event *) &m_buf[i]);
184
    m_events.push_back(evt);
185
    i += INOTIFY_EVENT_SIZE + (int) evt.GetLength();
186
  }
187
 
188
  return true;
189
}
190
 
191
int Inotify::GetEventCount()
192
{
193
  return m_events.size();
194
}
195
 
196
bool Inotify::GetEvent(InotifyEvent* pEvt)
197
{
198
  bool b = PeekEvent(pEvt);
199
  if (b)
200
    m_events.pop_front();
201
  return b;
202
}
203
 
204
bool Inotify::PeekEvent(InotifyEvent* pEvt)
205
{
206
  if (pEvt == NULL || m_events.empty())
207
    return false;
208
 
209
  *pEvt = m_events.front();
210
 
211
  return true;
212
}
213
 
214
InotifyWatch* Inotify::FindWatch(int iDescriptor)
215
{
216
  IN_WATCH_MAP::iterator it = m_watches.find(iDescriptor);
217
  if (it == m_watches.end())
218
    return NULL;
219
 
220
  return (*it).second;
221
}
222