Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Add cheksums computation for manifests.
Vsevolod Stakhov committed 13 years ago
commit 53c8ad999086a19746491004868c1e1c1fa1b238
parent 7c66f89
6 files changed +108 -18
modified libpkg/pkg.h.in
@@ -760,10 +760,12 @@ int pkg_load_manifest_file(struct pkg *pkg, const char *fpath);
 * Emit a manifest according to the attributes of pkg.
 * @param buf A pointer which will hold the allocated buffer containing the
 * manifest. To be free'ed.
+
 * @param pdigest A pointer that will hold digest of manifest produced, ignored
+
 * if NULL. To be free'ed if not NULL.
 * @return An error code.
 */
-
int pkg_emit_manifest(struct pkg *pkg, char **buf, bool compact);
-
int pkg_emit_manifest_file(struct pkg*, FILE *, bool);
+
int pkg_emit_manifest(struct pkg *pkg, char **buf, bool compact, char **pdigest);
+
int pkg_emit_manifest_file(struct pkg*, FILE *, bool, char **pdigest);

/* pkg_dep */
const char *pkg_dep_get(struct pkg_dep const * const , const pkg_dep_attr);
modified libpkg/pkg_create.c
@@ -103,7 +103,7 @@ pkg_create_from_dir(struct pkg *pkg, const char *root,
	} else {
		pkg_register_shlibs(pkg);

-
		pkg_emit_manifest(pkg, &m, false);
+
		pkg_emit_manifest(pkg, &m, false, NULL);
		packing_append_buffer(pkg_archive, m, "+MANIFEST", strlen(m));
		free(m);
	}
modified libpkg/pkg_manifest.c
@@ -690,11 +690,38 @@ pkg_parse_manifest(struct pkg *pkg, char *buf)
	return retcode;
}

+
struct pkg_yaml_emitter_data {
+
	SHA256_CTX *sign_ctx;
+
	union {
+
		struct sbuf *sbuf;
+
		FILE *file;
+
		char *dest;
+
	} data;
+
};
+

static int
yaml_write_buf(void *data, unsigned char *buffer, size_t size)
{
-
	struct sbuf *dest = (struct sbuf *)data;
-
	sbuf_bcat(dest, buffer, size);
+
	struct pkg_yaml_emitter_data *dest = (struct pkg_yaml_emitter_data *)data;
+

+
	sbuf_bcat(dest->data.sbuf, buffer, size);
+
	if (dest->sign_ctx != NULL)
+
		SHA256_Update(dest->sign_ctx, buffer, size);
+

+
	return (1);
+
}
+

+
static int
+
yaml_write_file(void *data, unsigned char *buffer, size_t size)
+
{
+
	struct pkg_yaml_emitter_data *dest = (struct pkg_yaml_emitter_data *)data;
+

+
	if (fwrite(buffer, size, 1, dest->data.file) != 1)
+
		return -1;
+

+
	if (dest->sign_ctx != NULL)
+
		SHA256_Update(dest->sign_ctx, buffer, size);
+

	return (1);
}

@@ -735,7 +762,7 @@ pkg_emit_filelist(struct pkg *pkg, FILE *f)
	yaml_emitter_t emitter;
	yaml_document_t doc;

-
	struct pkg_file *file;
+
	struct pkg_file *file = NULL;

	const char *name, *origin, *version;

@@ -990,46 +1017,93 @@ emit_manifest(struct pkg *pkg, yaml_emitter_t *emitter, bool compact)
	return (rc);
}

+
static void
+
pkg_emit_manifest_digest(const unsigned char *digest, size_t len, char *hexdigest)
+
{
+
	unsigned int i;
+

+
	for (i = 0; i < len; i ++)
+
		sprintf(hexdigest + (i * 2), "%02x", digest[i]);
+

+
	hexdigest[len * 2] = '\0';
+
}
+

int
-
pkg_emit_manifest_file(struct pkg *pkg, FILE *f, bool compact)
+
pkg_emit_manifest_file(struct pkg *pkg, FILE *f, bool compact, char **pdigest)
{
	yaml_emitter_t emitter;
+
	struct pkg_yaml_emitter_data emitter_data;
+
	unsigned char digest[SHA256_DIGEST_LENGTH];
	int rc;

+
	if (pdigest != NULL) {
+
		*pdigest = malloc(sizeof(digest) * 2 + 1);
+
		emitter_data.sign_ctx = malloc(sizeof(SHA256_CTX));
+
		SHA256_Init(emitter_data.sign_ctx);
+
	}
+
	else {
+
		emitter_data.sign_ctx = NULL;
+
	}
+

	yaml_emitter_initialize(&emitter);
	yaml_emitter_set_unicode(&emitter, 1);
-
	yaml_emitter_set_output_file(&emitter, f);
+
	emitter_data.data.file = f;
+
	yaml_emitter_set_output(&emitter, yaml_write_file, &emitter_data);

	rc = emit_manifest(pkg, &emitter, compact);

+
	if (emitter_data.sign_ctx != NULL) {
+
		SHA256_Final(digest, emitter_data.sign_ctx);
+
		pkg_emit_manifest_digest(digest, sizeof(digest), *pdigest);
+
		free(emitter_data.sign_ctx);
+
	}
	yaml_emitter_delete(&emitter);

	return (rc);
}

int
-
pkg_emit_manifest_sbuf(struct pkg *pkg, struct sbuf *b, bool compact)
+
pkg_emit_manifest_sbuf(struct pkg *pkg, struct sbuf *b, bool compact, char **pdigest)
{
	yaml_emitter_t emitter;
+
	struct pkg_yaml_emitter_data emitter_data;
+
	unsigned char digest[SHA256_DIGEST_LENGTH];
	int rc;

+
	if (pdigest != NULL) {
+
		*pdigest = malloc(sizeof(digest) * 2 + 1);
+
		emitter_data.sign_ctx = malloc(sizeof(SHA256_CTX));
+
		SHA256_Init(emitter_data.sign_ctx);
+
	}
+
	else {
+
		emitter_data.sign_ctx = NULL;
+
	}
+

	yaml_emitter_initialize(&emitter);
	yaml_emitter_set_unicode(&emitter, 1);
-
	yaml_emitter_set_output(&emitter, yaml_write_buf, b);
+
	emitter_data.data.sbuf = b;
+
	yaml_emitter_set_output(&emitter, yaml_write_buf, &emitter_data);

	rc = emit_manifest(pkg, &emitter, compact);

+
	if (emitter_data.sign_ctx != NULL) {
+
		SHA256_Final(digest, emitter_data.sign_ctx);
+
		pkg_emit_manifest_digest(digest, sizeof(digest), *pdigest);
+
		free(emitter_data.sign_ctx);
+
	}
+

	yaml_emitter_delete(&emitter);

	return (rc);
}
+

int
-
pkg_emit_manifest(struct pkg *pkg, char **dest, bool compact)
+
pkg_emit_manifest(struct pkg *pkg, char **dest, bool compact, char **pdigest)
{
	struct sbuf *b = sbuf_new_auto();
	int rc;

-
	rc = pkg_emit_manifest_sbuf(pkg, b, compact);
+
	rc = pkg_emit_manifest_sbuf(pkg, b, compact, pdigest);

	if (rc != EPKG_OK) {
		sbuf_delete(b);
modified libpkg/pkg_repo.c
@@ -585,9 +585,10 @@ pkg_create_repo(char *path, __unused bool force, void (progress)(struct pkg *pkg
	char *repopath[2];
	char repodb[MAXPATHLEN + 1];
	char repopack[MAXPATHLEN + 1];
-
	FILE *psyml, *fsyml;
+
	char *manifest_digest;
+
	FILE *psyml, *fsyml, *mandigests;

-
	psyml = fsyml = NULL;
+
	psyml = fsyml = mandigests = NULL;

	if (!is_dir(path)) {
		pkg_emit_error("%s is not a directory", path);
@@ -617,6 +618,11 @@ pkg_create_repo(char *path, __unused bool force, void (progress)(struct pkg *pkg
		retcode = EPKG_FATAL;
		goto cleanup;
	}
+
	snprintf(repodb, sizeof(repodb), "%s/digests", path);
+
	if ((mandigests = fopen(repodb, "w")) == NULL) {
+
		retcode = EPKG_FATAL;
+
		goto cleanup;
+
	}

	snprintf(repodb, sizeof(repodb), "%s/repo.sqlite", path);
	snprintf(repopack, sizeof(repopack), "%s/repoy.txz", path);
@@ -690,9 +696,10 @@ pkg_create_repo(char *path, __unused bool force, void (progress)(struct pkg *pkg
		if (progress != NULL)
			progress(r->pkg, data);

-
		pkg_emit_manifest_file(r->pkg, psyml, true);
+
		pkg_emit_manifest_file(r->pkg, psyml, true, &manifest_digest);
		pkg_emit_filelist(r->pkg, fsyml);

+

		pkg_get(r->pkg, PKG_ORIGIN, &origin, PKG_NAME, &name,
		    PKG_VERSION, &version, PKG_COMMENT, &comment,
		    PKG_DESC, &desc, PKG_ARCH, &arch,
@@ -700,6 +707,8 @@ pkg_create_repo(char *path, __unused bool force, void (progress)(struct pkg *pkg
		    PKG_PREFIX, &prefix, PKG_FLATSIZE, &flatsize,
		    PKG_LICENSE_LOGIC, &licenselogic, PKG_CKSUM, &sum,
		    PKG_NEW_PKGSIZE, &pkgsize, PKG_REPOPATH, &rpath);
+
		fprintf(mandigests, "%s: %s\n", origin, manifest_digest);
+
		free(manifest_digest);

	try_again:
		if ((ret = run_prepared_statement(PKG, origin, name, version,
@@ -850,6 +859,9 @@ cleanup:
	if (psyml != NULL)
		fclose(psyml);

+
	if (mandigests != NULL)
+
		fclose(mandigests);
+

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

@@ -916,7 +928,9 @@ read_pkg_file(void *data)
				strcmp(ext, ".tar") != 0)
			continue;

-
		if (strcmp(fts_name, "repo.txz") == 0)
+
		if (strcmp(fts_name, "repo.txz") == 0 ||
+
			strcmp(fts_name, "packagesite.txz") == 0 ||
+
			strcmp(fts_name, "filesite.txz") == 0)
			continue;

		pkg_path = fts_path;
modified libpkg/private/pkg.h
@@ -383,7 +383,7 @@ int pkg_register_shlibs(struct pkg *pkg);

void pkg_config_parse(yaml_document_t *doc, yaml_node_t *node, struct pkg_config *conf_by_key);

-
int pkg_emit_manifest_sbuf(struct pkg*, struct sbuf *, bool);
+
int pkg_emit_manifest_sbuf(struct pkg*, struct sbuf *, bool, char **);
int pkg_emit_filelist(struct pkg *, FILE *);

#endif
modified pkg/utils.c
@@ -229,7 +229,7 @@ print_info(struct pkg * const pkg, unsigned int options)

	if (options & INFO_RAW) { /* Not for remote packages */
		if (pkg_type(pkg) != PKG_REMOTE)
-
			pkg_emit_manifest_file(pkg, stdout, false);
+
			pkg_emit_manifest_file(pkg, stdout, false, NULL);
		return;
	}