]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/acl/cache.c
Fix a crash when searching for a UUID that is not a special local UUID and LDAP suppo...
[netatalk.git] / libatalk / acl / cache.c
index ad27aa86cd27992bba1c8f981934a11a41135a31..9fe8405ff72a3e9b9e749cbbeb8b97ce5e559d8f 100644 (file)
@@ -1,5 +1,4 @@
 /*
-  $Id: cache.c,v 1.3 2009-11-28 12:37:30 franklahm Exp $
   Copyright (c) 2008,2009 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -45,25 +44,29 @@ cacheduser_t *uuidcache[256];   /* indexed by hash of uuid */
  * helper function
  ********************************************************/
 
-static int dumpcache() {
+void uuidcache_dump(void) {
     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);
+                LOG(log_debug, logtype_default,
+                    "namecache{%d}: name:%s, uuid:%s, type%s: %s, cached: %s",
+                    i,
+                    entry->name,
+                    uuid_bin2string(entry->uuid),
+                    (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
+                    uuidtype[entry->type & UUIDTYPESTR_MASK],
+                    timestr);
             } while ((entry = entry->next) != NULL);
         }
     }
@@ -71,19 +74,23 @@ static int dumpcache() {
     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_debug, logtype_default,
+                    "uuidcache{%d}: uuid:%s, name:%s, type%s: %s, cached: %s",
+                    i,
+                    uuid_bin2string(entry->uuid),
+                    entry->name,
+                    (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
+                    uuidtype[entry->type & UUIDTYPESTR_MASK],
+                    timestr);
             } while ((entry = entry->next) != NULL);
         }
     }
-
-    return ret;
 }
 
 /* hash string it into unsigned char */
@@ -101,7 +108,7 @@ static unsigned char hashstring(unsigned char *str) {
     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;
@@ -120,9 +127,8 @@ static unsigned char hashuuid(uuidp_t uuid) {
 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;
+    uuidp_t uuid = NULL;
     cacheduser_t *cacheduser = NULL;
-    cacheduser_t *entry;
     unsigned char hash;
 
     /* allocate mem and copy values */
@@ -161,15 +167,14 @@ 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 */
+    /* 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;
-    } 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;
     }
 
 cleanup:
@@ -181,10 +186,21 @@ cleanup:
         if (cacheduser)
             free(cacheduser);
     }
+
     return ret;
 }
 
-int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
+/*!
+ * Search cache by name and uuid type
+ *
+ * @args name     (r)  name to search
+ * @args type     (rw) type (user or group) of name, returns found type here which might
+ *                     mark it as a negative entry
+ * @args uuid     (w)  found uuid is returned here
+ * @returns       0 on sucess, entry found
+ *                -1 no entry found
+ */
+int search_cachebyname(const char *name, uuidtype_t *type, uuidp_t uuid) {
     int ret;
     unsigned char hash;
     cacheduser_t *entry;
@@ -192,36 +208,48 @@ int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
 
     hash = hashstring((unsigned char *)name);
 
-    if (! namecache[hash])
+    if (namecache[hash] == NULL)
         return -1;
 
     entry = namecache[hash];
     while (entry) {
         ret = strcmp(entry->name, name);
-        if (ret == 0 && type == entry->type) {
+        if (ret == 0 && *type == (entry->type & UUIDTYPESTR_MASK)) {
             /* 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);
+                LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\"%s\"", entry->name);
                 /* remove item */
-                if (entry->prev) /* 2nd to last in queue */
+                if (entry->prev) {
+                    /* 2nd to last in queue */
                     entry->prev->next = entry->next;
-                else        /* queue head */
-                    namecache[hash] = 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);
                 return -1;
             } else {
                 memcpy(uuid, entry->uuid, UUID_BINSIZE);
+                *type = entry->type;
                 return 0;
             }
         }
         entry = entry->next;
     }
+
     return -1;
 }
 
+/* 
+ * Caller must free allocated name
+ */
 int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
     int ret;
     unsigned char hash;
@@ -239,11 +267,18 @@ 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);
@@ -264,7 +299,7 @@ int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
 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;
+    uuidp_t uuid = NULL;
     cacheduser_t *cacheduser = NULL;
     cacheduser_t *entry;
     unsigned char hash;
@@ -305,15 +340,14 @@ 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 */
+    /* 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;
-    } 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;
     }
 
 cleanup:
@@ -325,5 +359,6 @@ cleanup:
         if (cacheduser)
             free(cacheduser);
     }
+
     return ret;
 }