Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
First version of the pkg_plugins interface
Marin Atanasov Nikolov committed 13 years ago
commit 7e34c7ca61debddbf933efc304b6e17afcd45497
parent d346148
2 files changed +207 -0
modified libpkg/pkg.h
@@ -65,6 +65,8 @@ struct pkg_repos_entry;

struct pkg_config_kv;

+
struct pkg_plugin;
+

typedef enum {
	/**
	 * The license logic is OR (dual in the ports)
@@ -890,6 +892,7 @@ int64_t pkgdb_stats(struct pkgdb *db, pkg_stats_t type);
 */
int pkg_plugin_init(void);
int pkg_plugin_shutdown(void);
+
int pkg_plugin_list(struct pkg_plugin **plugin);

/**
 * Get the value of a configuration key
added libpkg/plugins.c
@@ -0,0 +1,204 @@
+
/*
+
 * Copyright (c) 2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
+
 * All rights reserved.
+
 * 
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions
+
 * are met:
+
 * 1. Redistributions of source code must retain the above copyright
+
 *    notice, this list of conditions and the following disclaimer
+
 *    in this position and unchanged.
+
 * 2. Redistributions in binary form must reproduce the above copyright
+
 *    notice, this list of conditions and the following disclaimer in the
+
 *    documentation and/or other materials provided with the distribution.
+
 * 
+
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+
#include <sys/queue.h>
+
#include <sys/types.h>
+
#include <sys/stat.h>
+

+
#include <fts.h>
+
#include <fcntl.h>
+
#include <libutil.h>
+
#include <stdbool.h>
+
#include <string.h>
+

+
#include "pkg.h"
+
#include "private/pkg.h"
+
#include "private/event.h"
+

+
#define N(a) (sizeof(a) / sizeof(a[0]))
+

+
struct _pkg_plugin_kv {
+
	 char *key;
+
	 char *val;
+
} pkg_plugin_kv[] = {
+
	[PKG_PLUGIN_NAME] 	= { __DECONST(char *, "name"), NULL },
+
	[PKG_PLUGIN_DESC] 	= { __DECONST(char *, "description"), NULL },
+
	[PKG_PLUGIN_VERSION] 	= { __DECONST(char *, "version"), NULL },
+
	[PKG_PLUGIN_PLUGINFILE]	= { __DECONST(char *, "plugin"), NULL },
+
	[PKG_PLUGIN_ENABLED]	= { __DECONST(char *, "enabled"), NULL },
+
};
+

+
struct pkg_plugin {
+
	struct _pkg_plugin_kv fields[N(pkg_plugin_kv)];
+
	STAILQ_ENTRY(pkg_plugin) next;
+
};
+

+
STAILQ_HEAD(plugin_head, pkg_plugin);
+
static struct plugin_head ph = STAILQ_HEAD_INITIALIZER(ph);
+

+
static int pkg_plugin_discover(void);
+
static int pkg_plugin_parse_conf(const char *file);
+
static int pkg_plugin_free(void);
+

+
static int
+
pkg_plugin_discover(void)
+
{
+
	FTS  	*fts = NULL;
+
	FTSENT	*ftsent = NULL;
+
	char	*paths[2];
+
	const char *plugins_dir = NULL;
+

+
	if (pkg_config_string(PKG_CONFIG_PLUGINS_DIR, &plugins_dir) != EPKG_OK) {
+
		pkg_emit_error("Cannot get PKG_PLUGINS_DIR config entry");
+
		return (EPKG_FATAL);
+
	}
+
	
+
        paths[0] = __DECONST(char *, plugins_dir);
+
        paths[1] = NULL;
+

+
	if ((fts = fts_open(paths, FTS_LOGICAL, NULL)) == NULL) {
+
		pkg_emit_error("fts_open(%s)", plugins_dir);
+
		return (EPKG_FATAL);
+
	}
+

+
	while ((ftsent = fts_read(fts)) != NULL) {
+

+
		/* skip anything that is not a file */
+
		if (ftsent->fts_info != FTS_F)
+
			continue;
+

+
		/* parse only .conf files */
+
		if (strstr(ftsent->fts_name, ".conf") != NULL)
+
			pkg_plugin_parse_conf(ftsent->fts_path);
+
	}
+

+
	fts_close(fts);
+

+
	return (EPKG_OK);
+
}
+

+
static int
+
pkg_plugin_parse_conf(const char *file)
+
{
+
	struct pkg_plugin *new = NULL;
+
	properties p = NULL;
+
	unsigned int i = 0;
+
	char *temp;
+
	int fd = -1;
+
	bool wrong_conf = false;
+

+
	if ((fd = open(file, O_RDONLY)) < 0) {
+
		pkg_emit_error("open(%s)", file);
+
		return (EPKG_FATAL);
+
	}
+

+
	if ((new = calloc(1, sizeof(struct pkg_plugin))) == NULL) {
+
		pkg_emit_error("Cannot allocate memory");
+
		return (EPKG_FATAL);
+
	}
+

+
	p = properties_read(fd);
+

+
	for (i = 0; i < N(pkg_plugin_kv); i++) {
+
		new->fields[i].key = strdup(pkg_plugin_kv[i].key);
+
		if ((temp = property_find(p, new->fields[i].key)) == NULL) {
+
			pkg_emit_error("required option '%s' is not specified in '%s'",
+
				       new->fields[i].key, file);
+
			wrong_conf = true;
+
		} else
+
			new->fields[i].val = strdup(temp);
+
	}
+

+
	properties_free(p);
+
	close(fd);
+

+
	if (wrong_conf == true) {
+
		pkg_emit_error("required options were missing in '%s', plugin will not be loaded", file);
+
		for (i = 0; i < N(pkg_plugin_kv); i++) {
+
			if (new->fields[i].key != NULL)
+
				free(new->fields[i].key);
+
			if (new->fields[i].val != NULL)
+
				free (new->fields[i].val);
+
		}
+
		free(new);
+
		return (EPKG_FATAL);
+
	}
+

+
	STAILQ_INSERT_TAIL(&ph, new, next);
+

+
	return (EPKG_OK);
+
}
+

+
static int
+
pkg_plugin_free(void)
+
{
+
	struct pkg_plugin *p = NULL;
+
	unsigned int i;
+

+
        while (!STAILQ_EMPTY(&ph)) {
+
                p = STAILQ_FIRST(&ph);
+
                STAILQ_REMOVE_HEAD(&ph, next);
+

+
		for (i = 0; i < N(pkg_plugin_kv); i++) {
+
			free(p->fields[i].key);
+
			free(p->fields[i].val);
+
		}
+

+
		free(p);
+
        }
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_plugin_list(struct pkg_plugin **plugin)
+
{
+
	if ((*plugin) == NULL)
+
		(*plugin) = STAILQ_FIRST(&ph);
+
	else
+
		(*plugin) = STAILQ_NEXT((*plugin), next);
+

+
	if ((*plugin) == NULL)
+
		return (EPKG_END);
+
	else
+
		return (EPKG_OK);
+
}
+

+
int
+
pkg_plugin_init(void)
+
{
+
	pkg_plugin_discover();
+

+
	return (EPKG_OK);
+
}
+

+
int
+
pkg_plugin_shutdown(void)
+
{
+
	pkg_plugin_free();
+

+
	return (EPKG_OK);
+
}