Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge remote branch 'pkgng/master'
Will Andrews committed 14 years ago
commit c712e8455c1e9472c6aa8106929edad5cbe73599
parent 444ea24
9 files changed +339 -294
modified .gitignore
@@ -7,6 +7,8 @@
*.core
*.gmon
*.log
+
*.gz
pkg/pkg
+
pkg2legacy
tests/test
docs/html/*
modified libpkg/Makefile
@@ -20,6 +20,7 @@ SRCS= pkg.c \
		pkg_option.c \
		pkg_ports.c \
		pkg_repo.c \
+
		pkg_create_repo.c \
		pkg_util.c \
		pkg_version.c \
		pkgdb.c \
modified libpkg/pkg.c
@@ -406,8 +406,9 @@ pkg_new(struct pkg **pkg)
		{PKG_MAINTAINER, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
		{PKG_WWW, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 1},
		{PKG_PREFIX, PKG_FILE|PKG_REMOTE|PKG_INSTALLED|PKG_UPGRADE, 0},
+
		{PKG_REPOPATH, PKG_REMOTE|PKG_UPGRADE, 0},
+
		{PKG_CKSUM, PKG_REMOTE|PKG_UPGRADE, 0},
		{PKG_NEWVERSION, PKG_UPGRADE, 0},
-
		{PKG_NEWPATH, PKG_UPGRADE, 0}
	};

	for (int i = 0; i < PKG_NUM_FIELDS; i++) {
modified libpkg/pkg.h
@@ -97,8 +97,9 @@ typedef enum {
	PKG_MAINTAINER,
	PKG_WWW,
	PKG_PREFIX,
+
	PKG_REPOPATH,
+
	PKG_CKSUM,
	PKG_NEWVERSION,
-
	PKG_NEWPATH
} pkg_attr;

/**
@@ -153,9 +154,12 @@ typedef enum {
	EPKG_DEPENDENCY,
} pkg_error_t;

-
#define PKG_LT -1
-
#define PKG_EQ 0
-
#define PKG_GT 1
+
/**
+
 * A function used as a callback by functions which fetch files from the
+
 * network.
+
 */
+
typedef void (*fetch_cb)(void *data, const char *url, off_t total, off_t done,
+
						 time_t elapsed);

/**
 * Allocate a new pkg.
@@ -182,7 +186,6 @@ void pkg_free(struct pkg *);
 */
int pkg_open(struct pkg **p, const char *path);

-

/**
 * @return the type of the package.
 * @warning returns PKG_NONE on error.
@@ -202,12 +205,12 @@ const char *pkg_get(struct pkg const * const , const pkg_attr);
int64_t pkg_flatsize(struct pkg *);

/**
-
 * @return the size of the uncompressed package, in its futur version.
+
 * @return the size of the uncompressed new package (PKG_UPGRADE).
 */
int64_t pkg_new_flatsize(struct pkg *);

/**
-
 * @return the size of the compressed package, in its futur version.
+
 * @return the size of the compressed new package (PKG_UPGRADE).
 */
int64_t pkg_new_pkgsize(struct pkg *);

@@ -488,7 +491,9 @@ int pkgdb_compact(struct pkgdb *db);

/**
 * Install and register a new package.
+
 * @param db An opened pkgdb
 * @param path The path to the package archive file on the local disk
+
 * @param pkg A pointer to pkg pointer (allocates a new pkg).
 * @return An error code.
 */
int pkg_add(struct pkgdb *db, const char *path, struct pkg **pkg);
@@ -510,12 +515,16 @@ int pkg_create_fakeroot(const char *, pkg_formats, const char *, const char *);

/**
 * Remove and unregister the package.
+
 * @param pkg An installed package to delete
+
 * @param db An opened pkgdb
 * @param force If set to one, the function will not fail if the package is
 * required by other packages.
 * @return An error code.
 */
int pkg_delete(struct pkg *pkg, struct pkgdb *db, int force);

+
int pkg_repo_fetch(struct pkg *pkg, void *data, fetch_cb cb);
+

/**
 * These functions are helpers for specific parts of pkg_delete().
 * Generally speaking, external consumers should not use these.
@@ -537,17 +546,11 @@ const char * pkg_config(const char *key);
int pkg_version_cmp(const char * const , const char * const);

/**
-
 * A function used as a callback by functions which fetch files from the
-
 * network.
-
 */
-
typedef void (*fetch_cb)(void *data, const char *url, off_t total, off_t done,
-
						 time_t elapsed);
-

-
/**
 * Fetch a file.
 * @return An error code.
 */
int pkg_fetch_file(const char *url, const char *dest, void *data, fetch_cb cb);
+

/**
 * Fetch to a given buffer
 * @return An error code
@@ -577,9 +580,8 @@ const char * pkg_error_string(void);
void pkg_error_warn(const char *fmt, ...);

/**
-
 * TODO
+
 * @todo Document
 */
int pkg_copy_tree(struct pkg *, const char *src, const char *dest);

-

#endif
modified libpkg/pkg_config.c
@@ -18,6 +18,7 @@ struct _config {
} c[] = {
	{ "PACKAGESITE", NULL, NULL},
	{ "PKG_DBDIR", "/var/db/pkg", NULL},
+
	{ "PKG_CACHEDIR", "/var/lib/pkg", NULL},
	{ NULL, NULL, NULL}
};

added libpkg/pkg_create_repo.c
@@ -0,0 +1,290 @@
+
#include <sys/types.h>
+
#include <sys/stat.h>
+

+
#include <errno.h>
+
#include <fnmatch.h>
+
#include <sqlite3.h>
+
#include <fts.h>
+
#include <unistd.h>
+
#include <stdio.h>
+
#include <string.h>
+

+
#include <openssl/rsa.h>
+
#include <openssl/err.h>
+
#include <openssl/ssl.h>
+

+
#include "pkg.h"
+
#include "pkg_error.h"
+
#include "pkg_private.h"
+
#include "pkg_util.h"
+

+
int
+
pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *data)
+
{
+
	FTS *fts = NULL;
+
	FTSENT *ent = NULL;
+

+
	struct stat st;
+
	struct pkg *pkg = NULL;
+
	struct pkg **deps;
+
	char *ext = NULL;
+
	sqlite3 *sqlite = NULL;
+
	sqlite3_stmt *stmt_deps = NULL;
+
	sqlite3_stmt *stmt_pkg = NULL;
+
	int64_t package_id;
+
	char *errmsg = NULL;
+
	int retcode = EPKG_OK;
+
	char *pkg_path;
+
	char sum[65];
+

+
	int i;
+

+
	char *repopath[2];
+
	char repodb[MAXPATHLEN];
+

+
	const char initsql[] = ""
+
		"CREATE TABLE packages ("
+
			"id INTEGER PRIMARY KEY,"
+
			"origin TEXT UNIQUE,"
+
			"name TEXT,"
+
			"version TEXT,"
+
			"comment TEXT,"
+
			"desc TEXT,"
+
			"arch TEXT,"
+
			"osversion TEXT,"
+
			"maintainer TEXT,"
+
			"www TEXT,"
+
			"pkg_format_version INTEGER,"
+
			"pkgsize INTEGER,"
+
			"flatsize INTEGER,"
+
			"sum TEXT,"
+
			"path TEXT NOT NULL" /* relative path to the package in the repository */
+
		");"
+
		"CREATE TABLE deps ("
+
			"origin TEXT,"
+
			"name TEXT,"
+
			"version TEXT,"
+
			"package_id INTEGER REFERENCES packages(id),"
+
			"PRIMARY KEY (package_id, origin)"
+
		");"
+
		"CREATE INDEX deps_origin ON deps (origin);"
+
		"CREATE INDEX deps_package ON deps (package_id);";
+
	const char pkgsql[] = ""
+
		"INSERT INTO packages ("
+
				"origin, name, version, comment, desc, arch, osversion, "
+
				"maintainer, www, pkg_format_version, pkgsize, flatsize, "
+
				"sum, path"
+
		")"
+
		"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14);";
+
	const char depssql[] = ""
+
		"INSERT INTO deps (origin, name, version, package_id) "
+
		"VALUES (?1, ?2, ?3, ?4);";
+

+
	if (!is_dir(path))
+
		return (pkg_error_set(EPKG_FATAL, "%s is not a directory", path));
+

+
	repopath[0] = path;
+
	repopath[1] = NULL;
+

+
	snprintf(repodb, MAXPATHLEN, "%s/repo.sqlite", path);
+

+
	if (stat(repodb, &st) != -1)
+
		if (unlink(repodb) != 0)
+
			return (pkg_error_set(EPKG_FATAL, "can not unlink %s: %s", repodb,
+
								  strerror(errno)));
+

+
	if (sqlite3_open(repodb, &sqlite) != SQLITE_OK)
+
		return (EPKG_FATAL);
+

+
	if (sqlite3_exec(sqlite, initsql, NULL, NULL, &errmsg) != SQLITE_OK) {
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
		goto cleanup;
+
	}
+

+
	if (sqlite3_exec(sqlite, "BEGIN TRANSACTION;", NULL, NULL, &errmsg) !=
+
		SQLITE_OK) {
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+
		goto cleanup;
+
	}
+

+
	if (sqlite3_prepare(sqlite, pkgsql, -1, &stmt_pkg, NULL) != SQLITE_OK) {
+
		retcode = ERROR_SQLITE(sqlite);
+
		goto cleanup;
+
	}
+

+
	if (sqlite3_prepare(sqlite, depssql, -1, &stmt_deps, NULL) != SQLITE_OK) {
+
		retcode = ERROR_SQLITE(sqlite);
+
		goto cleanup;
+
	}
+

+
	if ((fts = fts_open(repopath, FTS_PHYSICAL, NULL)) == NULL) {
+
		retcode = pkg_error_set(EPKG_FATAL, "can not open %s: %s", repopath,
+
								strerror(errno));
+
		goto cleanup;
+
	}
+

+
	while ((ent = fts_read(fts)) != NULL) {
+
		sum[0] = '\0';
+
		/* skip everything that is not a file */
+
		if (ent->fts_info != FTS_F)
+
			continue;
+

+
		ext = strrchr(ent->fts_name, '.');
+

+
		if (ext == NULL)
+
			continue;
+

+
		if (strcmp(ext, ".tgz") != 0 &&
+
				strcmp(ext, ".tbz") != 0 &&
+
				strcmp(ext, ".txz") != 0 &&
+
				strcmp(ext, ".tar") != 0)
+
			continue;
+

+
		pkg_path = ent->fts_path;
+
		pkg_path += strlen(path);
+
		while (pkg_path[0] == '/' )
+
			pkg_path++;
+

+
		if (pkg_open(&pkg, ent->fts_accpath) != EPKG_OK) {
+
			if (progress != NULL) {
+
				pkg_error_set(EPKG_WARN, "can not open %s: %s", ent->fts_name,
+
							  pkg_error_string());
+
				progress(NULL, data);
+
			}
+
			continue;
+
		}
+

+
		if (progress != NULL)
+
			progress(pkg, data);
+

+
		sqlite3_bind_text(stmt_pkg, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 2, pkg_get(pkg, PKG_NAME), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 3, pkg_get(pkg, PKG_VERSION), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 4, pkg_get(pkg, PKG_COMMENT), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 5, pkg_get(pkg, PKG_DESC), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 6, pkg_get(pkg, PKG_ARCH), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 7, pkg_get(pkg, PKG_OSVERSION), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 8, pkg_get(pkg, PKG_MAINTAINER), -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 9, pkg_get(pkg, PKG_WWW), -1, SQLITE_STATIC);
+
		sqlite3_bind_int64(stmt_pkg, 11, ent->fts_statp->st_size);
+
		sqlite3_bind_int64(stmt_pkg, 12, pkg_flatsize(pkg));
+
		sha256_file(ent->fts_accpath, sum);
+
		sqlite3_bind_text(stmt_pkg, 13, sum, -1, SQLITE_STATIC);
+
		sqlite3_bind_text(stmt_pkg, 14, pkg_path, -1, SQLITE_STATIC);
+

+
		if (sqlite3_step(stmt_pkg) != SQLITE_DONE) {
+
			retcode = ERROR_SQLITE(sqlite);
+
			goto cleanup;
+
		}
+
		sqlite3_reset(stmt_pkg);
+

+
		package_id = sqlite3_last_insert_rowid(sqlite);
+

+
		deps = pkg_deps(pkg);
+
		for (i = 0; deps[i] != NULL; i++) {
+
			sqlite3_bind_text(stmt_deps, 1, pkg_get(deps[i], PKG_ORIGIN), -1, SQLITE_STATIC);
+
			sqlite3_bind_text(stmt_deps, 2, pkg_get(deps[i], PKG_NAME), -1, SQLITE_STATIC);
+
			sqlite3_bind_text(stmt_deps, 3, pkg_get(deps[i], PKG_VERSION), -1, SQLITE_STATIC);
+
			sqlite3_bind_int64(stmt_deps, 4, package_id);
+

+
			if (sqlite3_step(stmt_deps) != SQLITE_DONE) {
+
				retcode = ERROR_SQLITE(sqlite);
+
				goto cleanup;
+
			}
+
			sqlite3_reset(stmt_deps);
+
		}
+

+
	}
+
		sum[0] = '\0';
+

+
	if (sqlite3_exec(sqlite, "COMMIT;", NULL, NULL, &errmsg) != SQLITE_OK)
+
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
+

+
	cleanup:
+
	if (fts != NULL)
+
		fts_close(fts);
+

+
	if (pkg != NULL)
+
		pkg_free(pkg);
+

+
	if (stmt_pkg != NULL)
+
		sqlite3_finalize(stmt_pkg);
+

+
	if (stmt_deps != NULL)
+
		sqlite3_finalize(stmt_deps);
+

+
	if (sqlite != NULL)
+
		sqlite3_close(sqlite);
+

+
	if (errmsg != NULL)
+
		sqlite3_free(errmsg);
+

+
	return (retcode);
+
}
+

+
static RSA *
+
load_rsa_private_key(char *rsa_key_path, pem_password_cb *password_cb)
+
{
+
	FILE *fp;
+
	RSA *rsa = NULL;
+

+
	if ((fp = fopen(rsa_key_path, "r")) == 0)
+
		return (NULL);
+

+
	if ((rsa = RSA_new()) == NULL) {
+
		fclose(fp);
+
		return (NULL);
+
	}
+

+
	if ((rsa = PEM_read_RSAPrivateKey(fp, 0, password_cb, rsa_key_path)) == NULL) {
+
		fclose(fp);
+
		return (NULL);
+
	}
+

+
	fclose(fp);
+
	return (rsa);
+
}
+

+
int
+
pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path)
+
{
+
	char repo_path[MAXPATHLEN];
+
	char repo_archive[MAXPATHLEN];
+
	struct packing *pack;
+
	int max_len = 0;
+
	unsigned char *sigret = NULL;
+
	int siglen = 0;
+
	RSA *rsa = NULL;
+
	char sha256[65];
+

+
	snprintf(repo_path, MAXPATHLEN, "%s/repo.sqlite", path);
+
	snprintf(repo_archive, MAXPATHLEN, "%s/repo", path);
+

+
	packing_init(&pack, repo_archive, TXZ);
+
	if (rsa_key_path != NULL) {
+
		SSL_load_error_strings();
+

+
		OpenSSL_add_all_algorithms();
+
		OpenSSL_add_all_ciphers();
+

+
		rsa = load_rsa_private_key(rsa_key_path, password_cb);
+
		max_len = RSA_size(rsa);
+
		sigret = malloc(max_len + 1);
+
		memset(sigret, 0, max_len);
+

+
		sha256_file(repo_path, sha256);
+

+
		if (RSA_sign(NID_sha1, sha256, 65, sigret, &siglen, rsa) == 0)
+
			return pkg_error_set(EPKG_FATAL, "Unable to sign the repository");
+

+
		packing_append_buffer(pack, sigret, "signature", max_len);
+

+
		free(sigret);
+
		RSA_free(rsa);
+
		ERR_free_strings();
+
	}
+
	packing_append_file(pack, repo_path, "repo.sqlite");
+
	packing_finish(pack);
+

+
	return (EPKG_OK);
+
}
modified libpkg/pkg_private.h
@@ -9,7 +9,7 @@

#include "pkg_util.h"

-
#define PKG_NUM_FIELDS 14
+
#define PKG_NUM_FIELDS 15

#define EXTRACT_ARCHIVE_FLAGS  (ARCHIVE_EXTRACT_OWNER |ARCHIVE_EXTRACT_PERM| \
		ARCHIVE_EXTRACT_TIME  |ARCHIVE_EXTRACT_ACL | \
modified libpkg/pkg_repo.c
@@ -1,290 +1,38 @@
-
#include <sys/types.h>
-
#include <sys/stat.h>
-

-
#include <errno.h>
-
#include <fnmatch.h>
-
#include <sqlite3.h>
-
#include <fts.h>
-
#include <unistd.h>
-
#include <stdio.h>
#include <string.h>
-

-
#include <openssl/rsa.h>
-
#include <openssl/err.h>
-
#include <openssl/ssl.h>
+
#include <unistd.h>

#include "pkg.h"
#include "pkg_error.h"
#include "pkg_private.h"
-
#include "pkg_util.h"

int
-
pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *data)
+
pkg_repo_fetch(struct pkg *pkg, void *data, fetch_cb cb)
{
-
	FTS *fts = NULL;
-
	FTSENT *ent = NULL;
-

-
	struct stat st;
-
	struct pkg *pkg = NULL;
-
	struct pkg **deps;
-
	char *ext = NULL;
-
	sqlite3 *sqlite = NULL;
-
	sqlite3_stmt *stmt_deps = NULL;
-
	sqlite3_stmt *stmt_pkg = NULL;
-
	int64_t package_id;
-
	char *errmsg = NULL;
+
	char dest[MAXPATHLEN];
+
	char cksum[65];
+
	char *url;
	int retcode = EPKG_OK;
-
	char *pkg_path;
-
	char sum[65];
-

-
	int i;
-

-
	char *repopath[2];
-
	char repodb[MAXPATHLEN];
-

-
	const char initsql[] = ""
-
		"CREATE TABLE packages ("
-
			"id INTEGER PRIMARY KEY,"
-
			"origin TEXT UNIQUE,"
-
			"name TEXT,"
-
			"version TEXT,"
-
			"comment TEXT,"
-
			"desc TEXT,"
-
			"arch TEXT,"
-
			"osversion TEXT,"
-
			"maintainer TEXT,"
-
			"www TEXT,"
-
			"pkg_format_version INTEGER,"
-
			"pkgsize INTEGER,"
-
			"flatsize INTEGER,"
-
			"sum TEXT,"
-
			"path TEXT NOT NULL" /* relative path to the package in the repository */
-
		");"
-
		"CREATE TABLE deps ("
-
			"origin TEXT,"
-
			"name TEXT,"
-
			"version TEXT,"
-
			"package_id INTEGER REFERENCES packages(id),"
-
			"PRIMARY KEY (package_id, origin)"
-
		");"
-
		"CREATE INDEX deps_origin ON deps (origin);"
-
		"CREATE INDEX deps_package ON deps (package_id);";
-
	const char pkgsql[] = ""
-
		"INSERT INTO packages ("
-
				"origin, name, version, comment, desc, arch, osversion, "
-
				"maintainer, www, pkg_format_version, pkgsize, flatsize, "
-
				"sum, path"
-
		")"
-
		"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14);";
-
	const char depssql[] = ""
-
		"INSERT INTO deps (origin, name, version, package_id) "
-
		"VALUES (?1, ?2, ?3, ?4);";
-

-
	if (!is_dir(path))
-
		return (pkg_error_set(EPKG_FATAL, "%s is not a directory", path));
-

-
	repopath[0] = path;
-
	repopath[1] = NULL;
-

-
	snprintf(repodb, MAXPATHLEN, "%s/repo.sqlite", path);
-

-
	if (stat(repodb, &st) != -1)
-
		if (unlink(repodb) != 0)
-
			return (pkg_error_set(EPKG_FATAL, "can not unlink %s: %s", repodb,
-
								  strerror(errno)));
-

-
	if (sqlite3_open(repodb, &sqlite) != SQLITE_OK)
-
		return (EPKG_FATAL);
-

-
	if (sqlite3_exec(sqlite, initsql, NULL, NULL, &errmsg) != SQLITE_OK) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
-
		goto cleanup;
-
	}
-

-
	if (sqlite3_exec(sqlite, "BEGIN TRANSACTION;", NULL, NULL, &errmsg) !=
-
		SQLITE_OK) {
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
-
		goto cleanup;
-
	}
-

-
	if (sqlite3_prepare(sqlite, pkgsql, -1, &stmt_pkg, NULL) != SQLITE_OK) {
-
		retcode = ERROR_SQLITE(sqlite);
-
		goto cleanup;
-
	}
-

-
	if (sqlite3_prepare(sqlite, depssql, -1, &stmt_deps, NULL) != SQLITE_OK) {
-
		retcode = ERROR_SQLITE(sqlite);
-
		goto cleanup;
-
	}
-

-
	if ((fts = fts_open(repopath, FTS_PHYSICAL, NULL)) == NULL) {
-
		retcode = pkg_error_set(EPKG_FATAL, "can not open %s: %s", repopath,
-
								strerror(errno));
-
		goto cleanup;
-
	}
-

-
	while ((ent = fts_read(fts)) != NULL) {
-
		sum[0] = '\0';
-
		/* skip everything that is not a file */
-
		if (ent->fts_info != FTS_F)
-
			continue;
-

-
		ext = strrchr(ent->fts_name, '.');
-

-
		if (ext == NULL)
-
			continue;
-

-
		if (strcmp(ext, ".tgz") != 0 &&
-
				strcmp(ext, ".tbz") != 0 &&
-
				strcmp(ext, ".txz") != 0 &&
-
				strcmp(ext, ".tar") != 0)
-
			continue;
-

-
		pkg_path = ent->fts_path;
-
		pkg_path += strlen(path);
-
		while (pkg_path[0] == '/' )
-
			pkg_path++;
-

-
		if (pkg_open(&pkg, ent->fts_accpath) != EPKG_OK) {
-
			if (progress != NULL) {
-
				pkg_error_set(EPKG_WARN, "can not open %s: %s", ent->fts_name,
-
							  pkg_error_string());
-
				progress(NULL, data);
-
			}
-
			continue;
-
		}
-

-
		if (progress != NULL)
-
			progress(pkg, data);
-

-
		sqlite3_bind_text(stmt_pkg, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 2, pkg_get(pkg, PKG_NAME), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 3, pkg_get(pkg, PKG_VERSION), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 4, pkg_get(pkg, PKG_COMMENT), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 5, pkg_get(pkg, PKG_DESC), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 6, pkg_get(pkg, PKG_ARCH), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 7, pkg_get(pkg, PKG_OSVERSION), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 8, pkg_get(pkg, PKG_MAINTAINER), -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 9, pkg_get(pkg, PKG_WWW), -1, SQLITE_STATIC);
-
		sqlite3_bind_int64(stmt_pkg, 11, ent->fts_statp->st_size);
-
		sqlite3_bind_int64(stmt_pkg, 12, pkg_flatsize(pkg));
-
		sha256_file(ent->fts_accpath, sum);
-
		sqlite3_bind_text(stmt_pkg, 13, sum, -1, SQLITE_STATIC);
-
		sqlite3_bind_text(stmt_pkg, 14, pkg_path, -1, SQLITE_STATIC);
-

-
		if (sqlite3_step(stmt_pkg) != SQLITE_DONE) {
-
			retcode = ERROR_SQLITE(sqlite);
-
			goto cleanup;
-
		}
-
		sqlite3_reset(stmt_pkg);

-
		package_id = sqlite3_last_insert_rowid(sqlite);
+
	if ((pkg->type & PKG_REMOTE) != PKG_REMOTE)
+
		return (ERROR_BAD_ARG("pkg"));

-
		deps = pkg_deps(pkg);
-
		for (i = 0; deps[i] != NULL; i++) {
-
			sqlite3_bind_text(stmt_deps, 1, pkg_get(deps[i], PKG_ORIGIN), -1, SQLITE_STATIC);
-
			sqlite3_bind_text(stmt_deps, 2, pkg_get(deps[i], PKG_NAME), -1, SQLITE_STATIC);
-
			sqlite3_bind_text(stmt_deps, 3, pkg_get(deps[i], PKG_VERSION), -1, SQLITE_STATIC);
-
			sqlite3_bind_int64(stmt_deps, 4, package_id);
+
	snprintf(dest, sizeof(dest), "%s/%s", pkg_config("PKG_CACHEDIR"),
+
			 pkg_get(pkg, PKG_REPOPATH));

-
			if (sqlite3_step(stmt_deps) != SQLITE_DONE) {
-
				retcode = ERROR_SQLITE(sqlite);
-
				goto cleanup;
-
			}
-
			sqlite3_reset(stmt_deps);
-
		}
+
	/* If it is already in the local cachedir, dont bother to download it */
+
	if (access(dest, F_OK) == 0)
+
		goto checksum;

-
	}
-
		sum[0] = '\0';
+
	asprintf(&url, "%s/%s", pkg_config("PACKAGESITE"),
+
			 pkg_get(pkg, PKG_REPOPATH));
+
	pkg_fetch_file(url, dest, data, cb);
+
	free(url);

-
	if (sqlite3_exec(sqlite, "COMMIT;", NULL, NULL, &errmsg) != SQLITE_OK)
-
		retcode = pkg_error_set(EPKG_FATAL, "%s", errmsg);
-

-
	cleanup:
-
	if (fts != NULL)
-
		fts_close(fts);
-

-
	if (pkg != NULL)
-
		pkg_free(pkg);
-

-
	if (stmt_pkg != NULL)
-
		sqlite3_finalize(stmt_pkg);
-

-
	if (stmt_deps != NULL)
-
		sqlite3_finalize(stmt_deps);
-

-
	if (sqlite != NULL)
-
		sqlite3_close(sqlite);
-

-
	if (errmsg != NULL)
-
		sqlite3_free(errmsg);
+
	checksum:
+
	retcode = sha256_file(dest, cksum);
+
	if (retcode == EPKG_OK)
+
		if (strcmp(cksum, pkg_get(pkg, PKG_CKSUM)))
+
			retcode = pkg_error_set(EPKG_FATAL, "failed checksum");

	return (retcode);
}
-

-
static RSA *
-
load_rsa_private_key(char *rsa_key_path, pem_password_cb *password_cb)
-
{
-
	FILE *fp;
-
	RSA *rsa = NULL;
-

-
	if ((fp = fopen(rsa_key_path, "r")) == 0)
-
		return (NULL);
-

-
	if ((rsa = RSA_new()) == NULL) {
-
		fclose(fp);
-
		return (NULL);
-
	}
-

-
	if ((rsa = PEM_read_RSAPrivateKey(fp, 0, password_cb, rsa_key_path)) == NULL) {
-
		fclose(fp);
-
		return (NULL);
-
	}
-

-
	fclose(fp);
-
	return (rsa);
-
}
-

-
int
-
pkg_finish_repo(char *path, pem_password_cb *password_cb, char *rsa_key_path)
-
{
-
	char repo_path[MAXPATHLEN];
-
	char repo_archive[MAXPATHLEN];
-
	struct packing *pack;
-
	int max_len = 0;
-
	unsigned char *sigret = NULL;
-
	int siglen = 0;
-
	RSA *rsa = NULL;
-
	char sha256[65];
-

-
	snprintf(repo_path, MAXPATHLEN, "%s/repo.sqlite", path);
-
	snprintf(repo_archive, MAXPATHLEN, "%s/repo", path);
-

-
	packing_init(&pack, repo_archive, TXZ);
-
	if (rsa_key_path != NULL) {
-
		SSL_load_error_strings();
-

-
		OpenSSL_add_all_algorithms();
-
		OpenSSL_add_all_ciphers();
-

-
		rsa = load_rsa_private_key(rsa_key_path, password_cb);
-
		max_len = RSA_size(rsa);
-
		sigret = malloc(max_len + 1);
-
		memset(sigret, 0, max_len);
-

-
		sha256_file(repo_path, sha256);
-

-
		if (RSA_sign(NID_sha1, sha256, 65, sigret, &siglen, rsa) == 0)
-
			return pkg_error_set(EPKG_FATAL, "Unable to sign the repository");
-

-
		packing_append_buffer(pack, sigret, "signature", max_len);
-

-
		free(sigret);
-
		RSA_free(rsa);
-
		ERR_free_strings();
-
	}
-
	packing_append_file(pack, repo_path, "repo.sqlite");
-
	packing_finish(pack);
-

-
	return (EPKG_OK);
-
}
modified libpkg/pkgdb.c
@@ -95,13 +95,13 @@ pkgdb_pkgcmp(sqlite3_context *ctx, int argc, sqlite3_value **argv, int sign)
static void
pkgdb_pkglt(sqlite3_context *ctx, int argc, sqlite3_value **argv)
{
-
	pkgdb_pkgcmp(ctx, argc, argv, PKG_LT);
+
	pkgdb_pkgcmp(ctx, argc, argv, -1);
}

static void
pkgdb_pkggt(sqlite3_context *ctx, int argc, sqlite3_value **argv)
{
-
	pkgdb_pkgcmp(ctx, argc, argv, PKG_GT);
+
	pkgdb_pkgcmp(ctx, argc, argv, 1);
}

/*
@@ -360,7 +360,7 @@ pkgdb_it_next(struct pkgdb_it *it, struct pkg **pkg_p, int flags)
			pkg_set(pkg, PKG_NEWVERSION, sqlite3_column_text(it->stmt, 13));
			pkg_setnewflatsize(pkg, sqlite3_column_int64(it->stmt, 14));
			pkg_setnewpkgsize(pkg, sqlite3_column_int64(it->stmt, 15));
-
			pkg_set(pkg, PKG_NEWPATH, sqlite3_column_text(it->stmt, 16));
+
			pkg_set(pkg, PKG_URL, sqlite3_column_text(it->stmt, 16));
		}

		if (flags & PKG_LOAD_DEPS)