Subversion Repositories public

Compare Revisions

Ignore whitespace Rev 13 → Rev 12

/inotify-cxx/trunk/inotify-cxx.cpp
22,11 → 22,9
 
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
 
#include "inotify-cxx.h"
 
/// dump separator (between particular entries)
#define DUMP_SEP \
({ \
if (!rStr.empty()) { \
34,14 → 32,6
} \
})
 
 
int32_t InotifyEvent::GetDescriptor() const
{
return m_pWatch != NULL // if watch exists
? m_pWatch->GetDescriptor() // return its descriptor
: -1; // else return -1
}
 
uint32_t InotifyEvent::GetMaskByName(const std::string& rName)
{
if (rName == "IN_ACCESS")
173,15 → 163,13
 
void InotifyEvent::DumpTypes(std::string& rStr) const
{
DumpTypes(m_uMask, rStr);
DumpTypes((uint32_t) m_evt.mask, rStr);
}
 
 
Inotify::Inotify() throw (InotifyException)
Inotify::Inotify()
{
m_fd = inotify_init();
if (m_fd == -1)
throw InotifyException(std::string(__PRETTY_FUNCTION__) + ": inotify init failed", errno, NULL);
m_fd = inotify_init();
}
Inotify::~Inotify()
198,31 → 186,31
}
}
 
void Inotify::Add(InotifyWatch* pWatch) throw (InotifyException)
bool Inotify::Add(InotifyWatch* pWatch)
{
if (m_fd == -1)
throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this);
return false;
pWatch->m_wd = inotify_add_watch(m_fd, pWatch->GetPath().c_str(), pWatch->GetMask());
 
if (pWatch->m_wd == -1)
throw InotifyException(IN_EXC_MSG("adding watch failed"), errno, this);
 
m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch));
pWatch->m_pInotify = this;
if (pWatch->m_wd != -1) {
m_watches.insert(IN_WATCH_MAP::value_type(pWatch->m_wd, pWatch));
pWatch->m_pInotify = this;
return true;
}
return false;
}
 
void Inotify::Remove(InotifyWatch* pWatch) throw (InotifyException)
void Inotify::Remove(InotifyWatch* pWatch)
{
if (m_fd == -1)
throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this);
return;
if (inotify_rm_watch(m_fd, pWatch->GetMask()) == -1)
throw InotifyException(IN_EXC_MSG("removing watch failed"), errno, this);
m_watches.erase(pWatch->m_wd);
pWatch->m_wd = -1;
pWatch->m_pInotify = NULL;
if (inotify_rm_watch(m_fd, pWatch->GetMask()) != -1) {
m_watches.erase(pWatch->m_wd);
pWatch->m_wd = -1;
pWatch->m_pInotify = NULL;
}
}
 
void Inotify::RemoveAll()
239,7 → 227,7
m_watches.clear();
}
 
void Inotify::WaitForEvents(bool fNoIntr) throw (InotifyException)
bool Inotify::WaitForEvents(bool fNoIntr)
{
ssize_t len = 0;
247,19 → 235,19
len = read(m_fd, m_buf, INOTIFY_BUFLEN);
} while (fNoIntr && len == -1 && errno == EINTR);
if (len < 0)
throw InotifyException(IN_EXC_MSG("reading events failed"), errno, this);
if (len <= 0) {
return false;
}
ssize_t i = 0;
while (i < len) {
struct inotify_event* pEvt = (struct inotify_event*) &m_buf[i];
InotifyWatch* pW = FindWatch(pEvt->wd);
if (pW != NULL && pW->IsEnabled()) {
InotifyEvent evt(pEvt, pW);
m_events.push_back(evt);
}
i += INOTIFY_EVENT_SIZE + (ssize_t) pEvt->len;
InotifyWatch* pW = FindWatch(((struct inotify_event *) &m_buf[i])->wd);
InotifyEvent evt((struct inotify_event *) &m_buf[i], pW);
m_events.push_back(evt);
i += INOTIFY_EVENT_SIZE + (int) evt.GetLength();
}
return true;
}
int Inotify::GetEventCount()
267,27 → 255,22
return m_events.size();
}
bool Inotify::GetEvent(InotifyEvent* pEvt) throw (InotifyException)
bool Inotify::GetEvent(InotifyEvent* pEvt)
{
bool b = PeekEvent(pEvt);
bool b = PeekEvent(pEvt);
if (b)
m_events.pop_front();
return b;
}
bool Inotify::PeekEvent(InotifyEvent* pEvt) throw (InotifyException)
bool Inotify::PeekEvent(InotifyEvent* pEvt)
{
if (pEvt == NULL)
throw InotifyException(IN_EXC_MSG("null pointer to event"), EINVAL, this);
if (pEvt == NULL || m_events.empty())
return false;
*pEvt = m_events.front();
if (!m_events.empty()) {
*pEvt = m_events.front();
return true;
}
return false;
return true;
}
 
InotifyWatch* Inotify::FindWatch(int iDescriptor)
299,23 → 282,3
return (*it).second;
}
void Inotify::SetNonBlock(bool fNonBlock) throw (InotifyException)
{
if (m_fd == -1)
throw InotifyException(IN_EXC_MSG("invalid file descriptor"), EBUSY, this);
int res = fcntl(m_fd, F_GETFL);
if (res == -1)
throw InotifyException(IN_EXC_MSG("cannot get inotify flags"), errno, this);
if (fNonBlock) {
res |= O_NONBLOCK;
}
else {
res &= ~O_NONBLOCK;
}
if (fcntl(m_fd, F_SETFL, res) == -1)
throw InotifyException(IN_EXC_MSG("cannot set inotify flags"), errno, this);
}
 
/inotify-cxx/trunk/CHANGELOG
1,13 → 1,3
0.3.0 2006-10-03
* all errors now handled using exceptions (InotifyException)
* InotifyEvent no longer use struct inotity_event as its
internal data structure
* removed InotifyEvent::GetData() - internal data changed
* removed Inotify::IsReady() - no longer necessary
* added Inotify::GetDescriptor() - returns inotify file descriptor
* added Inotify::SetNonBlock() - switches nonblocking mode on/off
* some code cleanups
 
0.2.0 2006-09-15
* InotifyEvent now contains a pointer to the source InotifyWatch
* fixed: InotifyEvent::IsType() - it now handles the mask correctly
/inotify-cxx/trunk/inotify-cxx.h
40,72 → 40,12
/// Event buffer length
#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
 
/// Helper macro for creating exception messages.
/**
* It prepends the message by the function name.
*/
#define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
 
 
 
// forward declaration
class InotifyWatch;
class Inotify;
 
 
/// Class for inotify exceptions
class InotifyException
{
public:
/// Constructor
/**
* \param[in] rMsg message
* \param[in] iErr error number (see errno.h)
* \param[in] pSrc source
*/
InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
: m_msg(rMsg),
m_err(iErr)
{
m_pSrc = pSrc;
}
/// Returns the exception message.
/**
* \return message
*/
inline const std::string& GetMessage() const
{
return m_msg;
}
/// Returns the exception error number.
/**
* If not applicable this value is 0 (zero).
*
* \return error number (standardized; see errno.h)
*/
inline int GetErrorNumber() const
{
return m_err;
}
/// Returns the exception source.
/**
* \return source
*/
inline void* GetSource() const
{
return m_pSrc;
}
 
protected:
std::string m_msg; ///< message
int m_err; ///< error number
mutable void* m_pSrc; ///< source
};
 
 
/// inotify event class
/**
* It holds all information about inotify event and provides
119,9 → 59,9
* Creates a plain event.
*/
InotifyEvent()
: m_uMask(0),
m_uCookie(0)
{
memset(&m_evt, 0, sizeof(m_evt));
m_evt.wd = (int32_t) -1;
m_pWatch = NULL;
}
134,17 → 74,16
* \param[in] pWatch inotify watch
*/
InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
: m_uMask(0),
m_uCookie(0)
{
if (pEvt != NULL) {
m_uMask = (uint32_t) pEvt->mask;
m_uCookie = (uint32_t) pEvt->cookie;
memcpy(&m_evt, pEvt, sizeof(m_evt));
if (pEvt->name != NULL)
m_name = pEvt->name;
m_pWatch = pWatch;
}
else {
memset(&m_evt, 0, sizeof(m_evt));
m_evt.wd = (int32_t) -1;
m_pWatch = NULL;
}
}
158,7 → 97,10
*
* \sa InotifyWatch::GetDescriptor()
*/
int32_t GetDescriptor() const;
inline int32_t GetDescriptor() const
{
return (int32_t) m_evt.wd;
}
/// Returns the event mask.
/**
168,7 → 110,7
*/
inline uint32_t GetMask() const
{
return m_uMask;
return (uint32_t) m_evt.mask;
}
/// Checks a value for the event type.
189,7 → 131,7
*/
inline bool IsType(uint32_t uType) const
{
return IsType(m_uMask, uType);
return IsType((uint32_t) m_evt.mask, uType);
}
/// Returns the event cookie.
198,7 → 140,7
*/
inline uint32_t GetCookie() const
{
return m_uCookie;
return (uint32_t) m_evt.cookie;
}
/// Returns the event name length.
207,7 → 149,7
*/
inline uint32_t GetLength() const
{
return (uint32_t) m_name.length();
return (uint32_t) m_evt.len;
}
/// Returns the event name.
237,6 → 179,27
return m_pWatch;
}
/// Returns the event raw data.
/**
* For NULL pointer it does nothing.
*
* \param[in,out] pEvt event data
*/
inline void GetData(struct inotify_event* pEvt)
{
if (pEvt != NULL)
memcpy(pEvt, &m_evt, sizeof(m_evt));
}
/// Returns the event raw data.
/**
* \param[in,out] rEvt event data
*/
inline void GetData(struct inotify_event& rEvt)
{
memcpy(&rEvt, &m_evt, sizeof(m_evt));
}
/// Finds the appropriate mask for a name.
/**
* \param[in] rName mask name
258,9 → 221,8
void DumpTypes(std::string& rStr) const;
private:
uint32_t m_uMask; ///< mask
uint32_t m_uCookie; ///< cookie
std::string m_name; ///< name
struct inotify_event m_evt; ///< event structure
std::string m_name; ///< event name
InotifyWatch* m_pWatch; ///< source watch
};
 
277,15 → 239,12
*
* \param[in] rPath watched file path
* \param[in] uMask mask for events
* \param[in] fEnabled events enabled yes/no
*/
InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
: m_path(rPath),
m_uMask(uMask),
m_wd((int32_t) -1),
m_fEnabled(fEnabled)
InotifyWatch(const std::string& rPath, int32_t uMask)
{
m_path = rPath;
m_uMask = uMask;
m_wd = (int32_t) -1;
}
/// Destructor.
327,16 → 286,6
return m_pInotify;
}
inline void SetEnabled(bool fEnabled)
{
m_fEnabled = fEnabled;
}
inline bool IsEnabled() const
{
return m_fEnabled;
}
private:
friend class Inotify;
 
344,7 → 293,6
uint32_t m_uMask; ///< event mask
int32_t m_wd; ///< watch descriptor
Inotify* m_pInotify; ///< inotify object
bool m_fEnabled; ///< events enabled yes/no
};
 
 
360,37 → 308,42
/**
* Creates and initializes an instance of inotify communication
* object (opens the inotify device).
*
* \throw InotifyException thrown if inotify isn't available
*/
Inotify() throw (InotifyException);
Inotify();
/// Destructor.
/**
* Calls Close() due to clean-up.
* Calls Close() due for clean-up.
*/
~Inotify();
/// Removes all watches and closes the inotify device.
void Close();
/// Checks whether the inotify is ready.
/**
* \return true = initialized properly, false = something failed
*/
inline bool IsReady() const
{
return m_fd != -1;
}
/// Adds a new watch.
/**
* \param[in] pWatch inotify watch
*
* \throw InotifyException thrown if adding failed
* \return true = success, false = failure
*/
void Add(InotifyWatch* pWatch) throw (InotifyException);
bool Add(InotifyWatch* pWatch);
/// Adds a new watch.
/**
* \param[in] rWatch inotify watch
*
* \throw InotifyException thrown if adding failed
* \return true = success, false = failure
*/
inline void Add(InotifyWatch& rWatch) throw (InotifyException)
inline bool Add(InotifyWatch& rWatch)
{
Add(&rWatch);
return Add(&rWatch);
}
/// Removes a watch.
398,10 → 351,8
* If the given watch is not present it does nothing.
*
* \param[in] pWatch inotify watch
*
* \throw InotifyException thrown if removing failed
*/
void Remove(InotifyWatch* pWatch) throw (InotifyException);
void Remove(InotifyWatch* pWatch);
/// Removes a watch.
/**
408,10 → 359,8
* If the given watch is not present it does nothing.
*
* \param[in] rWatch inotify watch
*
* \throw InotifyException thrown if removing failed
*/
inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
inline void Remove(InotifyWatch& rWatch)
{
Remove(&rWatch);
}
430,17 → 379,12
/// Waits for inotify events.
/**
* It waits until one or more events occur. When called
* in nonblocking mode it only retrieves occurred events
* to the internal queue and exits.
* It waits until one or more events occur.
*
* \param[in] fNoIntr if true it re-calls the system call after a handled signal
*
* \throw InotifyException thrown if reading events failed
*
* \sa SetNonBlock()
* \return true = event(s) occurred, false = failure
*/
void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
bool WaitForEvents(bool fNoIntr = false);
/// Returns the count of received and queued events.
/**
457,10 → 401,9
* If the pointer is NULL it does nothing.
*
* \param[in,out] pEvt event object
*
* \throw InotifyException thrown if the provided pointer is NULL
* \return true = success, false = failure
*/
bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
bool GetEvent(InotifyEvent* pEvt);
/// Extracts a queued inotify event.
/**
467,10 → 410,9
* The extracted event is removed from the queue.
*
* \param[in,out] rEvt event object
*
* \throw InotifyException thrown only in very anomalous cases
* \return true = success, false = failure
*/
bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
bool GetEvent(InotifyEvent& rEvt)
{
return GetEvent(&rEvt);
}
481,10 → 423,9
* If the pointer is NULL it does nothing.
*
* \param[in,out] pEvt event object
*
* \throw InotifyException thrown if the provided pointer is NULL
* \return true = success, false = failure
*/
bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
bool PeekEvent(InotifyEvent* pEvt);
/// Extracts a queued inotify event (without removing).
/**
491,10 → 432,9
* The extracted event stays in the queue.
*
* \param[in,out] rEvt event object
*
* \throw InotifyException thrown only in very anomalous cases
* \return true = success, false = failure
*/
bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
bool PeekEvent(InotifyEvent& rEvt)
{
return PeekEvent(&rEvt);
}
506,35 → 446,7
* \param[in] iDescriptor watch descriptor
* \return found descriptor; NULL if no such watch exists
*/
InotifyWatch* FindWatch(int iDescriptor);
/// Returns the file descriptor.
/**
* The descriptor can be used in standard low-level file
* functions (poll(), select(), fcntl() etc.).
*
* \return valid file descriptor or -1 for inactive object
*
* \sa SetNonBlock()
*/
inline int GetDescriptor() const
{
return m_fd;
}
/// Enables/disables non-blocking mode.
/**
* Use this mode if you want to monitor the descriptor
* (acquired thru GetDescriptor()) in functions such as
* poll(), select() etc.
*
* \param[in] fNonBlock enable/disable non-blocking mode
*
* \throw InotifyException thrown if setting mode failed
*
* \sa GetDescriptor()
*/
void SetNonBlock(bool fNonBlock) throw (InotifyException);
InotifyWatch* FindWatch(int iDescriptor);
 
private:
int m_fd; ///< file descriptor