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 void uuidcache_dump(void) {
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_debug, logtype_default,
63 "namecache{%d}: name:%s, uuid:%s, type%s: %s, cached: %s",
66 uuid_bin2string(entry->uuid),
67 (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
68 uuidtype[entry->type & UUIDTYPESTR_MASK],
70 } while ((entry = entry->next) != NULL);
74 for ( i=0; i<256; i++) {
75 if ((entry = uuidcache[i]) != NULL) {
78 tmp = localtime(&entry->creationtime);
81 if (strftime(timestr, 200, "%c", tmp) == 0)
83 LOG(log_debug, logtype_default,
84 "uuidcache{%d}: uuid:%s, name:%s, type%s: %s, cached: %s",
86 uuid_bin2string(entry->uuid),
88 (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
89 uuidtype[entry->type & UUIDTYPESTR_MASK],
91 } while ((entry = entry->next) != NULL);
96 /* hash string it into unsigned char */
97 static unsigned char hashstring(unsigned char *str) {
98 unsigned long hash = 5381;
101 while ((c = *str++) != 0)
102 hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
104 index = 85 ^ (hash & 0xff);
105 while ((hash = hash >> 8) != 0)
106 index ^= (hash & 0xff);
111 /* hash atalk_uuid_t into unsigned char */
112 static unsigned char hashuuid(uuidp_t uuid) {
113 unsigned char index = 83;
116 for (i=0; i<16; i++) {
123 /********************************************************
125 ********************************************************/
127 int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid _U_) {
130 unsigned char *uuid = NULL;
131 cacheduser_t *cacheduser = NULL;
134 /* allocate mem and copy values */
135 name = malloc(strlen(inname)+1);
137 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
142 uuid = malloc(UUID_BINSIZE);
144 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
149 cacheduser = malloc(sizeof(cacheduser_t));
151 LOG(log_error, logtype_default, "add_cachebyname: mallor error");
156 strcpy(name, inname);
157 memcpy(uuid, inuuid, UUID_BINSIZE);
159 /* fill in the cacheduser */
160 cacheduser->name = name;
161 cacheduser->uuid = uuid;
162 cacheduser->type = type;
163 cacheduser->creationtime = time(NULL);
164 cacheduser->prev = NULL;
165 cacheduser->next = NULL;
168 hash = hashstring((unsigned char *)name);
170 /* insert cache entry into cache array at head of queue */
171 if (namecache[hash] == NULL) {
172 /* this queue is empty */
173 namecache[hash] = cacheduser;
175 cacheduser->next = namecache[hash];
176 namecache[hash]->prev = cacheduser;
177 namecache[hash] = cacheduser;
194 * Search cache by name and uuid type
196 * @args name (r) name to search
197 * @args type (rw) type (user or group) of name, returns found type here which might
198 * mark it as a negative entry
199 * @args uuid (w) found uuid is returned here
200 * @returns 0 on sucess, entry found
203 int search_cachebyname( const char *name, uuidtype_t *type, unsigned char *uuid) {
209 hash = hashstring((unsigned char *)name);
211 if (namecache[hash] == NULL)
214 entry = namecache[hash];
216 ret = strcmp(entry->name, name);
217 if (ret == 0 && *type == (entry->type & UUIDTYPESTR_MASK)) {
218 /* found, now check if expired */
220 if ((tim - entry->creationtime) > CACHESECONDS) {
221 LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\"%s\"", entry->name);
224 /* 2nd to last in queue */
225 entry->prev->next = entry->next;
227 /* not the last element */
228 entry->next->prev = entry->prev;
231 if ((namecache[hash] = entry->next) != NULL)
232 namecache[hash]->prev = NULL;
239 memcpy(uuid, entry->uuid, UUID_BINSIZE);
251 * Caller must free allocated name
253 int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
259 hash = hashuuid(uuidp);
261 if (! uuidcache[hash])
264 entry = uuidcache[hash];
266 ret = memcmp(entry->uuid, uuidp, UUID_BINSIZE);
269 if ((tim - entry->creationtime) > CACHESECONDS) {
270 LOG(log_debug, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash);
272 /* 2nd to last in queue */
273 entry->prev->next = entry->next;
275 /* not the last element */
276 entry->next->prev = entry->prev;
279 if ((uuidcache[hash] = entry->next) != NULL)
280 uuidcache[hash]->prev = NULL;
287 *name = malloc(strlen(entry->name)+1);
288 strcpy(*name, entry->name);
299 int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid _U_) {
302 unsigned char *uuid = NULL;
303 cacheduser_t *cacheduser = NULL;
307 /* allocate mem and copy values */
308 name = malloc(strlen(inname)+1);
310 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
315 uuid = malloc(UUID_BINSIZE);
317 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
322 cacheduser = malloc(sizeof(cacheduser_t));
324 LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
329 strcpy(name, inname);
330 memcpy(uuid, inuuid, UUID_BINSIZE);
332 /* fill in the cacheduser */
333 cacheduser->name = name;
334 cacheduser->type = type;
335 cacheduser->uuid = uuid;
336 cacheduser->creationtime = time(NULL);
337 cacheduser->prev = NULL;
338 cacheduser->next = NULL;
341 hash = hashuuid(uuid);
343 /* insert cache entry into cache array at head of queue */
344 if (uuidcache[hash] == NULL) {
345 /* this queue is empty */
346 uuidcache[hash] = cacheduser;
348 cacheduser->next = uuidcache[hash];
349 uuidcache[hash]->prev = cacheduser;
350 uuidcache[hash] = cacheduser;