Browse code

c4w: handle status report and force reload from sigui

aCaB authored on 2010/11/12 09:51:26
Showing 1 changed files
... ...
@@ -37,11 +37,15 @@
37 37
 HANDLE reload_event;
38 38
 volatile LONG reload_waiters = 0;
39 39
 
40
+HANDLE monitor_event;
41
+HANDLE monitor_hdl = NULL;
42
+
40 43
 HANDLE engine_mutex;
41 44
 /* protects the following items */
42 45
 struct cl_engine *engine = NULL;
43 46
 char dbdir[PATH_MAX];
44 47
 char tmpdir[PATH_MAX];
48
+FILETIME last_chk_time = {0, 0};
45 49
 /* end of protected items */
46 50
 
47 51
 typedef struct {
... ...
@@ -69,6 +73,68 @@ BOOL minimal_definitions = FALSE;
69 69
 cl_error_t prescan_cb(int fd, void *context);
70 70
 cl_error_t postscan_cb(int fd, int result, const char *virname, void *context);
71 71
 
72
+
73
+DWORD WINAPI monitor_thread(VOID *p) {
74
+    char watchme[PATH_MAX];
75
+    HANDLE harr[2], fff;
76
+
77
+    if(lock_engine()) {
78
+	logg("monitor_thread: failed to lock engine\n");
79
+	return 0;
80
+    }
81
+
82
+    snprintf(watchme, sizeof(watchme), "%s\\forcerld", dbdir);
83
+    watchme[sizeof(watchme)-1] = '\0';
84
+
85
+    harr[0] = monitor_event;
86
+    harr[1] = FindFirstChangeNotification(dbdir, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);
87
+
88
+    logg("monitor_thread: watching directory changes on %s\n", dbdir);
89
+
90
+    unlock_engine();
91
+
92
+    if(harr[1] == INVALID_HANDLE_VALUE) {
93
+	logg("monitor_thread: failed to monitor directory changes on %s\n", dbdir);
94
+	return 0;
95
+    }
96
+
97
+    while(1) {
98
+	WIN32_FIND_DATA wfd;
99
+	SYSTEMTIME st;
100
+
101
+	switch(WaitForMultipleObjects(2, harr, FALSE, INFINITE)) {
102
+	case WAIT_OBJECT_0:
103
+	    logg("monitor_thread: terminating upon request\n");
104
+	    FindCloseChangeNotification(fff);
105
+	    return 0;
106
+	case WAIT_OBJECT_0 + 1:
107
+	    break;
108
+	default:
109
+	    logg("monitor_thread: unexpected wait failure - %u\n", GetLastError());
110
+	    Sleep(1000);
111
+	    continue;
112
+	}
113
+	FindNextChangeNotification(fff);
114
+	if((fff = FindFirstFile(watchme, &wfd)) == INVALID_HANDLE_VALUE) {
115
+	    logg("monitor_thread: failed to find %s - %u\n", watchme, GetLastError());
116
+	    continue;
117
+	}
118
+	FindClose(fff);
119
+
120
+	GetSystemTime(&st);
121
+	SystemTimeToFileTime(&st, &wfd.ftCreationTime);
122
+	if(CompareFileTime(&wfd.ftLastWriteTime, &wfd.ftCreationTime) > 0)
123
+	    wfd.ftLastWriteTime = wfd.ftCreationTime;
124
+	if(CompareFileTime(&wfd.ftLastWriteTime, &last_chk_time) <= 0)
125
+	    continue;
126
+
127
+	logg("monitor_thread: reload requested!\n");
128
+	Scan_ReloadDatabase();
129
+	GetSystemTime(&st);
130
+	SystemTimeToFileTime(&st, &last_chk_time); /* FIXME: small race here */
131
+    }
132
+}
133
+
72 134
 static wchar_t *threat_type(const char *virname) {
73 135
     if(!virname)
74 136
 	return NULL;
... ...
@@ -169,7 +235,14 @@ BOOL interface_setup(void) {
169 169
 	CloseHandle(engine_mutex);
170 170
 	return FALSE;
171 171
     }
172
+    if(!(monitor_event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
173
+	CloseHandle(reload_event);
174
+	CloseHandle(engine_mutex);
175
+	return FALSE;
176
+    }
172 177
     if(!(instance_mutex = CreateMutex(NULL, FALSE, NULL))) {
178
+	CloseHandle(monitor_event);
179
+	CloseHandle(reload_event);
173 180
 	CloseHandle(engine_mutex);
174 181
 	return FALSE;
175 182
     }
... ...
@@ -182,11 +255,35 @@ static int sigload_callback(const char *type, const char *name, void *context) {
182 182
     return 0;
183 183
 }
184 184
 
185
+
186
+/* Must be called with engine_mutex locked ! */
187
+static void touch_last_update(void) {
188
+    char touchme[PATH_MAX];
189
+    HANDLE h;
190
+
191
+    snprintf(touchme, sizeof(touchme), "%s\\lastupd", dbdir);
192
+    touchme[sizeof(touchme)-1] = '\0';
193
+    if((h = CreateFile(touchme, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) {
194
+	DWORD d;
195
+	snprintf(touchme, sizeof(touchme), "w00t!");
196
+	touchme[sizeof(touchme)-1] = '\0';
197
+	if(WriteFile(h, touchme, strlen(touchme), &d, NULL)) {
198
+	    /* SetEndOfFile(h); */
199
+	    GetFileTime(h, NULL, NULL, &last_chk_time);
200
+	}
201
+	CloseHandle(h);
202
+    } else
203
+	logg("touch_lastcheck: failed to touch lastreload\n");
204
+}
205
+
206
+
185 207
 /* Must be called with engine_mutex locked ! */
186 208
 static int load_db(void) {
187
-    int ret;
188
-    size_t used, total;
189 209
     unsigned int signo = 0;
210
+    size_t used, total;
211
+    int ret;
212
+
213
+
190 214
     INFN();
191 215
 
192 216
     cl_engine_set_clcb_sigload(engine, sigload_callback, NULL);
... ...
@@ -203,10 +300,11 @@ static int load_db(void) {
203 203
     }
204 204
 
205 205
     logg("load_db: loaded %d signatures\n", signo);
206
-    if (!mpool_getstats(engine, &used, &total)) {
207
-	logg("load_db: memory %.3f MB / %.3f MB\n",
208
-	     used/(1024*1024.0), total/(1024*1024.0));
209
-    }
206
+    if (!mpool_getstats(engine, &used, &total))
207
+	logg("load_db: memory %.3f MB / %.3f MB\n", used/(1024*1024.0), total/(1024*1024.0));
208
+
209
+    touch_last_update();
210
+
210 211
     WIN();
211 212
 }
212 213
 
... ...
@@ -257,6 +355,11 @@ int CLAMAPI Scan_Initialize(const wchar_t *pEnginesFolder, const wchar_t *pTempR
257 257
     }
258 258
     ret = load_db();
259 259
     unlock_engine();
260
+
261
+    ResetEvent(monitor_event);
262
+    if(!(monitor_hdl = CreateThread(NULL, 0, monitor_thread, NULL, 0, NULL)))
263
+	logg("!Falied to start db monitoring thread\n");
264
+
260 265
     logg("Scan_Initialize: returning %d\n", ret);
261 266
     return ret;
262 267
 }
... ...
@@ -287,6 +390,15 @@ int CLAMAPI Scan_Uninitialize(void) {
287 287
     }
288 288
     unlock_instances();
289 289
     free_engine_and_unlock();
290
+
291
+    if(monitor_hdl) {
292
+	SetEvent(monitor_event);
293
+	if(WaitForSingleObject(monitor_hdl, 60000) != WAIT_OBJECT_0) {
294
+	    logg("Scan_Uninitialize: forcibly terminating monitor thread after 60 seconds\n");
295
+	    TerminateThread(monitor_hdl, 0);
296
+	}
297
+    }
298
+    monitor_hdl = NULL;
290 299
     WIN();
291 300
 }
292 301
 
... ...
@@ -825,10 +937,6 @@ CLAMAPI void Scan_ReloadDatabase(void) {
825 825
 		continue;
826 826
 	    }
827 827
 	    logg("Scan_ReloadDatabase: Now idle, acquiring engine lock\n");
828
-    	    if(lock_engine()) {
829
-		logg("!Scan_ReloadDatabase: failed to lock engine\n");
830
-		break;
831
-	    }
832 828
 	    if(lock_engine()) {
833 829
 		logg("!Scan_ReloadDatabase: failed to lock engine\n");
834 830
 		break;
... ...
@@ -861,7 +969,6 @@ CLAMAPI void Scan_ReloadDatabase(void) {
861 861
 
862 862
 	    // NEW STUFF //
863 863
 	    if(!(engine = cl_engine_new())) {
864
-		unlock_engine();
865 864
 		logg("!Scan_ReloadDatabase: Not enough memory for a new engine\n");
866 865
 		unlock_instances();
867 866
 		unlock_engine();