/** heim_db_register * @brief Registers a DB type for use with heim_db_create(). * * @param dbtype Name of DB type * @param data Private data argument to the dbtype's openf method * @param plugin Structure with DB type methods (function pointers) * * Backends that provide begin/commit/rollback methods must provide ACID * semantics. * * The registered DB type will have ACID semantics for backends that do * not provide begin/commit/rollback methods but do provide lock/unlock * and rdjournal/wrjournal methods (using a replay log journalling * scheme). * * If the registered DB type does not natively provide read vs. write * transaction isolation but does provide a lock method then the DB will * provide read/write transaction isolation. * * @return ENOMEM on failure, else 0. * * @addtogroup heimbase */ int heim_db_register(const char *dbtype, void *data, struct heim_db_type *plugin) { heim_dict_t plugins; heim_string_t s; db_plugin plug, plug2; int ret = 0; if ((plugin->beginf != NULL && plugin->commitf == NULL) || (plugin->beginf != NULL && plugin->rollbackf == NULL) || (plugin->lockf != NULL && plugin->unlockf == NULL) || plugin->copyf == NULL) heim_abort("Invalid DB plugin; make sure methods are paired"); /* Initialize */ plugins = heim_dict_create(11); if (plugins == NULL) return ENOMEM; heim_base_once_f(&db_plugin_init_once, plugins, db_init_plugins_once); heim_release(plugins); heim_assert(db_plugins != NULL, "heim_db plugin table initialized"); s = heim_string_create(dbtype); if (s == NULL) return ENOMEM; plug = heim_alloc(sizeof (*plug), "db_plug", plugin_dealloc); if (plug == NULL) { heim_release(s); return ENOMEM; } plug->name = heim_retain(s); plug->openf = plugin->openf; plug->clonef = plugin->clonef; plug->closef = plugin->closef; plug->lockf = plugin->lockf; plug->unlockf = plugin->unlockf; plug->syncf = plugin->syncf; plug->beginf = plugin->beginf; plug->commitf = plugin->commitf; plug->rollbackf = plugin->rollbackf; plug->copyf = plugin->copyf; plug->setf = plugin->setf; plug->delf = plugin->delf; plug->iterf = plugin->iterf; plug->data = data; HEIMDAL_MUTEX_lock(&db_type_mutex); plug2 = heim_dict_get_value(db_plugins, s); if (plug2 == NULL) ret = heim_dict_set_value(db_plugins, s, plug); HEIMDAL_MUTEX_unlock(&db_type_mutex); heim_release(plug); heim_release(s); return ret; }
static void search_modules(heim_object_t key, heim_object_t value, void *ctx) { struct iter_ctx *s = ctx; struct plugin2 *p = value; struct plug *pl = heim_dict_get_value(p->names, s->n); struct common_plugin_method *cpm; if (pl == NULL) { if (p->dsohandle == NULL) return; pl = heim_alloc(sizeof(*pl), "struct-plug", plug_free); cpm = pl->dataptr = dlsym(p->dsohandle, s->name); if (cpm) { int ret; ret = cpm->init(s->context, &pl->ctx); if (ret) cpm = pl->dataptr = NULL; } heim_dict_set_value(p->names, s->n, pl); heim_release(pl); } else { cpm = pl->dataptr; } if (cpm && cpm->version >= s->min_version) heim_array_append_value(s->result, pl); }
static struct krb5_krbhst_data* common_init(krb5_context context, const char *service, const char *realm, int flags) { struct krb5_krbhst_data *kd; if ((kd = heim_alloc(sizeof(*kd), "krbhst-context", krbhost_dealloc)) == NULL) return NULL; if((kd->realm = strdup(realm)) == NULL) { heim_release(kd); return NULL; } _krb5_debug(context, 2, "Trying to find service %s for realm %s flags %x", service, realm, flags); /* For 'realms' without a . do not even think of going to DNS */ if (!strchr(realm, '.')) kd->flags |= KD_CONFIG_EXISTS; if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG) kd->flags |= KD_LARGE_MSG; kd->end = kd->index = &kd->hosts; return kd; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx) { *ctx = heim_alloc(sizeof(**ctx), "sendto-context", dealloc_sendto_ctx); if (*ctx == NULL) return krb5_enomem(context); (*ctx)->hosts = heim_array_create(); return 0; }
static int json_db_open(void *plug, const char *dbtype, const char *dbname, heim_dict_t options, void **db, heim_error_t *error) { json_db_t jsondb; heim_dict_t contents = NULL; heim_string_t dbname_s = NULL; heim_string_t bkpname_s = NULL; if (error) *error = NULL; if (dbtype && *dbtype && strcmp(dbtype, "json")) return HEIM_ERROR(error, EINVAL, (EINVAL, N_("Wrong DB type", ""))); if (dbname && *dbname && strcmp(dbname, "MEMORY") != 0) { char *ext = strrchr(dbname, '.'); char *bkpname; size_t len; int ret; if (ext == NULL || strcmp(ext, ".json") != 0) return HEIM_ERROR(error, EINVAL, (EINVAL, N_("JSON DB files must end in .json", ""))); if (options) { heim_object_t vc, ve, vt; vc = heim_dict_get_value(options, HSTR("create")); ve = heim_dict_get_value(options, HSTR("exclusive")); vt = heim_dict_get_value(options, HSTR("truncate")); if (vc && vt) { ret = open_file(dbname, 1, ve ? 1 : 0, NULL, error); if (ret) return ret; } else if (vc || ve || vt) { return HEIM_ERROR(error, EINVAL, (EINVAL, N_("Invalid JSON DB open options", ""))); } /* * We don't want cloned handles to truncate the DB, eh? * * We should really just create a copy of the options dict * rather than modify the caller's! But for that it'd be * nicer to have copy utilities in heimbase, something like * this: * * heim_object_t heim_copy(heim_object_t src, int depth, * heim_error_t *error); * * so that options = heim_copy(options, 1); means copy the * dict but nothing else (whereas depth == 0 would mean * heim_retain(), and depth > 1 would be copy that many * levels). */ heim_dict_delete_key(options, HSTR("create")); heim_dict_delete_key(options, HSTR("exclusive")); heim_dict_delete_key(options, HSTR("truncate")); } dbname_s = heim_string_create(dbname); if (dbname_s == NULL) return HEIM_ENOMEM(error); len = snprintf(NULL, 0, "%s~", dbname); bkpname = malloc(len + 2); if (bkpname == NULL) { heim_release(dbname_s); return HEIM_ENOMEM(error); } (void) snprintf(bkpname, len + 1, "%s~", dbname); bkpname_s = heim_string_create(bkpname); free(bkpname); if (bkpname_s == NULL) { heim_release(dbname_s); return HEIM_ENOMEM(error); } ret = read_json(dbname, (heim_object_t *)&contents, error); if (ret) return ret; if (contents != NULL && heim_get_tid(contents) != HEIM_TID_DICT) return HEIM_ERROR(error, EINVAL, (EINVAL, N_("JSON DB contents not valid JSON", ""))); } jsondb = heim_alloc(sizeof (*jsondb), "json_db", NULL); if (jsondb == NULL) { heim_release(contents); heim_release(dbname_s); return ENOMEM; } jsondb->last_read_time = time(NULL); jsondb->fd = -1; jsondb->dbname = dbname_s; jsondb->bkpname = bkpname_s; jsondb->read_only = 0; if (contents != NULL) jsondb->dict = contents; else { jsondb->dict = heim_dict_create(29); if (jsondb->dict == NULL) { heim_release(jsondb); return ENOMEM; } } *db = jsondb; return 0; }
/** * Load plugins (new system) for the given module @name (typicall * "krb5") from the given directory @paths. * * Inputs: * * @context A krb5_context * @name Name of plugin module (typically "krb5") * @paths Array of directory paths where to look */ void _krb5_load_plugins(krb5_context context, const char *name, const char **paths) { #ifdef HAVE_DLOPEN heim_string_t s = heim_string_create(name); heim_dict_t module; struct dirent *entry; krb5_error_code ret; const char **di; DIR *d; HEIMDAL_MUTEX_lock(&plugin_mutex); if (modules == NULL) { modules = heim_dict_create(11); if (modules == NULL) { HEIMDAL_MUTEX_unlock(&plugin_mutex); return; } } module = heim_dict_get_value(modules, s); if (module == NULL) { module = heim_dict_create(11); if (module == NULL) { HEIMDAL_MUTEX_unlock(&plugin_mutex); heim_release(s); return; } heim_dict_set_value(modules, s, module); heim_release(module); } heim_release(s); for (di = paths; *di != NULL; di++) { d = opendir(*di); if (d == NULL) continue; rk_cloexec_dir(d); while ((entry = readdir(d)) != NULL) { char *n = entry->d_name; char *path = NULL; heim_string_t spath; struct plugin2 *p; /* skip . and .. */ if (n[0] == '.' && (n[1] == '\0' || (n[1] == '.' && n[2] == '\0'))) continue; ret = 0; #ifdef __APPLE__ { /* support loading bundles on MacOS */ size_t len = strlen(n); if (len > 7 && strcmp(&n[len - 7], ".bundle") == 0) ret = asprintf(&path, "%s/%s/Contents/MacOS/%.*s", *di, n, (int)(len - 7), n); } #endif if (ret < 0 || path == NULL) ret = asprintf(&path, "%s/%s", *di, n); if (ret < 0 || path == NULL) continue; spath = heim_string_create(n); if (spath == NULL) { free(path); continue; } /* check if already cached */ p = heim_dict_get_value(module, spath); if (p == NULL) { p = heim_alloc(sizeof(*p), "krb5-plugin", plug_dealloc); if (p) p->dsohandle = dlopen(path, RTLD_LOCAL|RTLD_LAZY); if (p->dsohandle) { p->path = heim_retain(spath); p->names = heim_dict_create(11); heim_dict_set_value(module, spath, p); } heim_release(p); } heim_release(spath); free(path); } closedir(d); } HEIMDAL_MUTEX_unlock(&plugin_mutex); #endif /* HAVE_DLOPEN */ }