]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/acl/cache.c
Merge master
[netatalk.git] / libatalk / acl / cache.c
index e84076a31362529870bc6cc14a6a296093318133..ee4d3f2295494306d54ca28853181e77ea8d93bd 100644 (file)
@@ -1,17 +1,16 @@
 /*
-   $Id: cache.c,v 1.1 2009-02-02 11:55:01 franklahm Exp $
-   Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
- */
+  Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+*/
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #include "cache.h"
 
 typedef struct cacheduser {
-    unsigned long uid;         /* for future use */
+    unsigned long uid;      /* for future use */
     uuidtype_t type;
-    uuidp_t uuid;
+    unsigned char *uuid;
     char *name;
     time_t creationtime;
     struct cacheduser *prev;
     struct cacheduser *next;
 } cacheduser_t;
 
-cacheduser_t *namecache[256];  /* indexed by hash of name */
-cacheduser_t *uuidcache[256];  /* indexed by hash of uuid */
+cacheduser_t *namecache[256];   /* indexed by hash of name */
+cacheduser_t *uuidcache[256];   /* indexed by hash of uuid */
 
 /********************************************************
  * helper function
@@ -49,36 +48,34 @@ static int dumpcache() {
     int i;
     int ret = 0;
     cacheduser_t *entry;
-    char *uuidstring = NULL;
     char timestr[200];
     struct tm *tmp = NULL;
 
     for ( i=0 ; i<256; i++) {
-       if ((entry = namecache[i]) != NULL) {
-           do {
-               uuid_bin2string(entry->uuid, &uuidstring);
-               tmp = localtime(&entry->creationtime);
-               if (tmp == NULL)
-                   continue;
-               if (strftime(timestr, 200, "%c", tmp) == 0)
-                   continue;
-               LOG(log_debug9, logtype_default, "namecache{%d}]: name:%s, uuid:%s, cached: %s", i, entry->name, uuidstring, timestr);
-               free(uuidstring);
-           } while ((entry = entry->next) != NULL);
-       }
+        if ((entry = namecache[i]) != NULL) {
+            do {
+                tmp = localtime(&entry->creationtime);
+                if (tmp == NULL)
+                    continue;
+                if (strftime(timestr, 200, "%c", tmp) == 0)
+                    continue;
+                LOG(log_debug9, logtype_default, "namecache{%d}: name:%s, uuid:%s, type: %s, cached: %s",
+                    i, entry->name, uuid_bin2string(entry->uuid), uuidtype[entry->type], timestr);
+            } while ((entry = entry->next) != NULL);
+        }
     }
 
     for ( i=0; i<256; i++) {
         if ((entry = uuidcache[i]) != NULL) {
             do {
-                uuid_bin2string(entry->uuid, &uuidstring);
+
                 tmp = localtime(&entry->creationtime);
                 if (tmp == NULL)
                     continue;
                 if (strftime(timestr, 200, "%c", tmp) == 0)
                     continue;
-                LOG(log_debug9, logtype_default, "uuidcache{%d}: uuid:%s, name:%s, type:%d, cached: %s", i, uuidstring, entry->name, entry->type,timestr);
-               free(uuidstring);
+                LOG(log_debug9, logtype_default, "uuidcache{%d}: uuid:%s, name:%s, type: %s, cached: %s",
+                    i, uuid_bin2string(entry->uuid), entry->name, uuidtype[entry->type], timestr);
             } while ((entry = entry->next) != NULL);
         }
     }
@@ -92,59 +89,62 @@ static unsigned char hashstring(unsigned char *str) {
     unsigned char index;
     int c;
     while ((c = *str++) != 0)
-       hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
+        hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
 
     index = 85 ^ (hash & 0xff);
     while ((hash = hash >> 8) != 0)
-       index ^= (hash & 0xff);
-    
+        index ^= (hash & 0xff);
+
     return index;
 }
 
-/* hash uuid_t into unsigned char */
+/* hash atalk_uuid_t into unsigned char */
 static unsigned char hashuuid(uuidp_t uuid) {
     unsigned char index = 83;
     int i;
 
     for (i=0; i<16; i++) {
-       index ^= uuid[i];
-       index += uuid[i];
+        index ^= uuid[i];
+        index += uuid[i];
     }
     return index;
 }
 
-/******************************************************** 
+/********************************************************
  * Interface
  ********************************************************/
 
 int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid _U_) {
     int ret = 0;
     char *name = NULL;
-    uuidp_t uuid;
+    unsigned char *uuid = NULL;
     cacheduser_t *cacheduser = NULL;
-    cacheduser_t *entry;
     unsigned char hash;
 
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     /* allocate mem and copy values */
     name = malloc(strlen(inname)+1);
     if (!name) {
-       LOG(log_error, logtype_default, "add_cachebyname: mallor error");
-       ret = -1;
-       goto cleanup;
+        LOG(log_error, logtype_default, "add_cachebyname: mallor error");
+        ret = -1;
+        goto cleanup;
     }
-    
+
     uuid = malloc(UUID_BINSIZE);
     if (!uuid) {
-       LOG(log_error, logtype_default, "add_cachebyname: mallor error");
-       ret = -1;
-       goto cleanup;
+        LOG(log_error, logtype_default, "add_cachebyname: mallor error");
+        ret = -1;
+        goto cleanup;
     }
 
     cacheduser = malloc(sizeof(cacheduser_t));
     if (!cacheduser) {
-       LOG(log_error, logtype_default, "add_cachebyname: mallor error");
-       ret = -1;
-       goto cleanup;
+        LOG(log_error, logtype_default, "add_cachebyname: mallor error");
+        ret = -1;
+        goto cleanup;
     }
 
     strcpy(name, inname);
@@ -161,72 +161,107 @@ int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t
     /* get hash */
     hash = hashstring((unsigned char *)name);
 
-    /* insert cache entry into cache array */
-    if (namecache[hash] == NULL) { /* this queue is empty */
-       namecache[hash] = cacheduser;
-    } else {                   /* queue is not empty, search end of queue*/
-       entry = namecache[hash];
-       while( entry->next != NULL)
-           entry = entry->next;
-       cacheduser->prev = entry;
-       entry->next = cacheduser;
+    /* insert cache entry into cache array at head of queue */
+    if (namecache[hash] == NULL) {
+        /* this queue is empty */
+        namecache[hash] = cacheduser;
+    } else {
+        cacheduser->next = namecache[hash];
+        namecache[hash]->prev = cacheduser;
+        namecache[hash] = cacheduser;
     }
 
 cleanup:
     if (ret != 0) {
-       if (name)
-           free(name);
-       if (uuid)
-           free(uuid);
-       if (cacheduser)
-           free(cacheduser);
+        if (name)
+            free(name);
+        if (uuid)
+            free(uuid);
+        if (cacheduser)
+            free(cacheduser);
     }
+
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     return ret;
 }
 
-int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
+/* 
+ * Caller provides buffer uuid for result
+ */
+int search_cachebyname( const char *name, uuidtype_t type, unsigned char *uuid) {
     int ret;
     unsigned char hash;
     cacheduser_t *entry;
     time_t tim;
 
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     hash = hashstring((unsigned char *)name);
 
-    if (! namecache[hash])
-       return -1;
+    if (namecache[hash] == NULL)
+        return -1;
 
     entry = namecache[hash];
     while (entry) {
-       ret = strcmp(entry->name, name);
-       if (ret == 0 && type == entry->type) {
-           /* found, now check if expired */
-           tim = time(NULL);
-           if ((tim - entry->creationtime) > CACHESECONDS) {
-               /* remove item */
-               if (entry->prev) /* 2nd to last in queue */
-                   entry->prev->next = entry->next;
-               else            /* queue head */
-                   namecache[hash] = entry->next;
-               free(entry->name);
-               free(entry->uuid);
-               free(entry);
-               return -1;
-           } else {
-               memcpy(uuid, entry->uuid, UUID_BINSIZE);
-                   return 0;
-           }
-       }
-       entry = entry->next;
+        ret = strcmp(entry->name, name);
+        if (ret == 0 && type == entry->type) {
+            /* found, now check if expired */
+            tim = time(NULL);
+            if ((tim - entry->creationtime) > CACHESECONDS) {
+                LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\'%s\' in queue {%d}", entry->name, hash);
+                /* remove item */
+                if (entry->prev) {
+                    /* 2nd to last in queue */
+                    entry->prev->next = entry->next;
+                    if (entry->next)
+                        /* not the last element */
+                        entry->next->prev = entry->prev;
+                } else  {
+                    /* queue head */
+                    if ((namecache[hash] = entry->next) != NULL)
+                        namecache[hash]->prev = NULL;
+                }
+                free(entry->name);
+                free(entry->uuid);
+                free(entry);
+#ifdef DEBUG
+                dumpcache();
+#endif
+                return -1;
+            } else {
+                memcpy(uuid, entry->uuid, UUID_BINSIZE);
+#ifdef DEBUG
+                dumpcache();
+#endif
+                return 0;
+            }
+        }
+        entry = entry->next;
     }
+#ifdef DEBUG
+    dumpcache();
+#endif
     return -1;
 }
 
+/* 
+ * Caller must free allocated name
+ */
 int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
     int ret;
     unsigned char hash;
     cacheduser_t *entry;
     time_t tim;
 
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     hash = hashuuid(uuidp);
 
     if (! uuidcache[hash])
@@ -238,56 +273,77 @@ int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
         if (ret == 0) {
             tim = time(NULL);
             if ((tim - entry->creationtime) > CACHESECONDS) {
-                LOG(log_info, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash);
-                if (entry->prev)
+                LOG(log_debug, logtype_default, "search_cachebyuuid: expired: name:\'%s\' in queue {%d}", entry->name, hash);
+                if (entry->prev) {
+                    /* 2nd to last in queue */
                     entry->prev->next = entry->next;
-                else
-                    uuidcache[hash] = entry->next;
+                    if (entry->next)
+                        /* not the last element */
+                        entry->next->prev = entry->prev;
+                } else {
+                    /* queue head  */
+                    if ((uuidcache[hash] = entry->next) != NULL)
+                        uuidcache[hash]->prev = NULL;
+                }
                 free(entry->name);
                 free(entry->uuid);
                 free(entry);
+#ifdef DEBUG
+                dumpcache();
+#endif
                 return -1;
             } else {
-               *name = malloc(strlen(entry->name)+1);
-               strcpy(*name, entry->name);
-               *type = entry->type;
+                *name = malloc(strlen(entry->name)+1);
+                strcpy(*name, entry->name);
+                *type = entry->type;
+#ifdef DEBUG
+                dumpcache();
+#endif
                 return 0;
             }
         }
         entry = entry->next;
     }
 
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     return -1;
 }
 
 int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid _U_) {
     int ret = 0;
     char *name = NULL;
-    uuidp_t uuid;
+    unsigned char *uuid = NULL;
     cacheduser_t *cacheduser = NULL;
     cacheduser_t *entry;
     unsigned char hash;
 
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     /* allocate mem and copy values */
     name = malloc(strlen(inname)+1);
     if (!name) {
-       LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
-       ret = -1;
-       goto cleanup;
+        LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
+        ret = -1;
+        goto cleanup;
     }
-    
+
     uuid = malloc(UUID_BINSIZE);
     if (!uuid) {
-       LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
-       ret = -1;
-       goto cleanup;
+        LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
+        ret = -1;
+        goto cleanup;
     }
 
     cacheduser = malloc(sizeof(cacheduser_t));
     if (!cacheduser) {
-       LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
-       ret = -1;
-       goto cleanup;
+        LOG(log_error, logtype_default, "add_cachebyuuid: mallor error");
+        ret = -1;
+        goto cleanup;
     }
 
     strcpy(name, inname);
@@ -304,25 +360,29 @@ int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const
     /* get hash */
     hash = hashuuid(uuid);
 
-    /* insert cache entry into cache array */
-    if (uuidcache[hash] == NULL) { /* this queue is empty */
-       uuidcache[hash] = cacheduser;
-    } else {                   /* queue is not empty, search end of queue*/
-       entry = uuidcache[hash];
-       while( entry->next != NULL)
-           entry = entry->next;
-       cacheduser->prev = entry;
-       entry->next = cacheduser;
+    /* insert cache entry into cache array at head of queue */
+    if (uuidcache[hash] == NULL) {
+        /* this queue is empty */
+        uuidcache[hash] = cacheduser;
+    } else {
+        cacheduser->next = uuidcache[hash];
+        uuidcache[hash]->prev = cacheduser;
+        uuidcache[hash] = cacheduser;
     }
 
 cleanup:
     if (ret != 0) {
-       if (name)
-           free(name);
-       if (uuid)
-           free(uuid);
-       if (cacheduser)
-           free(cacheduser);
+        if (name)
+            free(name);
+        if (uuid)
+            free(uuid);
+        if (cacheduser)
+            free(cacheduser);
     }
+
+#ifdef DEBUG
+    dumpcache();
+#endif
+
     return ret;
 }