Use an event in lock_file_mutex() to test if the client is still
[pwmd.git] / src / cache.c
blob8979908d6c2b13b860188e473a08365e764bdc81
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006-2008 Ben Kibbey <bjk@luxsci.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <glib.h>
21 #include <string.h>
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include "status.h"
28 #include "cache.h"
29 #include "mem.h"
31 static gboolean valid_key(const guchar *key, gsize len)
33 gint b;
35 for (b = 0; b < len; b++) {
36 if (key[b])
37 return TRUE;
40 return FALSE;
43 gboolean cache_get_mutex(const guchar *md5filename, pth_mutex_t **result)
45 void *p;
46 glong len;
47 file_cache_t f;
49 for (p = key_cache, len = 0; len <= cache_size;) {
50 memcpy(&f, p, sizeof(file_cache_t));
52 if (f.used == TRUE) {
53 if (memcmp(&f.filename, md5filename, sizeof(f.filename)) == 0) {
54 *result = f.mutex;
55 memset(&f, 0, sizeof(file_cache_t));
56 return *result ? TRUE : FALSE;
60 p += sizeof(file_cache_t);
61 len += sizeof(file_cache_t);
63 if (len + sizeof(file_cache_t) > cache_size)
64 break;
67 memset(&f, 0, sizeof(file_cache_t));
68 return FALSE;
71 gint cache_file_count()
73 void *p;
74 gint n = 0;
75 glong len;
76 file_cache_t f;
78 for (p = key_cache, len = 0; len <= cache_size;) {
79 memcpy(&f, p, sizeof(file_cache_t));
81 if (f.used == TRUE && valid_key(f.key, sizeof(f.key)) == TRUE)
82 n++;
84 p += sizeof(file_cache_t);
85 len += sizeof(file_cache_t);
87 if (len + sizeof(file_cache_t) > cache_size)
88 break;
91 memset(&f, 0, sizeof(file_cache_t));
92 return n;
95 void cache_adjust_timer()
97 file_cache_t f;
98 void *p;
99 glong len;
101 for (p = key_cache, len = 0; len <= cache_size;) {
102 memcpy(&f, p, sizeof(file_cache_t));
104 if (f.used == TRUE && f.reset >= 0) {
105 if (f.timeout > 0)
106 f.timeout--;
108 if (f.timeout == 0) {
109 if (valid_key(f.key, sizeof(f.key)) == TRUE) {
110 memset(&f.key, 0, sizeof(f.key));
111 send_status_all(STATUS_CACHE);
114 f.timeout = -1;
117 memcpy(p, &f, sizeof(file_cache_t));
120 p += sizeof(file_cache_t);
121 len += sizeof(file_cache_t);
123 if (len + sizeof(file_cache_t) > cache_size)
124 break;
127 memset(&f, 0, sizeof(file_cache_t));
130 gboolean cache_add_file(const guchar *md5file, const guchar *shakey)
132 void *p;
133 file_cache_t f;
134 gint nfiles = cache_file_count();
135 glong len;
138 * Make sure there is enough secure memory.
140 if (!md5file || (nfiles + 1) * sizeof(file_cache_t) > cache_size)
141 return FALSE;
144 * Find the first available "slot".
146 for (p = key_cache, len = 0; len <= cache_size;) {
147 memcpy(&f, p, sizeof(file_cache_t));
149 if (f.used == FALSE) {
150 memset(&f, 0, sizeof(file_cache_t));
151 f.mutex = xmalloc(sizeof(pth_mutex_t));
153 if (!f.mutex)
154 return FALSE;
156 pth_mutex_init(f.mutex);
157 memcpy(&f.filename, md5file, sizeof(f.filename));
159 if (shakey)
160 memcpy(&f.key, shakey, sizeof(f.key));
162 f.used = TRUE;
163 f.reset = f.timeout = -2;
164 memcpy(p, &f, sizeof(file_cache_t));
165 memset(&f, 0, sizeof(file_cache_t));
166 return TRUE;
169 p += sizeof(file_cache_t);
170 len += sizeof(file_cache_t);
172 if (len + sizeof(file_cache_t) > cache_size)
173 break;
176 memset(&f, 0, sizeof(file_cache_t));
177 return FALSE;
180 static void reset_entry(file_cache_t *f)
182 pth_mutex_t *m = f->mutex;
184 if (!f->refcount && m) {
185 xfree(m);
186 memset(f, 0, sizeof(file_cache_t));
188 else
189 memset(f->key, 0, sizeof(f->key));
192 gboolean cache_clear(const guchar *md5filename, gint which)
194 void *p;
195 file_cache_t f;
196 glong len;
198 for (p = key_cache, len = 0; len <= cache_size;) {
199 memcpy(&f, p, sizeof(file_cache_t));
201 if (which == 2) {
202 reset_entry(&f);
203 memcpy(p, &f, sizeof(file_cache_t));
204 memset(&f, 0, sizeof(file_cache_t));
206 else if (f.used == TRUE && which == 1) {
207 if (memcmp(&f.filename, md5filename, sizeof(f.filename)) == 0) {
208 reset_entry(&f);
209 memcpy(p, &f, sizeof(file_cache_t));
211 if (f.reset)
212 send_status_all(STATUS_CACHE);
214 memset(&f, 0, sizeof(file_cache_t));
215 return TRUE;
219 p += sizeof(file_cache_t);
220 len += sizeof(file_cache_t);
222 if (len + sizeof(file_cache_t) > cache_size)
223 break;
226 memset(&f, 0, sizeof(file_cache_t));
228 if (which == 2) {
229 send_status_all(STATUS_CACHE);
230 return TRUE;
233 return FALSE;
236 gboolean cache_iscached(const guchar *md5filename)
238 void *p;
239 file_cache_t f;
240 glong len;
241 gboolean ret = FALSE;
243 for (p = key_cache, len = 0; len <= cache_size;) {
244 memcpy(&f, p, sizeof(file_cache_t));
246 if (f.used == TRUE) {
247 if (memcmp(&f.filename, md5filename, sizeof(f.filename)) == 0) {
248 ret = valid_key(f.key, sizeof(f.key));
249 memset(&f, 0, sizeof(file_cache_t));
250 return ret;
254 p += sizeof(file_cache_t);
255 len += sizeof(file_cache_t);
257 if (len + sizeof(file_cache_t) > cache_size)
258 break;
261 memset(&f, 0, sizeof(file_cache_t));
262 return FALSE;
265 gboolean cache_reset_timeout(const guchar *md5filename, glong timeout)
267 void *p;
268 file_cache_t f;
269 glong len;
270 glong t = -2;
272 if (!md5filename)
273 return FALSE;
275 for (p = key_cache, len = 0; len <= cache_size;) {
276 memcpy(&f, p, sizeof(file_cache_t));
278 if (memcmp((gchar *)f.filename, (gchar *)md5filename, sizeof(f.filename)) == 0) {
279 t = f.reset;
280 break;
283 p += sizeof(file_cache_t);
284 len += sizeof(file_cache_t);
286 if (len + sizeof(file_cache_t) > cache_size)
287 break;
290 memset(&f, 0, sizeof(file_cache_t));
292 if (t == -2)
293 return cache_set_timeout(md5filename, timeout);
295 return cache_set_timeout(md5filename, t);
298 gboolean cache_set_timeout(const guchar *md5filename, glong timeout)
300 void *p;
301 file_cache_t f;
302 glong len;
304 for (p = key_cache, len = 0; len <= cache_size;) {
305 memcpy(&f, p, sizeof(file_cache_t));
307 if (md5filename) {
308 if (memcmp((gchar *)f.filename, (gchar *)md5filename, sizeof(f.filename)) == 0) {
309 if (timeout == -2)
310 f.timeout = f.reset;
311 else
312 f.reset = f.timeout = timeout;
314 memcpy(p, &f, sizeof(file_cache_t));
315 memset(&f, 0, sizeof(file_cache_t));
316 return TRUE;
320 p += sizeof(file_cache_t);
321 len += sizeof(file_cache_t);
323 if (len + sizeof(file_cache_t) > cache_size)
324 break;
327 memset(&f, 0, sizeof(file_cache_t));
328 return (md5filename) ? FALSE : TRUE;
331 gboolean cache_update_key(const guchar *md5filename, const guchar *shakey)
333 void *p;
334 file_cache_t f;
335 glong len;
337 for (p = key_cache, len = 0; len <= cache_size;) {
338 memcpy(&f, p, sizeof(file_cache_t));
340 if (f.used == TRUE) {
341 if (memcmp((gchar *)f.filename, (gchar *)md5filename, sizeof(f.filename)) == 0) {
342 if (f.reset)
343 memcpy(&f.key, shakey, sizeof(f.key));
345 memcpy(p, &f, sizeof(file_cache_t));
346 memset(&f, 0, sizeof(file_cache_t));
347 return TRUE;
351 p += sizeof(file_cache_t);
352 len += sizeof(file_cache_t);
354 if (len + sizeof(file_cache_t) > cache_size)
355 break;
358 memset(&f, 0, sizeof(file_cache_t));
359 return cache_add_file(md5filename, shakey);
362 gboolean cache_get_key(const guchar *md5file, guchar *shakey)
364 void *p;
365 file_cache_t f;
366 glong len;
368 for (p = key_cache, len = 0; len <= cache_size;) {
369 memcpy(&f, p, sizeof(file_cache_t));
372 * The slot may be used but not yet contain a key.
374 if (f.used == TRUE) {
375 if (memcmp(&f.filename, md5file, sizeof(f.filename)) == 0) {
376 if (valid_key(f.key, sizeof(f.key)) == FALSE)
377 goto fail;
379 memcpy(shakey, &f.key, sizeof(f.key));
380 memset(&f, 0, sizeof(file_cache_t));
381 return TRUE;
385 p += sizeof(file_cache_t);
386 len += sizeof(file_cache_t);
388 if (len + sizeof(file_cache_t) > cache_size)
389 break;
392 fail:
393 memset(&f, 0, sizeof(file_cache_t));
394 return FALSE;
397 gboolean cache_has_file(const guchar *md5file)
399 void *p;
400 file_cache_t f;
401 glong len;
403 for (p = key_cache, len = 0; len <= cache_size;) {
404 memcpy(&f, p, sizeof(file_cache_t));
406 if (memcmp(&f.filename, md5file, sizeof(f.filename)) == 0) {
407 memset(&f, 0, sizeof(file_cache_t));
408 return TRUE;
411 p += sizeof(file_cache_t);
412 len += sizeof(file_cache_t);
414 if (len + sizeof(file_cache_t) > cache_size)
415 break;
418 memset(&f, 0, sizeof(file_cache_t));
419 return FALSE;
422 gboolean cache_decr_refcount(const guchar *md5file)
424 void *p;
425 file_cache_t f;
426 glong len;
428 for (p = key_cache, len = 0; len <= cache_size;) {
429 memcpy(&f, p, sizeof(file_cache_t));
431 if (f.used == TRUE) {
432 if (memcmp(&f.filename, md5file, sizeof(f.filename)) == 0) {
433 f.refcount--;
435 if (f.refcount < 0)
436 f.refcount = 0;
438 memcpy(p, &f, sizeof(file_cache_t));
439 memset(&f, 0, sizeof(file_cache_t));
440 return TRUE;
444 p += sizeof(file_cache_t);
445 len += sizeof(file_cache_t);
447 if (len + sizeof(file_cache_t) > cache_size)
448 break;
451 memset(&f, 0, sizeof(file_cache_t));
452 return FALSE;
455 gboolean cache_incr_refcount(const guchar *md5file)
457 void *p;
458 file_cache_t f;
459 glong len;
461 for (p = key_cache, len = 0; len <= cache_size;) {
462 memcpy(&f, p, sizeof(file_cache_t));
464 if (f.used == TRUE) {
465 if (memcmp(&f.filename, md5file, sizeof(f.filename)) == 0) {
466 f.refcount++;
467 memcpy(p, &f, sizeof(file_cache_t));
468 memset(&f, 0, sizeof(file_cache_t));
469 return TRUE;
473 p += sizeof(file_cache_t);
474 len += sizeof(file_cache_t);
476 if (len + sizeof(file_cache_t) > cache_size)
477 break;
480 memset(&f, 0, sizeof(file_cache_t));
481 return FALSE;