Subversion Repositories public

Rev

Rev 47 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
45 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
uint32_t InotifyEvent::GetMaskByName(const std::string& rName)
36
{
37
  if (rName == "IN_ACCESS")
38
    return IN_ACCESS;
39
  else if (rName == "IN_MODIFY")
40
    return IN_MODIFY;
41
  else if (rName == "IN_ATTRIB")
42
    return IN_ATTRIB;
43
  else if (rName == "IN_CLOSE_WRITE")
44
    return IN_CLOSE_WRITE;
45
  else if (rName == "IN_CLOSE_NOWRITE")
46
    return IN_CLOSE_NOWRITE;
47
  else if (rName == "IN_MOVED_FROM")
48
    return IN_MOVED_FROM;
49
  else if (rName == "IN_MOVED_TO")
50
    return IN_MOVED_TO;
51
  else if (rName == "IN_CREATE")
52
    return IN_CREATE;
53
  else if (rName == "IN_DELETE")
54
    return IN_DELETE;
55
  else if (rName == "IN_DELETE_SELF")
56
    return IN_DELETE_SELF;
57
  else if (rName == "IN_UNMOUNT")
58
    return IN_UNMOUNT;
59
  else if (rName == "IN_Q_OVERFLOW")
60
    return IN_Q_OVERFLOW;
61
  else if (rName == "IN_IGNORED")
62
    return IN_IGNORED;
63
  else if (rName == "IN_CLOSE")
64
    return IN_CLOSE;
65
  else if (rName == "IN_MOVE")
66
    return IN_MOVE;
67
  else if (rName == "IN_ISDIR")
68
    return IN_ISDIR;
69
  else if (rName == "IN_ONESHOT")
70
    return IN_ONESHOT;
71
  else if (rName == "IN_ALL_EVENTS")
72
    return IN_ALL_EVENTS;
73
 
74
  return (uint32_t) 0;
75
}
76
 
77
void InotifyEvent::DumpTypes(uint32_t uValue, std::string& rStr)
78
{
79
  rStr = "";
80
 
81
  if (IsType(uValue, IN_ALL_EVENTS)) {
82
    rStr.append("IN_ALL_EVENTS");
83
  }
84
  else {
85
    if (IsType(uValue, IN_ACCESS)) {
86
      DUMP_SEP;
87
      rStr.append("IN_ACCESS");    
88
    }
89
    if (IsType(uValue, IN_MODIFY)) {
90
      DUMP_SEP;
91
      rStr.append("IN_MODIFY");
92
    }
93
    if (IsType(uValue, IN_ATTRIB)) {
94
      DUMP_SEP;
95
      rStr.append("IN_ATTRIB");
96
    }
97
    if (IsType(uValue, IN_CREATE)) {
98
      DUMP_SEP;
99
      rStr.append("IN_CREATE");
100
    }
101
    if (IsType(uValue, IN_DELETE)) {
102
      DUMP_SEP;
103
      rStr.append("IN_DELETE");
104
    }
105
    if (IsType(uValue, IN_DELETE_SELF)) {
106
      DUMP_SEP;
107
      rStr.append("IN_DELETE_SELF");
108
    }
109
    if (IsType(uValue, IN_OPEN)) {
110
      DUMP_SEP;
111
      rStr.append("IN_OPEN");
112
    }
113
    if (IsType(uValue, IN_CLOSE)) {
114
      DUMP_SEP;
115
      rStr.append("IN_CLOSE");
116
    }
117
    else {
118
      if (IsType(uValue, IN_CLOSE_WRITE)) {
119
        DUMP_SEP;
120
        rStr.append("IN_CLOSE_WRITE");
121
      }
122
      if (IsType(uValue, IN_CLOSE_NOWRITE)) {
123
        DUMP_SEP;
124
        rStr.append("IN_CLOSE_NOWRITE");
125
      }
126
    }
127
    if (IsType(uValue, IN_MOVE)) {
128
      DUMP_SEP;
129
      rStr.append("IN_MOVE");
130
    }
131
    else {
132
      if (IsType(uValue, IN_MOVED_FROM)) {
133
        DUMP_SEP;
134
        rStr.append("IN_MOVED_FROM");
135
      }
136
      if (IsType(uValue, IN_MOVED_TO)) {
137
        DUMP_SEP;
138
        rStr.append("IN_MOVED_TO");
139
      }
140
    }
141
  }
142
  if (IsType(uValue, IN_UNMOUNT)) {
143
    DUMP_SEP;
144
    rStr.append("IN_UNMOUNT");
145
  }
146
  if (IsType(uValue, IN_Q_OVERFLOW)) {
147
    DUMP_SEP;
148
    rStr.append("IN_Q_OVERFLOW");
149
  }
150
  if (IsType(uValue, IN_IGNORED)) {
151
    DUMP_SEP;
152
    rStr.append("IN_IGNORED");
153
  }
154
  if (IsType(uValue, IN_ISDIR)) {
155
    DUMP_SEP;
156
    rStr.append("IN_ISDIR");
157
  }
158
  if (IsType(uValue, IN_ONESHOT)) {
159
    DUMP_SEP;
160
    rStr.append("IN_ONESHOT");
161
  }
162
}
163
 
164
void InotifyEvent::DumpTypes(std::string& rStr) const
165
{
166
  DumpTypes((uint32_t) m_evt.mask, rStr);
167
}
168
 
169
 
170
Inotify::Inotify()
171
{
172
  m_fd = inotify_init();  
173
}
174
 
175
Inotify::~Inotify()
176
{
177
  Close();
178
}
179
 
180
void Inotify::Close()
181
{
182
  if (m_fd != -1) {
183
    RemoveAll();
184
    close(m_fd);
185
    m_fd = -1;
186
  }
187
}
188
 
189
bool Inotify::Add(InotifyWatch* pWatch)
190
{
191
  if (m_fd == -1)
192
    return false;
193
 
194
  pWatch->m_wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask());
195
  if (pWatch->m_wd != -1) {
196
    m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch));
197
    pWatch->m_pInotify = this;
198
    return true;
199
  }
200
 
201
  return false;
202
}
203
 
204
void Inotify::Remove(InotifyWatch* pWatch)
205
{
206
  if (m_fd == -1)
207
    return;
208
 
209
  if (inotify_rm_watch(m_fd, pWatch->GetMask()) != -1) {
210
    m_watches.erase(pWatch->m_wd);
211
    pWatch->m_wd = -1;
212
    pWatch->m_pInotify = NULL;
213
  }
214
}
215
 
216
void Inotify::RemoveAll()
217
{
218
  IN_WATCH_MAP::iterator it = m_watches.begin();
219
  while (it != m_watches.end()) {
220
    InotifyWatch* pW = (*it).second;
221
    inotify_rm_watch(m_fd, pW->GetMask());
222
    pW->m_wd = -1;
223
    pW->m_pInotify = NULL;
224
    it++;
225
  }
226
 
227
  m_watches.clear();
228
}
229
 
230
bool Inotify::WaitForEvents(bool fNoIntr)
231
{
232
  ssize_t len = 0;
233
 
234
  do {
235
    len = read(m_fd, m_buf, INOTIFY_BUFLEN);
236
  } while (fNoIntr && len == -1 && errno == EINTR);
237
 
238
  if (len <= 0) {
239
    return false;
240
  }
241
 
242
  ssize_t i = 0;
243
  while (i < len) {
244
    InotifyWatch* pW = FindWatch(((struct inotify_event *) &m_buf[i])->wd);
245
    InotifyEvent evt((struct inotify_event *) &m_buf[i], pW);
246
    m_events.push_back(evt);
247
    i += INOTIFY_EVENT_SIZE + (int) evt.GetLength();
248
  }
249
 
250
  return true;
251
}
252
 
253
int Inotify::GetEventCount()
254
{
255
  return m_events.size();
256
}
257
 
258
bool Inotify::GetEvent(InotifyEvent* pEvt)
259
{
260
  bool b = PeekEvent(pEvt);
261
  if (b)
262
    m_events.pop_front();
263
  return b;
264
}
265
 
266
bool Inotify::PeekEvent(InotifyEvent* pEvt)
267
{
268
  if (pEvt == NULL || m_events.empty())
269
    return false;
270
 
271
  *pEvt = m_events.front();
272
 
273
  return true;
274
}
275
 
276
InotifyWatch* Inotify::FindWatch(int iDescriptor)
277
{
278
  IN_WATCH_MAP::iterator it = m_watches.find(iDescriptor);
279
  if (it == m_watches.end())
280
    return NULL;
281
 
282
  return (*it).second;
283
}
284