Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
This is better if diff are not omitted
Baptiste Daroussin committed 15 years ago
commit 7f3adc899bd3507e5b5230b9d56738df29dfd43c
parent d8c1981
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},