Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
This is better if diff are not omitted
Baptiste Daroussin committed 15 years ago
commit 7f3adc899bd3507e5b5230b9d56738df29dfd43c
parent d8c1981f4b83052747a1e028e3a6e4093baa8f4e
11 files changed +277 -393
modified libpkg/Makefile
@@ -8,9 +8,7 @@ SHLIB_MAJOR= 0

SRCS=		pkg.c \
		pkgdb.c \
-
		pkg_compat.c \
		pkg_conflict.c \
-
		pkg_create.c \
		pkg_file.c \
		pkg_manifest.c \
		util.c
modified libpkg/pkg.c
@@ -1,4 +1,7 @@
#include <err.h>
+
#include <string.h>
+
#include <archive.h>
+
#include <archive_entry.h>
#include <stdlib.h>

#include <sqlite3.h>
@@ -37,7 +40,7 @@ pkg_comment(struct pkg *pkg)
const char *
pkg_desc(struct pkg *pkg)
{
-
	return (sbuf_data(pkg->comment));
+
	return (sbuf_data(pkg->desc));
}

struct pkg **
@@ -65,6 +68,73 @@ pkg_conflicts(struct pkg *pkg)
}

int
+
pkg_open(const char *path, struct pkg **pkg, int query_flags)
+
{
+
	struct archive *a;
+
	struct archive_entry *ae;
+
	struct pkg_file *file = NULL;
+
	int ret;
+
	int64_t size;
+
	char *buf;
+

+
	a = archive_read_new();
+
	archive_read_support_compression_all(a);
+
	archive_read_support_format_tar(a);
+

+
	if (archive_read_open_filename(a, path, 4096) != ARCHIVE_OK) {
+
		archive_read_finish(a);
+
		return (-1);
+
	}
+

+
	/* first patch to check is the archive is corrupted bye the way retreive
+
	 * informations */
+

+
	pkg_new(pkg);
+

+
	while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
+
		if (!strcmp(archive_entry_pathname(ae),"+DESC")) {
+
			size = archive_entry_size(ae);
+
			buf = calloc(1, size+1);
+
			archive_read_data(a, buf, size);
+
			sbuf_cat((*pkg)->desc, buf);
+
			sbuf_finish((*pkg)->desc);
+
			free(buf);
+
		}
+

+
		if (!strcmp(archive_entry_pathname(ae), "+MANIFEST")) {
+
			size = archive_entry_size(ae);
+
			buf = calloc(1, size + 1);
+
			archive_read_data(a, buf, size);
+
			pkg_parse_manifest(*pkg, buf);
+
			free(buf);
+
		}
+

+
		if (archive_entry_pathname(ae)[0] == '+') {
+
			archive_read_data_skip(a);
+
			continue;
+
		}
+

+

+
		if (file == NULL)
+
			pkg_file_new(&file);
+
		else
+
			pkg_file_reset(file);
+

+
		strlcpy(file->path, archive_entry_pathname(ae), sizeof(file->path));
+

+
		array_append(&(*pkg)->files, file);
+
		archive_read_data_skip(a);
+
	}
+

+
	if (ret != ARCHIVE_EOF)
+
		warn("Archive corrupted");
+

+
	archive_read_finish(a);
+

+
	return (0);
+
}
+

+
int
pkg_new(struct pkg **pkg)
{
	if ((*pkg = calloc(1, sizeof(struct pkg))) == NULL)
modified libpkg/pkg.h
@@ -18,6 +18,7 @@ typedef enum _match_t {

/* pkg */
int pkg_new(struct pkg **);
+
int pkg_open(const char *, struct pkg **, int);
void pkg_reset(struct pkg *);
void pkg_free(struct pkg *);
const char *pkg_name(struct pkg *);
@@ -30,6 +31,9 @@ struct pkg ** pkg_rdeps(struct pkg *);
struct pkg_file ** pkg_files(struct pkg *);
struct pkg_conflict ** pkg_conflicts(struct pkg *);

+
/* pkg_manifest */
+
int pkg_parse_manifest(struct pkg *, char *);
+

/* pkg_file */
int pkg_file_new(struct pkg_file **);
void pkg_file_reset(struct pkg_file *);
modified libpkg/pkg_compat.c
@@ -1,10 +1,12 @@
#include <sys/param.h>
+
#include <sys/stat.h>
#include <sys/utsname.h>

#include <ctype.h>
#include <err.h>
#include <stdlib.h>
#include <string.h>
+
#include <libgen.h>

#include "util.h"
#include "pkg_compat.h"
@@ -231,14 +233,13 @@ struct pkg_manifest *
pkg_compat_convert_installed(const char *pkg_dbdir, char *pkgname, char *mpath)
{
	struct pkg_manifest *m;
-
	char *buffer;
+
	char *buffer, *dir;
	off_t buffer_len;
-
	char filepath[MAXPATHLEN], pkg_dir[MAXPATHLEN];
+
	char filepath[MAXPATHLEN];

-
	snprintf(pkg_dir, sizeof(pkg_dir), "%s/%s", pkg_dbdir, pkgname);
-
	snprintf(filepath, sizeof(filepath), "%s/+CONTENTS", pkg_dir);
+
	snprintf(filepath, sizeof(filepath), "%s/%s/+CONTENTS", pkg_dbdir, pkgname);

-
	if (file_to_buffer(filepath, &buffer) == -1) {
+
	if ((buffer_len = file_to_buffer(filepath, &buffer)) == -1) {
		warnx("can not read %s", filepath);
		return (NULL);
	}
@@ -250,7 +251,9 @@ pkg_compat_convert_installed(const char *pkg_dbdir, char *pkgname, char *mpath)
	}

	/* adding comment */
-
	snprintf(filepath, sizeof(filepath), "%s/+COMMENT", pkg_dir);
+
	dir =  dirname(filepath);
+
	snprintf(filepath, sizeof(filepath), "%s/+COMMENT", dirname(filepath));
+
	free(dir);

	if ((buffer_len = file_to_buffer(filepath, &buffer)) == -1) {
		warn("Unable to read +COMMENT for %s", pkgname);
@@ -263,9 +266,9 @@ pkg_compat_convert_installed(const char *pkg_dbdir, char *pkgname, char *mpath)
	}

	/* adding description */
-
	snprintf(filepath, sizeof(filepath), "%s/+DESC", pkg_dir);
+
	snprintf(filepath, sizeof(filepath), "%s/+DESC", dirname(filepath));

-
	if (file_to_buffer(filepath, &buffer) == -1) {
+
	if ((buffer_len = file_to_buffer(filepath, &buffer)) == -1) {
		warn("Unable to read +DESC for %s", pkgname);
	} else {
		pkg_manifest_add_value(m, "desc", buffer);
@@ -273,9 +276,9 @@ pkg_compat_convert_installed(const char *pkg_dbdir, char *pkgname, char *mpath)
	}

	/* adding display */
-
	snprintf(filepath, sizeof(filepath), "%s/+DISPLAY", pkg_dir);
+
	snprintf(filepath, sizeof(filepath), "%s/+DISPLAY", dirname(filepath));
	/* ignore if no +DISPLAY */
-
	if (file_to_buffer(filepath, &buffer) != -1) {
+
	if ((buffer_len = file_to_buffer(filepath, &buffer)) != -1) {
		pkg_manifest_add_value(m, "display", buffer);
		free(buffer);
	}
modified libpkg/pkg_manifest.c
@@ -1,446 +1,195 @@
#include <assert.h>
+
#include <ctype.h>
#include <err.h>
#include <stdbool.h>
#include <stdlib.h>
+
#include <string.h>
+
#include <sys/types.h>
+
#include <sys/sbuf.h>

-
#include <jansson.h>
-

+
#include "util.h"
#include "pkg.h"
-
#include "pkg_manifest.h"
-

-
enum array_type {
-
	ARRAY_FILES,
-
	ARRAY_DEPS,
-
	ARRAY_CONFLICTS,
-
	ARRAY_EXEC,
-
	ARRAY_UNEXEC
-
};
-

-
struct pkg_manifest_array {
-
	json_t *node;
-
	json_t *elm;
-
	unsigned int size;
-
	unsigned int idx;
-
	enum array_type type;
-
};
-

-
struct pkg_manifest {
-
	json_t *json;
-
	struct pkg_manifest_array array;
+
#include "pkg_private.h"
+

+
static int m_parse_name(struct pkg *pkg, char *buf);
+
static int m_parse_origin(struct pkg *pkg, char *buf);
+
static int m_parse_version(struct pkg *pkg, char *buf);
+
static int m_parse_arch(struct pkg *pkg, char *buf);
+
static int m_parse_osrelease(struct pkg *pkg, char *buf);
+
static int m_parse_osversion(struct pkg *pkg, char *buf);
+
static int m_parse_build_time(struct pkg *pkg, char *buf);
+
static int m_parse_www(struct pkg *pkg, char *buf);
+
static int m_parse_comment(struct pkg *pkg, char *buf);
+
static int m_parse_license(struct pkg *pkg, char *buf);
+
static int m_parse_option(struct pkg *pkg, char *buf);
+
static int m_parse_dep(struct pkg *pkg, char *buf);
+
static int m_parse_conflict(struct pkg *pkg, char *buf);
+

+
#define MANIFEST_FORMAT_KEY "@pkg_format_version"
+

+
static struct manifest_key {
+
	const char *key;
+
	int (*parse)(struct pkg *pkg, char *buf);
+
} manifest_key[] = {
+
	{ "@name", m_parse_name},
+
	{ "@origin", m_parse_origin},
+
	{ "@version", m_parse_version},
+
	{ "@arch", m_parse_arch},
+
	{ "@osrelease", m_parse_osrelease},
+
	{ "@osversion", m_parse_osversion},
+
	{ "@build_time", m_parse_build_time},
+
	{ "@www", m_parse_www},
+
	{ "@comment", m_parse_comment},
+
	{ "@license", m_parse_license},
+
	{ "@option", m_parse_option},
+
	{ "@dep", m_parse_dep},
+
	{ "@conflict", m_parse_conflict},
};

-
/* Helpers */
-
const char * pkg_manifest_keystr(json_t *, const char *);
-
void pkg_manifest_array_init(struct pkg_manifest *, enum array_type);
-
const char * pkg_manifest_simplenext(struct pkg_manifest *, enum array_type,
-
									 const char *);
-

-
const char *
-
pkg_manifest_keystr(json_t *root, const char *key)
-
{
-
	json_t *node;
-

-
	if ((node = json_object_get(root, key)) == NULL)
-
		return (NULL);
-
	else
-
		return json_string_value(node);
-
}
-

-
void
-
pkg_manifest_array_init(struct pkg_manifest *m, enum array_type t)
-
{
-
	m->array.node = NULL;
-
	m->array.elm = NULL;
-
	m->array.size = 0;
-
	m->array.idx = 0;
-
	m->array.type = t;
-
}
-

-
const char *
-
pkg_manifest_simplenext(struct pkg_manifest *m, enum array_type t, const char *key)
-
{
-
	assert(m->array.type == t);
-

-
	/* First call */
-
	if (m->array.node == NULL) {
-
		if ((m->array.node = json_object_get(m->json, key)) == NULL)
-
			return (NULL);
-
		m->array.size = json_array_size(m->array.node);
-
	}
-

-
	if (m->array.idx >= m->array.size)
-
		return (NULL);
-

-
	if ((m->array.elm = json_array_get(m->array.node, m->array.idx)) == NULL)
-
		return (NULL);
-

-
	m->array.idx++;
-

-
	return json_string_value(m->array.elm);
-
}
-

-
/*
-
 * Simple accesser for string value at the root of the JSON node
-
 */
-
const char *
-
pkg_manifest_value(struct pkg_manifest *manifest, const char *key)
-
{
-
	const char *str;
-

-
	if ((str = pkg_manifest_keystr(manifest->json, key)) == NULL)
-
		warnx("Can not find '%s' in the manifest", key);
-

-
	return (str);
-
}
-

-
/*
-
 * Return true if the package was built with option named `name'
-
 */
-
bool
-
pkg_manifest_with_option(struct pkg_manifest *manifest, const char *name)
-
{
-
	json_t *node;
-
	json_t *elm;
-

-
	if ((node = json_object_get(manifest->json, "options")) == NULL)
-
		return (false);
-

-
	if ((elm = json_object_get(node, name)) == NULL)
-
		return (false);
-

-
	return json_equal(elm, json_true());
-
}
-

-
void
-
pkg_manifest_file_init(struct pkg_manifest *m)
-
{
-
	pkg_manifest_array_init(m, ARRAY_FILES);
-
}
+
#define manifest_key_len (int)(sizeof(manifest_key)/sizeof(manifest_key[0]))

-
/*
-
 * Return 0 if there is another file, 1 if we are done, -1 if an error occured.
-
 */
-
int
-
pkg_manifest_file_next(struct pkg_manifest *m)
+
static int
+
m_parse_name(struct pkg *pkg, char *buf)
{
-
	assert(m->array.type == ARRAY_FILES);
-

-
	/* First call */
-
	if (m->array.node == NULL) {
-
		if ((m->array.node = json_object_get(m->json, "files")) == NULL)
-
			return (-1);
-
		m->array.size = json_array_size(m->array.node);
-
	}
+
	/* remove trailing spaces */
+
	while (isspace(*buf))
+
		buf++;

-
	if (m->array.idx >= m->array.size)
-
		return (1);
-

-
	if ((m->array.elm = json_array_get(m->array.node, m->array.idx)) == NULL)
-
		return (-1);
-

-
	m->array.idx++;
+
	sbuf_cat(pkg->name, buf);
+
	sbuf_finish(pkg->name);

	return (0);
}

-
const char *
-
pkg_manifest_file_path(struct pkg_manifest *m)
+
static int
+
m_parse_origin(struct pkg *pkg, char *buf)
{
-
	assert(m->array.type == ARRAY_FILES);
-
	assert(m->array.elm != NULL);
+
	while (isspace(*buf))
+
		buf++;

-
	return pkg_manifest_keystr(m->array.elm, "path");
-
}
-

-
const char *
-
pkg_manifest_file_md5(struct pkg_manifest *m)
-
{
-
	assert(m->array.type == ARRAY_FILES);
-
	assert(m->array.elm != NULL);
-

-
	return pkg_manifest_keystr(m->array.elm, "md5");
-
}
-

-
void
-
pkg_manifest_dep_init(struct pkg_manifest *m)
-
{
-
	pkg_manifest_array_init(m, ARRAY_DEPS);
-
}
-

-
int
-
pkg_manifest_dep_next(struct pkg_manifest *m)
-
{
-
	assert(m->array.type == ARRAY_DEPS);
-

-
	/* First call */
-
	if (m->array.node == NULL) {
-
		if ((m->array.node = json_object_get(m->json, "deps")) == NULL)
-
			return (-1);
-
		m->array.size = json_array_size(m->array.node);
-
	}
-

-
	if (m->array.idx >= m->array.size)
-
		return (1);
-

-
	if ((m->array.elm = json_array_get(m->array.node, m->array.idx)) == NULL)
-
		return (-1);
-

-
	m->array.idx++;
+
	sbuf_cat(pkg->origin, buf);
+
	sbuf_finish(pkg->origin);

	return (0);
-

-
}
-

-
const char *
-
pkg_manifest_dep_name(struct pkg_manifest *m)
-
{
-
	assert(m->array.type == ARRAY_DEPS);
-
	assert(m->array.elm != NULL);
-

-
	return pkg_manifest_keystr(m->array.elm, "name");
-
}
-

-
const char *
-
pkg_manifest_dep_origin(struct pkg_manifest *m)
-
{
-
	assert(m->array.type == ARRAY_DEPS);
-
	assert(m->array.elm != NULL);
-

-
	return pkg_manifest_keystr(m->array.elm, "origin");
}

-
const char *
-
pkg_manifest_dep_version(struct pkg_manifest *m)
+
static int
+
m_parse_version(struct pkg *pkg, char *buf)
{
-
	assert(m->array.type == ARRAY_DEPS);
-
	assert(m->array.elm != NULL);
-

-
	return pkg_manifest_keystr(m->array.elm, "version");
-
}
+
	while (isspace(*buf))
+
		buf++;

-
void
-
pkg_manifest_conflict_init(struct pkg_manifest *m)
-
{
-
	pkg_manifest_array_init(m, ARRAY_CONFLICTS);
-
}
+
	sbuf_cat(pkg->version, buf);
+
	sbuf_finish(pkg->version);

-
const char *
-
pkg_manifest_conflict_next(struct pkg_manifest *m)
-
{
-
	return pkg_manifest_simplenext(m, ARRAY_CONFLICTS, "conflicts");
-
}
-

-
void
-
pkg_manifest_exec_init(struct pkg_manifest *m)
-
{
-
	pkg_manifest_array_init(m, ARRAY_EXEC);
-
}
-

-
const char *
-
pkg_manifest_exec_next(struct pkg_manifest *m)
-
{
-
	return pkg_manifest_simplenext(m, ARRAY_EXEC, "exec");
+
	return (0);
}

-
void
-
pkg_manifest_unexec_init(struct pkg_manifest *m)
+
static int
+
m_parse_arch(struct pkg *pkg, char *buf)
{
-
	pkg_manifest_array_init(m, ARRAY_UNEXEC);
+
	/* TODO */
+
	return (0);
}

-
const char *
-
pkg_manifest_unexec_next(struct pkg_manifest *m)
+
static int
+
m_parse_osrelease(struct pkg *pkg, char *buf)
{
-
	return pkg_manifest_simplenext(m, ARRAY_UNEXEC, "unexec");
+
	/* TODO */
+
	return (0);
}

-
/* Setters */
-

-
void
-
pkg_manifest_add_value(struct pkg_manifest *m, const char *key, const char *value)
+
static int
+
m_parse_osversion(struct pkg *pkg, char *buf)
{
-
	json_object_set_new(m->json, key, json_string(value));
+
	/* TODO */
+
	return (0);
}

-
void
-
pkg_manifest_add_file(struct pkg_manifest *m, const char *path, const char *md5)
+
static int
+
m_parse_build_time(struct pkg *pkg, char *buf)
{
-
	json_t *files;
-
	json_t *file;
-

-
	if ((files = json_object_get(m->json, "files")) == NULL) {
-
		files = json_array();
-
		json_object_set_new(m->json, "files", files);
-
	}
-

-
	file = json_object();
-
	json_object_set_new(file, "path", json_string(path));
-
	json_object_set_new(file, "md5", json_string(md5));
-

-
	json_array_append_new(files, file);
+
	/* TODO */
+
	return (0);
}

-
void
-
pkg_manifest_add_dep(struct pkg_manifest *m, const char *name, const char *origin,
-
					 const char *version)
+
static int
+
m_parse_www(struct pkg *pkg, char *buf)
{
-
	json_t *deps;
-
	json_t *dep;
-

-
	if ((deps = json_object_get(m->json, "deps")) == NULL) {
-
		deps = json_array();
-
		json_object_set_new(m->json, "deps", deps);
-
	}
-

-
	dep = json_object();
-
	json_object_set_new(dep, "name", json_string(name));
-
	json_object_set_new(dep, "origin", json_string(origin));
-
	json_object_set_new(dep, "version", json_string(version));
-

-
	json_array_append_new(deps, dep);
+
	/* TODO */
+
	return (0);
}

-
void
-
pkg_manifest_add_conflict(struct pkg_manifest *m, const char *value)
+
static int
+
m_parse_comment(struct pkg *pkg, char *buf)
{
-
	json_t *array;
+
	while (isspace(*buf))
+
		buf++;

-
	if ((array = json_object_get(m->json, "conflicts")) == NULL) {
-
		array = json_array();
-
		json_object_set_new(m->json, "conflicts", array);
-
	}
+
	sbuf_cat(pkg->comment, buf);
+
	sbuf_finish(pkg->comment);

-
	json_array_append_new(array, json_string(value));
+
	return (0);
}

-
void
-
pkg_manifest_add_exec(struct pkg_manifest *m, const char *value)
+
static int
+
m_parse_license(struct pkg *pkg, char *buf)
{
-
	json_t *array;
-

-
	if ((array = json_object_get(m->json, "exec")) == NULL) {
-
		array = json_array();
-
		json_object_set_new(m->json, "exec", array);
-
	}
-

-
	json_array_append_new(array, json_string(value));
+
	/* TODO */
+
	return (0);
}

-
void
-
pkg_manifest_add_unexec(struct pkg_manifest *m, const char *value)
+
static int
+
m_parse_option(struct pkg *pkg, char *buf)
{
-
	json_t *array;
-

-
	if ((array = json_object_get(m->json, "unexec")) == NULL) {
-
		array = json_array();
-
		json_object_set_new(m->json, "unexec", array);
-
	}
-

-
	json_array_append_new(array, json_string(value));
+
	/* TODO */
+
	return (0);
}

-
struct pkg_manifest *
-
pkg_manifest_new(void)
+
static int
+
m_parse_dep(struct pkg *pkg, char *buf)
{
-
	struct pkg_manifest *m;
-

-
	if ((m = malloc(sizeof(struct pkg_manifest))) == NULL)
-
		err(EXIT_FAILURE, "malloc()");
-

-
	m->json = json_object();
-

-
	return (m);
+
	/* TODO */
+
	return (0);
}

-
struct pkg_manifest *
-
pkg_manifest_load_buffer(const char *buffer)
+
static int
+
m_parse_conflict(struct pkg *pkg, char *buf)
{
-
	struct pkg_manifest *m;
-
	json_error_t error;
-

-
	if ((m = malloc(sizeof(struct pkg_manifest))) == NULL)
-
		err(EXIT_FAILURE, "malloc()");
-

-
	if ((m->json = json_loads(buffer, &error)) == NULL) {
-
		warnx("Can not parse buffer as JSON: %s", error.text);
-
		free(m);
-
		return (NULL);
-
	}
-

-
	return (m);
+
	/* TODO */
+
	return (0);
}

-
struct pkg_manifest *
-
pkg_manifest_load_file(const char *path)
+
int
+
pkg_parse_manifest(struct pkg *pkg, char *buf)
{
-
	struct pkg_manifest *m;
-
	json_error_t error;
-

-
	if ((m = malloc(sizeof(struct pkg_manifest))) == NULL)
-
		err(EXIT_FAILURE, "malloc()");
+
	int nbl;
+
	int i, j;
+
	char *buf_ptr;
+
	size_t next;

-
	if ((m->json = json_load_file(path, &error)) == NULL) {
-
		warnx("Can not parse %s: %s", path, error.text);
-
		free(m);
-
		return (NULL);
-
	}

-
	return (m);
-
}
+
	nbl = split_chr(buf, '\n');

-
int
-
pkg_manifest_from_pkg(struct pkg *pkg, struct pkg_manifest **m)
-
{
-
	size_t i;
-
	struct pkg **deps;
-
	struct pkg_file **files;
-
	*m = pkg_manifest_new();
-

-
	pkg_manifest_add_value(*m, "name", pkg_name(pkg));
-
	pkg_manifest_add_value(*m, "version", pkg_version(pkg));
-
	pkg_manifest_add_value(*m, "origin", pkg_version(pkg));
-
	pkg_manifest_add_value(*m, "comment", pkg_comment(pkg));
-
	pkg_manifest_add_value(*m, "desc", pkg_desc(pkg));
-

-
	deps = pkg_deps(pkg);
-
	if (deps == NULL) {
-
		warnx("Mising deps informations in pkg %s", pkg_origin(pkg));
+
	buf_ptr = buf;
+
	if (!STARTS_WITH(buf, MANIFEST_FORMAT_KEY)) {
+
		warn("Not a package manifest");
		return (-1);
	}
-
	for (i = 0; deps[i] != NULL; i++) {
-
		pkg_manifest_add_dep(*m, pkg_name(deps[i]), pkg_origin(deps[i]),
-
							 pkg_version(deps[i]));
-
	}

-
	files = pkg_files(pkg);
-
	if (files == NULL) {
-
		warnx("Missing files informations in pkg %s", pkg_origin(pkg));
-
		return (-1);
-
	}
-
	for (i = 0; files[i] != NULL; i++) {
-
		pkg_manifest_add_file(*m, pkg_file_path(files[i]), pkg_file_md5(files[i]));
+
	next = strlen(buf_ptr);
+
	buf_ptr += next + 1;
+
	next = strlen(buf_ptr);
+
	for (i = 1; i <= nbl; i++) {
+
		for (j = 0; j < manifest_key_len; j++) {
+
			if (STARTS_WITH(buf_ptr, manifest_key[j].key)) {
+
				manifest_key[j].parse(pkg, buf_ptr + strlen(manifest_key[j].key));
+
				break;
+
			}
+
		}
+
		buf_ptr += next + 1;
+
		next = strlen(buf_ptr);
	}

-
	/* TODO: conflicts, exec, unexec */
	return (0);
}
-

-
char *
-
pkg_manifest_dump_buffer(struct pkg_manifest *m)
-
{
-
	return json_dumps(m->json, JSON_COMPACT);
-
}
-

-
int
-
pkg_manifest_dump_file(struct pkg_manifest *m, const char *path)
-
{
-
	return json_dump_file(m->json, path, JSON_INDENT(2));
-
}
-

-
void
-
pkg_manifest_free(struct pkg_manifest *m)
-
{
-
	json_decref(m->json);
-
	free(m);
-
}
-

modified libpkg/pkg_private.h
@@ -6,6 +6,12 @@

#include "util.h"

+
typedef enum {
+
	PKG_FILE,
+
	PKG_REMOTE,
+
	PKG_INSTALLED,
+
	PKG_NOTFOUND
+
} pkg_t;
struct pkg {
	struct sbuf *origin;
	struct sbuf *name;
@@ -16,6 +22,7 @@ struct pkg {
	struct array rdeps;
	struct array conflicts;
	struct array files;
+
	pkg_t type;
};

struct pkg_conflict {
modified libpkg/util.c
@@ -139,3 +139,20 @@ select_dir(const struct dirent *dirent)

	return (0);
}
+

+
int
+
split_chr(char *str, char sep)
+
{
+
	char *next;
+
	char *buf = str;
+
	int nbel = 0;
+

+
	while ((next = strchr(buf, sep)) != NULL) {
+
		nbel++;
+
		buf = next;
+
		buf[0] = '\0';
+
		buf++;
+
	}
+

+
	return nbel;
+
}
modified libpkg/util.h
@@ -10,6 +10,8 @@ struct array {
	void **data;
};

+
#define STARTS_WITH(string, needle) (strncasecmp(string, needle, strlen(needle)) == 0)
+

void array_init(struct array *, size_t);
void array_append(struct array *, void *);
void array_reset(struct array *, void (*free_elm)(void*));
@@ -18,5 +20,6 @@ void array_free(struct array *, void (*free_elm)(void*));
off_t file_to_buffer(const char *path, char **buffer);
char *str_replace(char *string, const char *find, char *replace);
int select_dir(const struct dirent *);
+
int split_chr(char *, char);

#endif
modified pkg/Makefile
@@ -1,8 +1,8 @@
PROG=	pkg
SRCS=	main.c \
	info.c \
-
	create.c \
-
	which.c
+
	which.c \
+
	register.c

CFLAGS+=	-I${.CURDIR}/../libpkg -I${.CURDIR}/../external/tinycdb/
LDADD+=	-L${.CURDIR}/../external -L../libpkg -lpkg -lutil
modified pkg/info.c
@@ -33,6 +33,35 @@ pkg_size(struct pkg *pkg)
	return (size);
}

+
static int
+
query_pkg(struct pkg *pkg, unsigned char opt) {
+
	struct pkg **deps;
+
	struct pkg_file **files;
+
	int i;
+

+
	if (opt & INFO_PRINT_DEP) {
+
		printf("%s-%s depends on: \n", pkg_name(pkg), pkg_version(pkg));
+
		deps = pkg_deps(pkg);
+
		for (i = 0; deps[i] != NULL; i++) {
+
			printf("%s-%s\n", pkg_name(deps[i]), pkg_version(deps[i]));
+
		}
+
		printf("\n");
+
	} else if (opt & INFO_LIST_FILES) {
+
		printf("%s-%s owns the following files:\n", pkg_name(pkg), pkg_version(pkg));
+
		files = pkg_files(pkg);
+

+
		for (i = 0; files[i] != NULL; i++) {
+
			printf("%s\n", pkg_file_path(files[i]));
+
		}
+
	} else {
+
		printf("%s-%s: %s\n", pkg_name(pkg), pkg_version(pkg), pkg_comment(pkg));
+
	}
+

+
	pkg_free(pkg);
+

+
	return (0);
+
}
+

void
usage_info(void)
{
@@ -100,6 +129,10 @@ exec_info(int argc, char **argv)
	if (argc == 0)
		match = MATCH_ALL;

+
	/* if the last argument is a file then query directly the file */
+
	if (pkg_open(argv[0], &pkg, query_flags) == 0)
+
		return (query_pkg(pkg, opt));
+

	if (pkgdb_open(&db) == -1) {
		pkgdb_warn(db);
		return (-1);
modified pkg/main.c
@@ -19,7 +19,7 @@ static struct commands {
	void (*usage)(void);
} cmd[] = { 
	{ "add", NULL, NULL},
-
	{ "create", exec_create, usage_create},
+
	{ "create", NULL, NULL},
	{ "delete", NULL, NULL},
	{ "info", exec_info, usage_info},
	{ "install", NULL, NULL},