summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2009-02-19 20:03:06 +0100
committerKarolin Seeger <kseeger@samba.org>2009-02-20 08:53:30 +0100
commit9034f373d433b5f15f1c2966a69b4092456af625 (patch)
treeeb0ad9814c8b3c4d599f5e9bdc17c8bf325de5a0
parent9f5ab2af11fbef878956e3e6ef6a1c5c511c707e (diff)
downloadsamba-9034f373d433b5f15f1c2966a69b4092456af625.tar.gz
Fix a O(n^2) algorithm in regdb_fetch_keys()
(cherry picked from commit d98c43982c56ef788144a3fd67cdd65a9f95f2be)
-rw-r--r--source/registry/reg_backend_db.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/source/registry/reg_backend_db.c b/source/registry/reg_backend_db.c
index a3cdaa7d41e..fe5f1927139 100644
--- a/source/registry/reg_backend_db.c
+++ b/source/registry/reg_backend_db.c
@@ -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", dos_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;
}
}