Radish alpha
H
HardenedBSD Package Manager
Radicle
Git (anonymous pull)
Log in to clone via SSH
Modified manifest format and database schema.
jlaffaye committed 15 years ago
commit b08c33e65c19ab1ae975460febbcb1353a868443
parent e3e53dc8df186da1e6043c832378b3932823ef5a
13 files changed +183 -77
modified docs/TODO
@@ -26,12 +26,15 @@ subcommands:
	  considering the files are already installed

- genrepo:
-
	- takes only one argument and generate two cache files (maybe more for
+
	- takes only one argument and generate two databases files (maybe more for
	  the time we will be willing to work with UPDATING and MOVED) the first
	  repo contain every informations concerning a package except files
	  (which will be in the second one) + it will compute and add a sha256
-
	  sum for each package. the cache will be in tcdb format compressed in
-
	  xz format.
+
	  sum for each package.
+
	  the database will be a sqlite file compressed with the xz format.
+
	  the database will be signed so we can trust the sha256 of the
+
	  packages, so if a package has the expected hash, it is considered
+
	  trusted.

- search:
	- will search both the remote repository to gives informations
modified libpkg/pkg.c
@@ -130,6 +130,15 @@ pkg_set_from_file(struct pkg *pkg, pkg_attr attr, const char *path)
	return (ret);
}

+
int64_t
+
pkg_flatsize(struct pkg *pkg)
+
{
+
	if (pkg == NULL)
+
		return (-1);
+

+
	return (pkg->flatsize);
+
}
+

struct pkg_script **
pkg_scripts(struct pkg *pkg)
{
@@ -227,7 +236,6 @@ pkg_open(const char *path, struct pkg **pkg_p, int query_flags)
	struct archive_entry *ae;
	struct pkg *pkg;
	struct pkg_script *script;
-
	struct pkg_file *file = NULL;
	int ret;
	int64_t size;
	char *manifest;
@@ -272,12 +280,17 @@ pkg_open(const char *path, struct pkg **pkg_p, int query_flags)
	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);
			manifest = calloc(1, size + 1);
			archive_read_data(a, manifest, size);
-
			pkg_parse_manifest(pkg, manifest);
+
			ret = pkg_parse_manifest(pkg, manifest);
			free(manifest);
+
			if (ret != EPKG_OK)
+
				goto error;
		}

#define COPY_FILE(fname, dest)												\
@@ -313,18 +326,12 @@ pkg_open(const char *path, struct pkg **pkg_p, int query_flags)
		COPY_SCRIPT("+INSTALL", PKG_SCRIPT_INSTALL)
		COPY_SCRIPT("+DEINSTALL", PKG_SCRIPT_DEINSTALL)
		COPY_SCRIPT("+UPGRADE", PKG_SCRIPT_UPGRADE)
-

-
		if (fpath[0] == '+')
-
			continue;
-

-
		pkg_file_new(&file);
-
		strlcpy(file->path, archive_entry_pathname(ae), sizeof(file->path));
-
		file->size = archive_entry_size(ae);
-
		array_append(&pkg->files, file);
	}

-
	if (ret != ARCHIVE_EOF)
+
	if (ret != ARCHIVE_OK && ret != ARCHIVE_EOF) {
+
		warnx("libarchive: %s", archive_error_string(a));
		goto error;
+
	}

	archive_read_finish(a);
	return (EPKG_OK);
@@ -341,8 +348,6 @@ pkg_new(struct pkg **pkg)
	if ((*pkg = calloc(1, sizeof(struct pkg))) == NULL)
		err(EXIT_FAILURE, "calloc()");

-
	(*pkg)->path = NULL;
-

	return (EPKG_OK);
}

@@ -365,6 +370,9 @@ pkg_reset(struct pkg *pkg)
	sbuf_reset(pkg->www);
	sbuf_reset(pkg->prefix);

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

	array_reset(&pkg->deps, &pkg_free_void);
	array_reset(&pkg->rdeps, &pkg_free_void);
	array_reset(&pkg->conflicts, &pkg_conflict_free_void);
@@ -412,6 +420,19 @@ pkg_free_void(void *p)
}

int
+
pkg_setflatsize(struct pkg *pkg, int64_t size)
+
{
+
	if (pkg == NULL)
+
		return (EPKG_NULL_PKG);
+

+
	if (size <= 0)
+
		return (EPKG_FATAL);
+

+
	pkg->flatsize = size;
+
	return (EPKG_OK);
+
}
+

+
int
pkg_addscript(struct pkg *pkg, const char *path)
{
	struct pkg_script *script;
@@ -535,7 +556,7 @@ pkg_adddep(struct pkg *pkg, const char *name, const char *origin, const char *ve
}

int
-
pkg_addfile(struct pkg *pkg, const char *path, const char *sha256, int64_t sz)
+
pkg_addfile(struct pkg *pkg, const char *path, const char *sha256)
{
	struct pkg_file *file;

@@ -552,8 +573,6 @@ pkg_addfile(struct pkg *pkg, const char *path, const char *sha256, int64_t sz)
	if (sha256 != NULL)
		strlcpy(file->sha256, sha256, sizeof(file->sha256));

-
	file->size = sz;
-

	array_init(&pkg->files, 10);
	array_append(&pkg->files, file);

modified libpkg/pkg.h
@@ -167,6 +167,8 @@ void pkg_free(struct pkg *);
 */
int pkg_open(const char *path, struct pkg **p, int flags);

+
pkg_t pkg_type(struct pkg *);
+

/**
 * Generic getter for simple attributes.
 * @return NULL-terminated string.
@@ -174,7 +176,10 @@ int pkg_open(const char *path, struct pkg **p, int flags);
 */
const char *pkg_get(struct pkg *, pkg_attr);

-
pkg_t pkg_type(struct pkg *);
+
/**
+
 * Returns the size of the uncompressed package.
+
 */
+
int64_t pkg_flatsize(struct pkg *);

/**
 * @return NULL-terminated array of pkg.
@@ -248,8 +253,13 @@ int pkg_set(struct pkg *, pkg_attr, const char *);
 */
int pkg_set_from_file(struct pkg *, pkg_attr, const char *);

+
/**
+
 * Set the uncompressed size of the package.
+
 */
+
int pkg_setflatsize(struct pkg *, int64_t);
+

int pkg_adddep(struct pkg *, const char *, const char *, const char *);
-
int pkg_addfile(struct pkg *, const char *, const char *, int64_t);
+
int pkg_addfile(struct pkg *, const char *, const char *);
int pkg_addconflict(struct pkg *, const char *);
int pkg_addexec(struct pkg *, const char *, pkg_exec_t);
int pkg_addscript(struct pkg *, const char *);
@@ -265,7 +275,6 @@ void pkg_file_reset(struct pkg_file *);
void pkg_file_free(struct pkg_file *);
const char * pkg_file_path(struct pkg_file *);
const char * pkg_file_sha256(struct pkg_file *);
-
int64_t pkg_file_size(struct pkg_file *);

/* pkg_conflict */
int pkg_conflict_new(struct pkg_conflict **);
modified libpkg/pkg_file.c
@@ -15,19 +15,12 @@ pkg_file_sha256(struct pkg_file *file)
	return (file->sha256);
}

-
int64_t
-
pkg_file_size(struct pkg_file *file)
-
{
-
	return (file->size);
-
}
-

int
pkg_file_new(struct pkg_file **file)
{
	if ((*file = calloc(1, sizeof(struct pkg_file))) == NULL)
		return (EPKG_FATAL);

-
	(*file)->size = -1;
	return (EPKG_OK);
}

@@ -36,7 +29,6 @@ pkg_file_reset(struct pkg_file *file)
{
	file->path[0] = '\0';
	file->sha256[0] = '\0';
-
	file->size = -1;
}

void
modified libpkg/pkg_manifest.c
@@ -1,11 +1,13 @@
+
#include <sys/types.h>
+
#include <sys/sbuf.h>
+

#include <assert.h>
#include <ctype.h>
#include <err.h>
+
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
-
#include <sys/types.h>
-
#include <sys/sbuf.h>

#include "pkg_util.h"
#include "pkg.h"
@@ -18,6 +20,7 @@ static int m_parse_arch(struct pkg *pkg, char *buf);
static int m_parse_osversion(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_flatsize(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);
@@ -25,6 +28,7 @@ static int m_parse_maintainer(struct pkg *pkg, char *buf);
static int m_parse_exec(struct pkg *pkg, char *buf);
static int m_parse_unexec(struct pkg *pkg, char *buf);
static int m_parse_prefix(struct pkg *pkg, char *buf);
+
static int m_parse_file(struct pkg *pkg, char *buf);
static int m_parse_set_string(struct pkg *pkg, char *buf, pkg_attr attr);

#define MANIFEST_FORMAT_KEY "@pkg_format_version"
@@ -40,6 +44,7 @@ static struct manifest_key {
	{ "@osversion", m_parse_osversion},
	{ "@www", m_parse_www},
	{ "@comment", m_parse_comment},
+
	{ "@flatsize", m_parse_flatsize},
	{ "@option", m_parse_option},
	{ "@dep", m_parse_dep},
	{ "@conflict", m_parse_conflict},
@@ -47,6 +52,7 @@ static struct manifest_key {
	{ "@exec", m_parse_exec},
	{ "@unexec", m_parse_unexec},
	{ "@prefix", m_parse_prefix},
+
	{ "@file", m_parse_file},
};

#define manifest_key_len (int)(sizeof(manifest_key)/sizeof(manifest_key[0]))
@@ -116,6 +122,20 @@ m_parse_comment(struct pkg *pkg, char *buf)
}

static int
+
m_parse_flatsize(struct pkg *pkg, char *buf)
+
{
+
	int64_t size;
+

+
	size = strtoimax(buf, NULL, 10);
+

+
	if (size <= 0)
+
		return (EPKG_FATAL);
+

+
	pkg_setflatsize(pkg, size);
+
	return (EPKG_OK);
+
}
+

+
static int
m_parse_exec(struct pkg *pkg, char *buf)
{
	while (isspace(*buf))
@@ -212,6 +232,28 @@ m_parse_conflict(struct pkg *pkg, char *buf)
	return (EPKG_OK);
}

+
static int
+
m_parse_file(struct pkg *pkg, char *buf)
+
{
+
	const char *path;
+
	const char *sha256;
+

+
	while (isspace(*buf))
+
		buf++;
+

+
	if (split_chr(buf, ' ') != 1)
+
		return (EPKG_FATAL);
+

+
	path = buf;
+

+
	buf += strlen(path) + 1;
+
	sha256 = buf;
+

+
	pkg_addfile(pkg, path, sha256);
+

+
	return (EPKG_OK);
+
}
+

int
pkg_parse_manifest(struct pkg *pkg, char *buf)
{
@@ -235,8 +277,13 @@ pkg_parse_manifest(struct pkg *pkg, char *buf)
	for (i = 1; i <= nbel; i++) {
		for (j = 0; j < manifest_key_len; j++) {
			if (STARTS_WITH(buf_ptr, manifest_key[j].key)) {
-
				if (manifest_key[j].parse(pkg, buf_ptr + strlen(manifest_key[j].key)) != EPKG_OK)
+
				if (manifest_key[j].parse(pkg, buf_ptr +
+
					strlen(manifest_key[j].key)) != EPKG_OK) {
+

+
					warnx("Error while parsing %s at line %d",
+
						  manifest_key[j].key, i + 1);
					return (EPKG_FATAL);
+
				}
				break;
			}
		}
@@ -258,6 +305,7 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
	struct pkg_conflict **conflicts;
	struct pkg_exec **execs;
	struct pkg_option **options;
+
	struct pkg_file **files;
	int i;
	int len = 0;

@@ -272,7 +320,8 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
			"@osversion %s\n"
			"@www %s\n"
			"@maintainer %s\n"
-
			"@prefix %s\n",
+
			"@prefix %s\n"
+
			"@flatsize %" PRId64 "\n",
			pkg_get(pkg, PKG_NAME),
			pkg_get(pkg, PKG_VERSION),
			pkg_get(pkg, PKG_ORIGIN),
@@ -281,7 +330,8 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
			pkg_get(pkg, PKG_OSVERSION),
			pkg_get(pkg, PKG_WWW),
			pkg_get(pkg, PKG_MAINTAINER) ? pkg_get(pkg, PKG_MAINTAINER) : "UNKNOWN",
-
			pkg_get(pkg, PKG_PREFIX)
+
			pkg_get(pkg, PKG_PREFIX),
+
			pkg_flatsize(pkg)
			);

	if ((deps = pkg_deps(pkg)) != NULL) {
@@ -316,6 +366,13 @@ pkg_emit_manifest(struct pkg *pkg, char **dest)
		}
	}

+
	if ((files = pkg_files(pkg)) != NULL) {
+
		for (i = 0; files[i] != NULL; i++) {
+
			sbuf_printf(manifest, "@file %s %s\n", pkg_file_path(files[i]),
+
						pkg_file_sha256(files[i]));
+
		}
+
	}
+

	sbuf_finish(manifest);
	len = sbuf_len(manifest);
	*dest = strdup(sbuf_data(manifest));
modified libpkg/pkg_ports.c
@@ -87,7 +87,7 @@ ports_parse_plist(struct pkg *pkg, char *plist)
				p = NULL;
			}

-
			ret += pkg_addfile(pkg, path, p, -1);
+
			ret += pkg_addfile(pkg, path, p);
		}

		if (i != nbel) {
modified libpkg/pkg_private.h
@@ -21,6 +21,7 @@ struct pkg {
	struct sbuf *www;
	struct sbuf *err;
	struct sbuf *prefix;
+
	int64_t flatsize;
	struct array deps;
	struct array rdeps;
	struct array conflicts;
@@ -49,7 +50,6 @@ struct pkg_exec {
struct pkg_file {
	char path[MAXPATHLEN];
	char sha256[65];
-
	int64_t size;
};

struct pkg_option {
modified libpkg/pkg_repo.c
@@ -20,12 +20,10 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
	struct stat st;
	struct pkg *pkg = NULL;
	struct pkg **deps;
-
	struct pkg_file **files;
	char *ext = NULL;
	sqlite3 *sqlite;
	sqlite3_stmt *stmt_deps;
	sqlite3_stmt *stmt_pkg;
-
	int64_t flatsize = 0;

	int i;

@@ -103,18 +101,10 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *

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

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

-
		/* Compute the fat size (uncompressed) */
-
		if ((files = pkg_files(pkg)) != NULL) {
-
			for (i = 0; files[i] != NULL; i++) {
-
				flatsize += pkg_file_size(files[i]);
-
			}
-
		}
-

		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);
@@ -125,7 +115,7 @@ pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *
		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, flatsize);
+
		sqlite3_bind_int64(stmt_pkg, 12, pkg_flatsize(pkg));

		sqlite3_step(stmt_pkg);
		sqlite3_reset(stmt_pkg);
modified libpkg/pkgdb.c
@@ -125,6 +125,7 @@ pkgdb_init(sqlite3 *sdb)
		"maintainer TEXT,"
		"www TEXT,"
		"prefix TEXT,"
+
		"flatsize INTEGER,"
		"automatic INTEGER,"
		"pkg_format_version INTEGER"
	");"
@@ -282,6 +283,7 @@ pkgdb_it_next_pkg(struct pkgdb_it *it, struct pkg **pkg_p, int flags)
		pkg_set(pkg, PKG_MAINTAINER, sqlite3_column_text(it->stmt, 9));
		pkg_set(pkg, PKG_WWW, sqlite3_column_text(it->stmt, 10));
		pkg_set(pkg, PKG_PREFIX, sqlite3_column_text(it->stmt, 11));
+
		pkg_setflatsize(pkg, sqlite3_column_int64(it->stmt, 12));

		if (flags & PKG_DEPS) {
			array_init(&pkg->deps, 10);
@@ -561,7 +563,8 @@ pkgdb_query(struct pkgdb *db, const char *pattern, match_t match)

	snprintf(sql, sizeof(sql),
			"SELECT p.origin, p.name, p.version, p.comment, p.desc, m.content, "
-
				"p.message, p.arch, p.osversion, p.maintainer, p.www, p.prefix "
+
				"p.message, p.arch, p.osversion, p.maintainer, p.www, "
+
				"p.prefix, p.flatsize "
			"FROM packages AS p, mtree AS m "
			"WHERE m.id = p.mtree_id%s;", comp);

@@ -580,7 +583,8 @@ pkgdb_query_which(struct pkgdb *db, const char *path)

	sqlite3_prepare(db->sqlite,
					"SELECT p.origin, p.name, p.version, p.comment, p.desc, m.content, "
-
						"p.message, p.arch, p.osversion, p.maintainer, p.www, p.prefix "
+
						"p.message, p.arch, p.osversion, p.maintainer, p.www, "
+
						"p.prefix, p.flatsize "
					"FROM packages AS p, mtree AS m, files AS f "
					"WHERE m.id = p.mtree_id " 
					"AND p.origin = f.package_id "
@@ -597,6 +601,7 @@ pkgdb_query_dep(struct pkgdb *db, const char *origin) {
	sqlite3_prepare(db->sqlite,
					"SELECT p.origin, p.name, p.version, p.comment, p.desc, m.content, "
						"p.message, p.arch, p.osversion, p.maintainer, p.www "
+
						"p.prefix, p.flatsize "
					"FROM packages AS p, mtree AS m, deps AS d "
					"WHERE m.id = p.mtree_id "
					"AND p.origin = d.origin "
@@ -613,6 +618,7 @@ pkgdb_query_rdep(struct pkgdb *db, const char *origin) {
	sqlite3_prepare(db->sqlite,
					"SELECT p.origin, p.name, p.version, p.comment, p.desc, m.content, "
						"p.message, p.arch, p.osversion, p.maintainer, p.www "
+
						"p.prefix, p.flatsize "
					"FROM packages AS p, mtree AS m, deps AS d "
					"WHERE m.id = p.mtree_id "
					"AND p.origin = d.package_id "
@@ -752,8 +758,14 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)

	/* Add the record into packages */
	sqlite3_prepare(db->sqlite,
-
					"INSERT OR REPLACE INTO packages (origin, name, version, comment, desc, mtree_id, message, arch, osversion, maintainer, www, prefix) "
-
					"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12);",
+
					"INSERT OR REPLACE INTO packages( "
+
						"origin, name, version, comment, desc, mtree_id, "
+
						"message, arch, osversion, maintainer, www, "
+
						"prefix, flatsize) "
+
					"VALUES( "
+
						"?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, "
+
						"?12, ?13)"
+
					";",
					-1, &stmt_pkg, NULL);

	sqlite3_bind_text(stmt_pkg, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC);
@@ -768,6 +780,7 @@ pkgdb_register_pkg(struct pkgdb *db, struct pkg *pkg)
	sqlite3_bind_text(stmt_pkg, 10, pkg_get(pkg, PKG_MAINTAINER), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 11, pkg_get(pkg, PKG_WWW), -1, SQLITE_STATIC);
	sqlite3_bind_text(stmt_pkg, 12, pkg_get(pkg, PKG_PREFIX), -1, SQLITE_STATIC);
+
	sqlite3_bind_int64(stmt_pkg, 13, pkg_flatsize(pkg));

	sqlite3_step(stmt_pkg);
	sqlite3_finalize(stmt_pkg);
modified pkg/add.c
@@ -72,7 +72,8 @@ exec_add(int argc, char **argv)
	if (ret != 0)
		return (ret);

-
	pkg_add(db, pkg);
+
	if (pkg_add(db, pkg) != EPKG_OK)
+
		err(1, "installation of %s failed", argv[1]);

	pkgdb_close(db);
	pkg_free(pkg);
modified pkg/info.c
@@ -1,5 +1,4 @@
#include <sys/types.h>
-
#include <sys/stat.h>

#include <err.h>
#include <inttypes.h>
@@ -13,24 +12,6 @@

#include "info.h"

-
static int64_t
-
pkg_size(struct pkg *pkg)
-
{
-
	struct pkg_file **files;
-
	struct stat st;
-
	int64_t size = 0;
-

-
	files = pkg_files(pkg);
-
	for (size_t i = 0; files[i] != NULL; i++) {
-
		if (stat(pkg_file_path(files[i]), &st) != 0) {
-
			warn("stat(%s)", pkg_file_path(files[i]));
-
			continue;
-
		}
-
		size += st.st_size;
-
	}
-
	return (size);
-
}
-

static int
query_pkg(struct pkg *pkg, unsigned char opt) {
	struct pkg **deps;
@@ -121,11 +102,10 @@ exec_info(int argc, char **argv)
				break;
			case 'l':
				opt |= INFO_LIST_FILES;
-
				query_flags = PKG_FILES;
+
				query_flags |= PKG_FILES;
				break;
			case 's':
				opt |= INFO_SIZE;
-
				query_flags = PKG_FILES;
				break;
			case 'q':
				opt |= INFO_QUIET;
@@ -144,8 +124,13 @@ exec_info(int argc, char **argv)
	pkg_new(&pkg);

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

	if (pkgdb_open(&db) == -1) {
		pkgdb_warn(db);
@@ -202,7 +187,7 @@ exec_info(int argc, char **argv)

			printf("\n");
		} else if (opt & INFO_SIZE) {
-
			humanize_number(size, sizeof(size), pkg_size(pkg), "B", HN_AUTOSCALE, 0);
+
			humanize_number(size, sizeof(size), pkg_flatsize(pkg), "B", HN_AUTOSCALE, 0);
			printf("%s-%s size is %s\n", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION), size);
		} else if (opt & INFO_ORIGIN) {
			if (opt & INFO_QUIET)
modified pkg/register.c
@@ -1,3 +1,4 @@
+
#include <sys/stat.h>
#include <sys/param.h>

#include <err.h>
@@ -12,6 +13,8 @@

#include "register.h"

+
static void compute_flatsize(struct pkg *pkg);
+

void
usage_register(void)
{
@@ -164,9 +167,30 @@ exec_register(int argc, char **argv)
	if (heuristic)
		pkg_analyse_files(db, pkg);

+
	compute_flatsize(pkg);
+

	pkgdb_register_pkg(db, pkg);
	pkgdb_close(db);
	pkg_free(pkg);

	return (0);
}
+

+
static void
+
compute_flatsize(struct pkg *pkg)
+
{
+
	struct pkg_file **files;
+
	struct stat st;
+
	int64_t size = 0;
+

+
	files = pkg_files(pkg);
+
	for (int i = 0; files[i] != NULL; i++) {
+
		if (stat(pkg_file_path(files[i]), &st) != 0) {
+
			warn("stat(%s)", pkg_file_path(files[i]));
+
			continue;
+
		}
+
		size += st.st_size;
+
	}
+

+
	pkg_setflatsize(pkg, size);
+
}
modified tests/manifest.c
@@ -14,6 +14,7 @@ char manifest[] = ""
	"@osversion 800500\n"
	"@www http://www.foobar.com\n"
	"@maintainer test@pkgng.lan\n"
+
	"@flatsize 10000\n"
	"@dep depfoo dep/foo 1.2\n"
	"@dep depbar dep/bar 3.4\n"
	"@conflict foo-*\n"
@@ -23,7 +24,9 @@ char manifest[] = ""
	"@unexec true && echo good\n"
	"@unexec false || echo bye\n"
	"@option foo true\n"
-
	"@option bar false\n";
+
	"@option bar false\n"
+
	"@file /usr/local/bin/foo "
+
		"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b\n";

char wrong_manifest1[] = ""
	"@pkg_format_version 0.9\n"
@@ -146,6 +149,7 @@ START_TEST(parse_manifest)
	struct pkg_conflict **conflicts;
	struct pkg_exec **execs;
	struct pkg_option **options;
+
	struct pkg_file **files;
	int i;

	fail_unless(pkg_new(&p) == 0);
@@ -222,6 +226,15 @@ START_TEST(parse_manifest)
		}
	}
	fail_unless(i == 2);
+

+
	files = pkg_files(p);
+
	fail_if(files == NULL);
+
	fail_unless(strcmp(pkg_file_path(files[0]), "/usr/local/bin/foo") ==
+
				0);
+
	fail_unless(strcmp(pkg_file_sha256(files[0]),
+
				"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b")
+
				== 0);
+

}
END_TEST