CGR Localization
 All Classes Namespaces Files Functions Variables Macros Pages
watch_files.cpp
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 
4 #include <fcntl.h>
5 #include <stdio.h>
6 
7 #include "watch_files.h"
8 
9 
10 static const bool Debug = false;
11 
12 /*
13  [ References ]
14 
15  Inofity Documentation and FAQ
16  http://inotify.aiken.cz/?section=inotify&page=doc&lang=en
17  http://inotify.aiken.cz/?section=inotify&page=faq&lang=en
18 */
19 
20 //====================================================================//
21 
22 time_t FileModTime(const char *filename)
23 {
24  struct stat st;
25  st.st_mtime = 0;
26  stat(filename,&st);
27  return(st.st_mtime);
28 }
29 
30 void SetNonBlocking(int fd)
31 {
32  int flags = fcntl(fd, F_GETFL, 0);
33  if(flags < 0) flags = 0;
34  fcntl(fd, F_SETFL, flags|O_NONBLOCK);
35 }
36 
37 //====================================================================//
38 
39 time_t ActiveFile::getFileModTime()
40 {
41  return(FileModTime(name()));
42 }
43 
44 //====================================================================//
45 
46 bool WatchFiles::init()
47 {
48  reset();
49 
50  inotify_fd = inotify_init();
51  if(inotify_fd < 0) return(false);
52  SetNonBlocking(inotify_fd);
53 
54  return(true);
55 }
56 
57 void WatchFiles::reset()
58 {
59  if(Debug){
60  printf("WatchFiles: reset (num=%d)\n",num_watches);
61  }
62 
63  if(isInited()){
64  close(inotify_fd);
65  inotify_fd = -1;
66  }
67  events.clear();
68  num_watches=0;
69 }
70 
71 bool WatchFiles::addWatch(Watch &w,const char *filename)
72 {
73  // initialize if needed
74  if(!isInited() && !init()) return(false);
75 
76  // remove existing watch if present
77  if(w.parent) removeWatch(w);
78 
79  // add watch for file
80  w.wd = inotify_add_watch(inotify_fd, filename, ModEvents);
81  if(w.wd < 0) return(false);
82  w.parent = this;
83  num_watches++;
84 
85  if(Debug){
86  printf("WatchFiles: watching \"%s\" (wd=%d)\n",
87  filename,w.wd);
88  }
89 
90  return(true);
91 }
92 
93 bool WatchFiles::removeWatch(Watch &w)
94 {
95  if(w.parent != this) return(false);
96 
97  if(Debug){
98  printf("WatchFiles: removing wd=%d\n",w.wd);
99  }
100 
101  int ret = inotify_rm_watch(inotify_fd, w.wd);
102  w.parent = NULL;
103  w.wd = -1;
104  if(ret == 0) num_watches--;
105 
106  return(ret == 0);
107 }
108 
109 uint32_t WatchFiles::calcEventMask(Watch &w)
110 {
111  uint32_t mask = 0;
112  for(unsigned i=0; i<events.size(); i++){
113  if(events[i].wd == w.wd) mask |= events[i].mask;
114  }
115  return(mask);
116 }
117 
118 int WatchFiles::getEvents()
119 {
120  static const int BufSize = 512;
121  char buf[BufSize];
122 
123  while(true){
124  // get a buffer of events
125  int nr = read(inotify_fd,buf,BufSize);
126  if(Debug){
127  printf("Read inotify: %d\n",nr);
128  }
129  if(nr < (int)sizeof(inotify_event)) break;
130 
131  // add them to our interal event queue
132  int i=0;
133  while(i < nr){
134  const inotify_event &e = *(inotify_event*)(buf+i);
135  events.push_back(e);
136  i += sizeof(inotify_event) + e.len;
137 
138  if(Debug){
139  printf("WatchFiles: wd=%d ev=0x%X",e.mask,e.wd);
140  if(e.len) printf(" len=%d name=\"%s\"",e.len,e.name);
141  printf("\n");
142  }
143  }
144  }
145 
146  return(events.size());
147 }