Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
API refactoring.
jlaffaye committed 15 years ago
commit 97c7fb7837499994323daa55734711a9dfde264a
parent 1a63530b2fcc65fff839c0c0b657ab64c3b6badc
7 files changed +129 -118
modified libpkg/pkg.c
@@ -214,10 +214,21 @@ pkg_conflicts(struct pkg *pkg)
}

int
-
pkg_open(const char *path, struct pkg **pkg_p)
+
pkg_open(struct pkg **pkg_p, const char *path)
{
	struct archive *a;
	struct archive_entry *ae;
+
	int retcode;
+

+
	retcode = pkg_open2(pkg_p, &a, &ae, path);
+

+
	archive_read_finish(a);
+
	return (retcode);
+
}
+

+
int
+
pkg_open2(struct pkg **pkg_p, struct archive **a, struct archive_entry **ae, const char *path)
+
{
	struct pkg *pkg;
	struct pkg_script *script;
	pkg_error_t retcode = EPKG_OK;
@@ -230,17 +241,9 @@ pkg_open(const char *path, struct pkg **pkg_p)
	if (path == NULL)
		return (ERROR_BAD_ARG("path"));

-
	/* search for http(s) or ftp(s) */
-
	if (STARTS_WITH(path, "http://") || STARTS_WITH(path, "https://")
-
			|| STARTS_WITH(path, "ftp://")) {
-
		/* TODO: */
-
		file_fetch(path, "/tmp/bla");
-
		path = "/tmp/bla";
-
	}
-

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

	if (*pkg_p == NULL)
		pkg_new(pkg_p);
@@ -249,29 +252,25 @@ pkg_open(const char *path, struct pkg **pkg_p)

	pkg = *pkg_p;
	pkg->type = PKG_FILE;
-
	pkg->path = path;

-
	if (archive_read_open_filename(a, path, 4096) != ARCHIVE_OK) {
-
		archive_read_finish(a);
-
		return (pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a)));
+
	if (archive_read_open_filename(*a, path, 4096) != ARCHIVE_OK) {
+
		archive_read_finish(*a);
+
		return (pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a)));
	}

-
	/* first path to check is the archive is corrupted bye the way retreive
-
	 * informations */
-

	array_init(&pkg->scripts, 10);
	array_init(&pkg->files, 10);

-
	while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
-
		fpath = archive_entry_pathname(ae);
+
	while ((ret = archive_read_next_header(*a, ae)) == ARCHIVE_OK) {
+
		fpath = archive_entry_pathname(*ae);

		if (fpath[0] != '+')
			break;

		if (strcmp(fpath, "+MANIFEST") == 0) {
-
			size = archive_entry_size(ae);
+
			size = archive_entry_size(*ae);
			manifest = calloc(1, size + 1);
-
			archive_read_data(a, manifest, size);
+
			archive_read_data(*a, manifest, size);
			ret = pkg_parse_manifest(pkg, manifest);
			free(manifest);
			if (ret != EPKG_OK) {
@@ -284,7 +283,7 @@ pkg_open(const char *path, struct pkg **pkg_p)
#define COPY_FILE(fname, dest)												\
	if (strcmp(fpath, fname) == 0) {										\
		dest = sbuf_new_auto();												\
-
		while ((size = archive_read_data(a, buf, sizeof(buf))) > 0 ) {		\
+
		while ((size = archive_read_data(*a, buf, sizeof(buf))) > 0 ) {		\
			sbuf_bcat(dest, buf, size);										\
		}																	\
		sbuf_finish(dest);													\
@@ -298,7 +297,7 @@ pkg_open(const char *path, struct pkg **pkg_p)
		pkg_script_new(&script);											\
		script->type = stype;												\
		script->data = sbuf_new_auto();										\
-
		while ((size = archive_read_data(a, buf, sizeof(buf))) > 0 ) {		\
+
		while ((size = archive_read_data(*a, buf, sizeof(buf))) > 0 ) {		\
			sbuf_bcat(script->data, buf, size);								\
		}																	\
		sbuf_finish(script->data);											\
@@ -317,10 +316,9 @@ pkg_open(const char *path, struct pkg **pkg_p)
	}

	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a));
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(*a));
	}

-
	archive_read_finish(a);
	return (retcode);
}

@@ -347,7 +345,6 @@ pkg_reset(struct pkg *pkg)

	pkg->flatsize = 0;
	pkg->flags = 0;
-
	pkg->path = NULL;

	array_reset(&pkg->deps, &pkg_free_void);
	array_reset(&pkg->rdeps, &pkg_free_void);
modified libpkg/pkg.h
@@ -47,7 +47,7 @@ typedef enum {
	 */
	PKG_FILE,
	/**
-
	 * The pkg refers to a package available of the remote repository.
+
	 * The pkg refers to a package available on the remote repository.
	 * @todo Document which attributes are available.
	 */
	PKG_REMOTE,
@@ -124,10 +124,20 @@ typedef enum {
	EPKG_WARNING,
	/**
	 * The function encountered a fatal error.
-
	 * errno was set to describe the error.
	 */
	EPKG_FATAL,
+
	/**
+
	 * Can not delete the package because it is required by another package.
+
	 */
	EPKG_REQUIRED,
+
	/**
+
	 * Can not install the package because it is already installed.
+
	 */
+
	EPKG_INSTALLED,
+
	/**
+
	 * Can not install the package because some dependencies are unresolved.
+
	 */
+
	EPKG_DEPENDENCY,
	EPKG_NOT_ORIGIN,
	EPKG_NOT_NAME,
} pkg_error_t;
@@ -150,13 +160,12 @@ void pkg_reset(struct pkg *);
void pkg_free(struct pkg *);

/**
-
 * Open a file archive.
-
 * @param path A local path or an URL.
+
 * Open a package file archive and retrive informations.
 * @param p A pointer to pkg allocated by pkg_new(), or if it points to a
 * NULL pointer, the function allocate a new pkg using pkg_new().
-
 * @param flags Unused.
+
 * @param path The path to the local package archive.
 */
-
int pkg_open(const char *path, struct pkg **p);
+
int pkg_open(struct pkg **p, const char *path);

pkg_t pkg_type(struct pkg *);

@@ -230,9 +239,10 @@ int pkg_resolvdeps(struct pkg *, struct pkgdb *db);
int pkg_analyse_files(struct pkgdb *, struct pkg *);

/**
-
 * add a new package this will check if upgrade is needed
+
 * Add a new package.
+
 * @param path The path to the package archive file on the local disk
 */
-
int pkg_add(struct pkgdb *, struct pkg *);
+
int pkg_add(struct pkgdb *, const char *path);

/**
 * Generic setter for simple attributes.
modified libpkg/pkg_add.c
@@ -11,54 +11,91 @@
		ARCHIVE_EXTRACT_FFLAGS|ARCHIVE_EXTRACT_XATTR)

static int
-
pkg_extract(const char *path)
+
extract(struct archive *a, struct archive_entry *ae)
{
-
	struct archive *a;
-
	struct archive_entry *ae;
-

+
	int retcode = EPKG_OK;
	int ret;

-
	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 (pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a)));
-
	}
-

-
	while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK) {
-
		if (archive_entry_pathname(ae)[0] == '+') {
-
			archive_read_data_skip(a);
-
		} else {
-
			archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS);
+
	do {
+
		if (archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS) != ARCHIVE_OK) {
+
			retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a));
+
			break;
		}
-
	}
+
	} while ((ret = archive_read_next_header(a, &ae)) == ARCHIVE_OK);

	if (ret != ARCHIVE_EOF)
-
		return (pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a)));
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", archive_error_string(a));

	archive_read_finish(a);

-
	return (EPKG_OK);
+
	return (retcode);
}

-
/* TODO: take a path to the package archive instead of a pkg */
int
-
pkg_add(struct pkgdb *db, struct pkg *pkg)
+
pkg_add(struct pkgdb *db, const char *path)
{
+
	struct archive *a;
+
	struct archive_entry *ae;
+
	struct pkgdb_it *it;
+
	struct pkg *pkg = NULL;
+
	struct pkg *p = NULL;
+
	struct pkg **deps;
	struct pkg_exec **execs;
	struct pkg_script **scripts;
	struct sbuf *script_cmd;
	int retcode = EPKG_OK;
+
	int ret;
	int i;

-
	if (pkg_type(pkg) != PKG_FILE || pkg->path == NULL)
-
		return (ERROR_BAD_ARG("pkg"));
+
	if (path == NULL)
+
		return (ERROR_BAD_ARG("path"));

+
	/*
+
	 * Open the package archive file, read all the meta files and set the
+
	 * current archive_entry to the first non-meta file.
+
	 */
+
	if ((retcode = pkg_open2(&pkg, &a, &ae, path)) != EPKG_OK)
+
		return (retcode);
+

+
	/*
+
	 * Check if the package is already installed
+
	 */
+
	it = pkgdb_query(db, pkg_get(pkg, PKG_ORIGIN), MATCH_EXACT);
+
	if (it == NULL) {
+
		retcode = EPKG_FATAL;
+
		goto error;
+
	}
+

+
	ret = pkgdb_it_next_pkg(it, &p, PKG_BASIC);
+
	pkgdb_it_free(it);
+
	pkg_free(p);
+

+
	if (ret == EPKG_OK) {
+
		retcode = pkg_error_set(EPKG_INSTALLED, "package already installed");
+
		goto error;
+
	} else if (ret != EPKG_END) {
+
		retcode = ret;
+
		goto error;
+
	}
+

+
	/*
+
	 * Check for dependencies
+
	 */
+
	pkg_resolvdeps(pkg, db);
+
	deps = pkg_deps(pkg);
+
	for (i = 0; deps[i] != NULL; i++)
+
		if (pkg_type(deps[i]) == PKG_NOTFOUND) {
+
			retcode = pkg_error_set(EPKG_DEPENDENCY, "unresolved %s-%s dependency",
+
								  pkg_get(deps[i], PKG_NAME),
+
								  pkg_get(deps[i], PKG_VERSION));
+
			goto error;
+
		}
+

+
	/*
+
	 * Execute pre-install scripts
+
	 */
	script_cmd = sbuf_new_auto();

-
	/* execute pre-install scripts */
	if ((scripts = pkg_scripts(pkg)) != NULL)
		for (i= 0; scripts[i] != NULL; i++) {
			switch (pkg_script_type(scripts[i])) {
@@ -80,10 +117,16 @@ pkg_add(struct pkgdb *db, struct pkg *pkg)
			}
		}

-
	if ((retcode = pkg_extract(pkg->path)) != EPKG_OK)
+
	/*
+
	 * Extract the files on disk.
+
	 */
+
	if ((retcode = extract(a, ae)) != EPKG_OK)
		return (retcode);
+
	a = NULL;

-
	/* execute post install scripts */
+
	/*
+
	 * Execute post install scripts
+
	 */
	if (scripts != NULL)
		for (i= 0; scripts[i] != NULL; i++) {
			switch (pkg_script_type(scripts[i])) {
@@ -107,12 +150,18 @@ pkg_add(struct pkgdb *db, struct pkg *pkg)

	sbuf_free(script_cmd);

-
	/* execute @exec */
+
	/*
+
	 * Execute @exec
+
	 */
	if ((execs = pkg_execs(pkg)) != NULL)
		for (i = 0; execs[i] != NULL; i++)
			if (pkg_exec_type(execs[i]) == PKG_EXEC)
				system(pkg_exec_cmd(execs[i]));

-

	return (pkgdb_register_pkg(db, pkg));
+

+
	error:
+
		if (a != NULL)
+
			archive_read_finish(a);
+
		return (retcode);
}
modified libpkg/pkg_private.h
@@ -5,6 +5,8 @@
#include <sys/types.h>
#include <sys/sbuf.h>

+
#include <archive.h>
+

#include "pkg_util.h"

#define PKG_NUM_FIELDS 12
@@ -22,7 +24,6 @@ struct pkg {
	struct array scripts;
	struct array exec;
	struct array options;
-
	const char *path; /* TODO: remove */
	int flags;
	pkg_t type;
};
@@ -57,4 +58,6 @@ void pkg_script_free_void(void *);
void pkg_exec_free_void(void *);
void pkg_option_free_void(void *);

+
int pkg_open2(struct pkg **p, struct archive **a, struct archive_entry **ae, const char *path);
+

#endif
modified libpkg/pkg_repo.c
@@ -101,7 +101,7 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
				strcmp(ext, ".tar") != 0)
			continue;

-
		if (pkg_open(ent->fts_path, &pkg) != EPKG_OK)
+
		if (pkg_open(&pkg, ent->fts_path) != EPKG_OK)
			continue;

		if (progress != NULL)
modified pkg/add.c
@@ -16,70 +16,22 @@ int
exec_add(int argc, char **argv)
{
	struct pkgdb *db;
-
	struct pkgdb_it *it;
-
	struct pkg *pkg = NULL;
-
	struct pkg *p;
-
	struct pkg **deps;
-
	int ret = 0;
-
	bool installed = false;
-
	int i;

	if (argc != 2) {
		usage_add();
		return (-1);
	}

-
	if (pkg_open(argv[1], &pkg) != EPKG_OK) {
-
		pkg_error_warn("can not open file %s", argv[1]);
-
		return (-1);
-
	}
-

	if (pkgdb_open(&db) != EPKG_OK) {
		pkg_error_warn("can not open database");
		pkgdb_close(db);
		return (-1);
	}

-
	/* TODO: all the following stuff should be into libpkg */
-

-
	/* check if already installed */
-
	if ((it = pkgdb_query(db, pkg_get(pkg, PKG_ORIGIN), MATCH_EXACT)) == NULL) {
-
		pkg_error_warn("can not query the database");
-
		return (-1);
-
	}
-

-
	pkg_new(&p);
-

-
	if (pkgdb_it_next_pkg(it, &p, PKG_BASIC) == EPKG_OK) {
-
		installed = true;
-
	}
-
	pkgdb_it_free(it);
-

-
	if (installed) {
-
		err(1, "%s is already installed\n", pkg_get(pkg, PKG_NAME));
-
	}
-

-
	deps = pkg_deps(pkg);
-
	if (deps != NULL) {
-
		pkg_resolvdeps(pkg, db);
-

-
		for (i = 0; deps[i] != NULL; i++) {
-
			if (pkg_type(deps[i]) == PKG_NOTFOUND) {
-
				warnx("%s-%s: unresolved dependency %s-%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), pkg_get(deps[i], PKG_NAME), pkg_get(deps[i], PKG_VERSION));
-
				ret = 1;
-
			}
-
		}
-
	}
-

-
	if (ret != 0) {
-
		return (ret);
-
	}
-

-
	if (pkg_add(db, pkg) != EPKG_OK)
+
	if (pkg_add(db, argv[1]) != EPKG_OK)
		pkg_error_warn("can not install %s", argv[1]);

	pkgdb_close(db);
-
	pkg_free(pkg);

	return (0);
}
modified pkg/info.c
@@ -126,7 +126,7 @@ exec_info(int argc, char **argv)

	/* if the last argument is a file then query directly the file */
	if (argc == 1 && access(argv[0], F_OK) == 0) {
-
		if (pkg_open(argv[0], &pkg) != EPKG_OK) {
+
		if (pkg_open(&pkg, argv[0]) != EPKG_OK) {
			warnx("can not read package %s", argv[0]);
			return (-1);
		}