예제 #1
0
파일: db.c 프로젝트: InvLim/heimdal
/** 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;
}
예제 #2
0
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);
}
예제 #3
0
파일: krbhst.c 프로젝트: Kendra123/heimdal
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;
}
예제 #4
0
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;
}
예제 #5
0
파일: db.c 프로젝트: InvLim/heimdal
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;
}
예제 #6
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 */
}