]> arthur.barton.de Git - netatalk.git/blob - libatalk/acl/cache.c
Untabify and reindent
[netatalk.git] / libatalk / acl / cache.c
1 /*
2   $Id: cache.c,v 1.2 2009-11-28 12:30:12 franklahm Exp $
3   Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
4
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.
9
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.
14 */
15
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif /* HAVE_CONFIG_H */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 #include <errno.h>
25
26 #include <atalk/logger.h>
27 #include <atalk/afp.h>
28 #include <atalk/uuid.h>
29 #include "cache.h"
30
31 typedef struct cacheduser {
32     unsigned long uid;      /* for future use */
33     uuidtype_t type;
34     uuidp_t uuid;
35     char *name;
36     time_t creationtime;
37     struct cacheduser *prev;
38     struct cacheduser *next;
39 } cacheduser_t;
40
41 cacheduser_t *namecache[256];   /* indexed by hash of name */
42 cacheduser_t *uuidcache[256];   /* indexed by hash of uuid */
43
44 /********************************************************
45  * helper function
46  ********************************************************/
47
48 static int dumpcache() {
49     int i;
50     int ret = 0;
51     cacheduser_t *entry;
52     char *uuidstring = NULL;
53     char timestr[200];
54     struct tm *tmp = NULL;
55
56     for ( i=0 ; i<256; i++) {
57         if ((entry = namecache[i]) != NULL) {
58             do {
59                 uuid_bin2string(entry->uuid, &uuidstring);
60                 tmp = localtime(&entry->creationtime);
61                 if (tmp == NULL)
62                     continue;
63                 if (strftime(timestr, 200, "%c", tmp) == 0)
64                     continue;
65                 LOG(log_debug9, logtype_default, "namecache{%d}]: name:%s, uuid:%s, cached: %s", i, entry->name, uuidstring, timestr);
66                 free(uuidstring);
67             } while ((entry = entry->next) != NULL);
68         }
69     }
70
71     for ( i=0; i<256; i++) {
72         if ((entry = uuidcache[i]) != NULL) {
73             do {
74                 uuid_bin2string(entry->uuid, &uuidstring);
75                 tmp = localtime(&entry->creationtime);
76                 if (tmp == NULL)
77                     continue;
78                 if (strftime(timestr, 200, "%c", tmp) == 0)
79                     continue;
80                 LOG(log_debug9, logtype_default, "uuidcache{%d}: uuid:%s, name:%s, type:%d, cached: %s", i, uuidstring, entry->name, entry->type,timestr);
81                 free(uuidstring);
82             } while ((entry = entry->next) != NULL);
83         }
84     }
85
86     return ret;
87 }
88
89 /* hash string it into unsigned char */
90 static unsigned char hashstring(unsigned char *str) {
91     unsigned long hash = 5381;
92     unsigned char index;
93     int c;
94     while ((c = *str++) != 0)
95         hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
96
97     index = 85 ^ (hash & 0xff);
98     while ((hash = hash >> 8) != 0)
99         index ^= (hash & 0xff);
100
101     return index;
102 }
103
104 /* hash uuid_t into unsigned char */
105 static unsigned char hashuuid(uuidp_t uuid) {
106     unsigned char index = 83;
107     int i;
108
109     for (i=0; i<16; i++) {
110         index ^= uuid[i];
111         index += uuid[i];
112     }
113     return index;
114 }
115
116 /********************************************************
117  * Interface
118  ********************************************************/
119
120 int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid _U_) {
121     int ret = 0;
122     char *name = NULL;
123     uuidp_t uuid;
124     cacheduser_t *cacheduser = NULL;
125     cacheduser_t *entry;
126     unsigned char hash;
127
128     /* allocate mem and copy values */
129     name = malloc(strlen(inname)+1);
130     if (!name) {
131         LOG(log_error, logtype_default, "add_cachebyname: mallor error");
132         ret = -1;
133         goto cleanup;
134     }
135
136     uuid = malloc(UUID_BINSIZE);
137     if (!uuid) {
138         LOG(log_error, logtype_default, "add_cachebyname: mallor error");
139         ret = -1;
140         goto cleanup;
141     }
142
143     cacheduser = malloc(sizeof(cacheduser_t));
144     if (!cacheduser) {
145         LOG(log_error, logtype_default, "add_cachebyname: mallor error");
146         ret = -1;
147         goto cleanup;
148     }
149
150     strcpy(name, inname);
151     memcpy(uuid, inuuid, UUID_BINSIZE);
152
153     /* fill in the cacheduser */
154     cacheduser->name = name;
155     cacheduser->uuid = uuid;
156     cacheduser->type = type;
157     cacheduser->creationtime = time(NULL);
158     cacheduser->prev = NULL;
159     cacheduser->next = NULL;
160
161     /* get hash */
162     hash = hashstring((unsigned char *)name);
163
164     /* insert cache entry into cache array */
165     if (namecache[hash] == NULL) { /* this queue is empty */
166         namecache[hash] = cacheduser;
167     } else {            /* queue is not empty, search end of queue*/
168         entry = namecache[hash];
169         while( entry->next != NULL)
170             entry = entry->next;
171         cacheduser->prev = entry;
172         entry->next = cacheduser;
173     }
174
175 cleanup:
176     if (ret != 0) {
177         if (name)
178             free(name);
179         if (uuid)
180             free(uuid);
181         if (cacheduser)
182             free(cacheduser);
183     }
184     return ret;
185 }
186
187 int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
188     int ret;
189     unsigned char hash;
190     cacheduser_t *entry;
191     time_t tim;
192
193     hash = hashstring((unsigned char *)name);
194
195     if (! namecache[hash])
196         return -1;
197
198     entry = namecache[hash];
199     while (entry) {
200         ret = strcmp(entry->name, name);
201         if (ret == 0 && type == entry->type) {
202             /* found, now check if expired */
203             tim = time(NULL);
204             if ((tim - entry->creationtime) > CACHESECONDS) {
205                 /* remove item */
206                 if (entry->prev) /* 2nd to last in queue */
207                     entry->prev->next = entry->next;
208                 else        /* queue head */
209                     namecache[hash] = entry->next;
210                 free(entry->name);
211                 free(entry->uuid);
212                 free(entry);
213                 return -1;
214             } else {
215                 memcpy(uuid, entry->uuid, UUID_BINSIZE);
216                 return 0;
217             }
218         }
219         entry = entry->next;
220     }
221     return -1;
222 }
223
224 int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
225     int ret;
226     unsigned char hash;
227     cacheduser_t *entry;
228     time_t tim;
229
230     hash = hashuuid(uuidp);
231
232     if (! uuidcache[hash])
233         return -1;
234
235     entry = uuidcache[hash];
236     while (entry) {
237         ret = memcmp(entry->uuid, uuidp, UUID_BINSIZE);
238         if (ret == 0) {
239             tim = time(NULL);
240             if ((tim - entry->creationtime) > CACHESECONDS) {
241                 LOG(log_info, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash);
242                 if (entry->prev)
243                     entry->prev->next = entry->next;
244                 else
245                     uuidcache[hash] = entry->next;
246                 free(entry->name);
247                 free(entry->uuid);
248                 free(entry);
249                 return -1;
250             } else {
251                 *name = malloc(strlen(entry->name)+1);
252                 strcpy(*name, entry->name);
253                 *type = entry->type;
254                 return 0;
255             }
256         }
257         entry = entry->next;
258     }
259
260     return -1;
261 }
262
263 int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid _U_) {
264     int ret = 0;
265     char *name = NULL;
266     uuidp_t uuid;
267     cacheduser_t *cacheduser = NULL;
268     cacheduser_t *entry;
269     unsigned char hash;
270
271     /* allocate mem and copy values */
272     name = malloc(strlen(inname)+1);
273     if (!name) {
274         LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
275         ret = -1;
276         goto cleanup;
277     }
278
279     uuid = malloc(UUID_BINSIZE);
280     if (!uuid) {
281         LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
282         ret = -1;
283         goto cleanup;
284     }
285
286     cacheduser = malloc(sizeof(cacheduser_t));
287     if (!cacheduser) {
288         LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
289         ret = -1;
290         goto cleanup;
291     }
292
293     strcpy(name, inname);
294     memcpy(uuid, inuuid, UUID_BINSIZE);
295
296     /* fill in the cacheduser */
297     cacheduser->name = name;
298     cacheduser->type = type;
299     cacheduser->uuid = uuid;
300     cacheduser->creationtime = time(NULL);
301     cacheduser->prev = NULL;
302     cacheduser->next = NULL;
303
304     /* get hash */
305     hash = hashuuid(uuid);
306
307     /* insert cache entry into cache array */
308     if (uuidcache[hash] == NULL) { /* this queue is empty */
309         uuidcache[hash] = cacheduser;
310     } else {            /* queue is not empty, search end of queue*/
311         entry = uuidcache[hash];
312         while( entry->next != NULL)
313             entry = entry->next;
314         cacheduser->prev = entry;
315         entry->next = cacheduser;
316     }
317
318 cleanup:
319     if (ret != 0) {
320         if (name)
321             free(name);
322         if (uuid)
323             free(uuid);
324         if (cacheduser)
325             free(cacheduser);
326     }
327     return ret;
328 }