+static bool tdb_data_read_uint32(TDB_DATA *buf, uint32_t *result)
+{
+ const size_t len = sizeof(uint32_t);
+ if (buf->dsize >= len) {
+ *result = IVAL(buf->dptr, 0);
+ buf->dptr += len;
+ buf->dsize -= len;
+ return true;
+ }
+ return false;
+}
+
+static bool tdb_data_read_cstr(TDB_DATA *buf, char **result)
+{
+ const size_t len = strnlen((char*)buf->dptr, buf->dsize) + 1;
+ if (buf->dsize >= len) {
+ *result = (char*)buf->dptr;
+ buf->dptr += len;
+ buf->dsize -= len;
+ return true;
+ }
+ return false;
+}
+
+static bool tdb_data_is_empty(TDB_DATA d) {
+ return (d.dptr == NULL) || (d.dsize == 0);
+}
+
+static bool tdb_data_is_cstr(TDB_DATA d) {
+ if (tdb_data_is_empty(d) || (d.dptr[d.dsize-1] != '\0')) {
+ return false;
+ }
+ return rawmemchr(d.dptr, '\0') == &d.dptr[d.dsize-1];
+}
+
+static bool upgrade_v2_to_v3_check_subkeylist(struct db_context *db,
+ const char *key,
+ const char *subkey)
+{
+ static uint32_t zero = 0;
+ static TDB_DATA empty_subkey_list = {
+ .dptr = (unsigned char*)&zero,
+ .dsize = sizeof(uint32_t),
+ };
+ bool success = false;
+ char *path = talloc_asprintf(talloc_tos(), "%s\\%s", key, subkey);
+ strupper_m(path);
+
+ if (!dbwrap_exists(db, string_term_tdb_data(path))) {
+ NTSTATUS status;
+
+ DEBUG(10, ("regdb_upgrade_v2_to_v3: writing subkey list [%s]\n",
+ path));
+
+ status = dbwrap_store_bystring(db, path, empty_subkey_list,
+ TDB_INSERT);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("regdb_upgrade_v2_to_v3: writing subkey list "
+ "[%s] failed\n", path));
+ goto done;
+ }
+ }
+ success = true;
+done:
+ talloc_free(path);
+ return success;
+}
+
+static bool upgrade_v2_to_v3_check_parent(struct db_context *db,
+ const char *key)
+{
+ const char *sep = strrchr_m(key, '\\');
+ if (sep != NULL) {
+ char *pkey = talloc_strndup(talloc_tos(), key, sep-key);
+ if (!dbwrap_exists(db, string_term_tdb_data(pkey))) {
+ DEBUG(0, ("regdb_upgrade_v2_to_v3: missing subkey list "
+ "[%s]\nrun \"net registry check\"\n", pkey));
+ }
+ talloc_free(pkey);
+ }
+ return true;
+}
+
+
+#define IS_EQUAL(d,s) (((d).dsize == strlen(s)+1) && \
+ (strcmp((char*)(d).dptr, (s)) == 0))
+#define STARTS_WITH(d,s) (((d).dsize > strlen(s)) && \
+ (strncmp((char*)(d).dptr, (s), strlen(s)) == 0))
+#define SSTR(d) (int)(d).dsize , (char*)(d).dptr
+
+