registry: Implement new semantics for existence of registry key in tdb.
authorMichael Adam <obnox@samba.org>
Tue, 6 May 2008 08:05:20 +0000 (10:05 +0200)
committerMichael Adam <obnox@samba.org>
Thu, 8 May 2008 16:29:09 +0000 (18:29 +0200)
Existence of a key is defined as follows:
* If the key is a base key (without separator), the key exists
  iff the corresponding entry exist in the registry tdb.
* If the key is not a base key, the key exists, iff it exists
  in the list of subkeys of it's parent keyname's tdb entry.

Michael
(This used to be commit 477008367f0ac90624b4b751955cd3235b2c9cc6)

source3/registry/reg_backend_db.c

index d1ec8e4b61a61670960ab365866cb2f788abadc2..658c979bb2b1ba30479b77954799a3a6da478561 100644 (file)
@@ -770,15 +770,64 @@ static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key)
 }
 
 
+/**
+ * Check for the existence of a key.
+ *
+ * Existence of a key is authoritatively defined by its
+ * existence in the list of subkeys of its parent key.
+ * The exeption of this are keys without a parent key,
+ * i.e. the "base" keys (HKLM, HKCU, ...).
+ */
 static bool regdb_key_exists(const char *key)
 {
        TALLOC_CTX *mem_ctx = talloc_stackframe();
        TDB_DATA value;
-       bool ret;
+       bool ret = false;
+       char *path, *p;
+
+       if (key == NULL) {
+               goto done;
+       }
+
+       path = normalize_reg_path(mem_ctx, key);
+       if (path == NULL) {
+               DEBUG(0, ("out of memory! (talloc failed)\n"));
+               goto done;
+       }
+
+       if (*path == '\0') {
+               goto done;
+       }
 
-       value = regdb_fetch_key_internal(mem_ctx, key);
-       ret = (value.dptr != NULL);
+       p = strrchr(path, '/');
+       if (p == NULL) {
+               /* this is a base key */
+               value = regdb_fetch_key_internal(mem_ctx, path);
+               ret = (value.dptr != NULL);
+       } else {
+               /* get the list of subkeys of the parent key */
+               uint32 num_items, len, i;
+               fstring subkeyname;
+
+               *p = '\0';
+               p++;
+               value = regdb_fetch_key_internal(mem_ctx, path);
+               if (value.dptr == NULL) {
+                       goto done;
+               }
 
+               len = tdb_unpack(value.dptr, value.dsize, "d", &num_items);
+               for (i = 0; i < num_items; i++) {
+                       len += tdb_unpack(value.dptr +len, value.dsize -len,
+                                         "f", &subkeyname);
+                       if (strequal(subkeyname, p)) {
+                               ret = true;
+                               goto done;
+                       }
+               }
+       }
+
+done:
        TALLOC_FREE(mem_ctx);
        return ret;
 }