]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Fix a O(n^2) algorithm in regdb_fetch_keys()
authorVolker Lendecke <vl@samba.org>
Thu, 19 Feb 2009 19:03:06 +0000 (20:03 +0100)
committerVolker Lendecke <vl@samba.org>
Thu, 19 Feb 2009 19:06:29 +0000 (20:06 +0100)
source3/registry/reg_backend_db.c

index 612b448cacd0c4fb634b4a61a08a35101b11534d..fe5f19271395c5158da2e71e1be68551cf5dad56 100644 (file)
@@ -942,7 +942,6 @@ done:
 
 int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
 {
-       WERROR werr;
        uint32 num_items;
        uint8 *buf;
        uint32 buflen, len;
@@ -973,12 +972,35 @@ int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr)
        buflen = value.dsize;
        len = tdb_unpack( buf, buflen, "d", &num_items);
 
+       /*
+        * The following code breaks the abstraction that reg_objects.c sets
+        * up with regsubkey_ctr_addkey(). But if we use that with the current
+        * data structure of ctr->subkeys being an unsorted array, we end up
+        * with an O(n^2) algorithm for retrieving keys from the tdb
+        * file. This is pretty pointless, as we have to trust the data
+        * structure on disk not to have duplicates anyway. The alternative to
+        * breaking this abstraction would be to set up a more sophisticated
+        * data structure in REGSUBKEY_CTR.
+        *
+        * This makes "net conf list" for a registry with >1000 shares
+        * actually usable :-)
+        */
+
+       ctr->subkeys = talloc_array(ctr, char *, num_items);
+       if (ctr->subkeys == NULL) {
+               DEBUG(5, ("regdb_fetch_keys: could not allocate subkeys\n"));
+               goto done;
+       }
+       ctr->num_subkeys = num_items;
+
        for (i=0; i<num_items; i++) {
                len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
-               werr = regsubkey_ctr_addkey(ctr, subkeyname);
-               if (!W_ERROR_IS_OK(werr)) {
-                       DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
-                                 "failed: %s\n", win_errstr(werr)));
+               ctr->subkeys[i] = talloc_strdup(ctr->subkeys, subkeyname);
+               if (ctr->subkeys[i] == NULL) {
+                       DEBUG(5, ("regdb_fetch_keys: could not allocate "
+                                 "subkeyname\n"));
+                       TALLOC_FREE(ctr->subkeys);
+                       ctr->num_subkeys = 0;
                        goto done;
                }
        }