2 Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
17 #endif /* HAVE_CONFIG_H */
25 #include <atalk/logger.h>
26 #include <atalk/afp.h>
27 #include <atalk/uuid.h>
30 typedef struct cacheduser {
31 unsigned long uid; /* for future use */
36 struct cacheduser *prev;
37 struct cacheduser *next;
40 cacheduser_t *namecache[256]; /* indexed by hash of name */
41 cacheduser_t *uuidcache[256]; /* indexed by hash of uuid */
43 /********************************************************
45 ********************************************************/
47 static int dumpcache() {
52 struct tm *tmp = NULL;
54 for ( i=0 ; i<256; i++) {
55 if ((entry = namecache[i]) != NULL) {
57 tmp = localtime(&entry->creationtime);
60 if (strftime(timestr, 200, "%c", tmp) == 0)
62 LOG(log_debug9, logtype_default, "namecache{%d}: name:%s, uuid:%s, type: %s, cached: %s",
63 i, entry->name, uuid_bin2string(entry->uuid), uuidtype[entry->type], timestr);
64 } while ((entry = entry->next) != NULL);
68 for ( i=0; i<256; i++) {
69 if ((entry = uuidcache[i]) != NULL) {
72 tmp = localtime(&entry->creationtime);
75 if (strftime(timestr, 200, "%c", tmp) == 0)
77 LOG(log_debug9, logtype_default, "uuidcache{%d}: uuid:%s, name:%s, type: %s, cached: %s",
78 i, uuid_bin2string(entry->uuid), entry->name, uuidtype[entry->type], timestr);
79 } while ((entry = entry->next) != NULL);
86 /* hash string it into unsigned char */
87 static unsigned char hashstring(unsigned char *str) {
88 unsigned long hash = 5381;
91 while ((c = *str++) != 0)
92 hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
94 index = 85 ^ (hash & 0xff);
95 while ((hash = hash >> 8) != 0)
96 index ^= (hash & 0xff);
101 /* hash atalk_uuid_t into unsigned char */
102 static unsigned char hashuuid(uuidp_t uuid) {
103 unsigned char index = 83;
106 for (i=0; i<16; i++) {
113 /********************************************************
115 ********************************************************/
117 int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid _U_) {
121 cacheduser_t *cacheduser = NULL;
128 /* allocate mem and copy values */
129 name = malloc(strlen(inname)+1);
131 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
136 uuid = malloc(UUID_BINSIZE);
138 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
143 cacheduser = malloc(sizeof(cacheduser_t));
145 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
150 strcpy(name, inname);
151 memcpy(uuid, inuuid, UUID_BINSIZE);
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;
162 hash = hashstring((unsigned char *)name);
164 /* insert cache entry into cache array at head of queue */
165 if (namecache[hash] == NULL) {
166 /* this queue is empty */
167 namecache[hash] = cacheduser;
169 cacheduser->next = namecache[hash];
170 namecache[hash]->prev = cacheduser;
171 namecache[hash] = cacheduser;
192 * Caller provides buffer uuid for result
194 int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
204 hash = hashstring((unsigned char *)name);
206 if (namecache[hash] == NULL)
209 entry = namecache[hash];
211 ret = strcmp(entry->name, name);
212 if (ret == 0 && type == entry->type) {
213 /* found, now check if expired */
215 if ((tim - entry->creationtime) > CACHESECONDS) {
216 LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\'%s\' in queue {%d}", entry->name, hash);
219 /* 2nd to last in queue */
220 entry->prev->next = entry->next;
222 /* not the last element */
223 entry->next->prev = entry->prev;
226 if ((namecache[hash] = entry->next) != NULL)
227 namecache[hash]->prev = NULL;
237 memcpy(uuid, entry->uuid, UUID_BINSIZE);
253 * Caller must free allocated name
255 int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
265 hash = hashuuid(uuidp);
267 if (! uuidcache[hash])
270 entry = uuidcache[hash];
272 ret = memcmp(entry->uuid, uuidp, UUID_BINSIZE);
275 if ((tim - entry->creationtime) > CACHESECONDS) {
276 LOG(log_debug, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash);
278 /* 2nd to last in queue */
279 entry->prev->next = entry->next;
281 /* not the last element */
282 entry->next->prev = entry->prev;
285 if ((uuidcache[hash] = entry->next) != NULL)
286 uuidcache[hash]->prev = NULL;
296 *name = malloc(strlen(entry->name)+1);
297 strcpy(*name, entry->name);
315 int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid _U_) {
319 cacheduser_t *cacheduser = NULL;
327 /* allocate mem and copy values */
328 name = malloc(strlen(inname)+1);
330 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
335 uuid = malloc(UUID_BINSIZE);
337 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
342 cacheduser = malloc(sizeof(cacheduser_t));
344 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
349 strcpy(name, inname);
350 memcpy(uuid, inuuid, UUID_BINSIZE);
352 /* fill in the cacheduser */
353 cacheduser->name = name;
354 cacheduser->type = type;
355 cacheduser->uuid = uuid;
356 cacheduser->creationtime = time(NULL);
357 cacheduser->prev = NULL;
358 cacheduser->next = NULL;
361 hash = hashuuid(uuid);
363 /* insert cache entry into cache array at head of queue */
364 if (uuidcache[hash] == NULL) {
365 /* this queue is empty */
366 uuidcache[hash] = cacheduser;
368 cacheduser->next = uuidcache[hash];
369 uuidcache[hash]->prev = cacheduser;
370 uuidcache[hash] = cacheduser;