Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Initial support for fakeroot creating packages.
Will Andrews committed 14 years ago
commit fcde051377522e3db83123ba92e23b374308e8e2
parent b748a6d
6 files changed +144 -38
modified libpkg/packing.c
@@ -1,4 +1,9 @@
#include <fcntl.h>
+
#include <sys/cdefs.h>
+
#include <sys/types.h>
+
#include <sys/stat.h>
+
#include <sys/sbuf.h>
+
#include <fts.h>

#include <archive.h>
#include <archive_entry.h>
@@ -103,6 +108,50 @@ packing_append_file(struct packing *pack, const char *filepath, const char *newp
}

int
+
packing_append_tree(struct packing *pack, const char *treepath, const char *newroot)
+
{
+
	FTS *fts = NULL;
+
	FTSENT *fts_e = NULL;
+
	size_t treelen;
+
	struct sbuf *sb;
+
	char *paths[2] = { __DECONST(char *, treepath), NULL };
+

+
	treelen = strlen(treepath);
+
	fts = fts_open(paths, FTS_PHYSICAL | FTS_XDEV, NULL);
+
	if (fts == NULL)
+
		goto cleanup;
+

+
	while ((fts_e = fts_read(fts)) != NULL) {
+
		switch(fts_e->fts_info) {
+
		case FTS_F:
+
			/* Skip entries that are shorter than the tree itself */
+
			if (fts_e->fts_pathlen <= treelen)
+
				break;
+
			sb = sbuf_new_auto();
+
			/* Strip the prefix to obtain the target path */
+
			if (newroot) /* Prepend a root if one is specified */
+
				sbuf_cat(sb, newroot);
+
			sbuf_cat(sb, fts_e->fts_path + treelen + 1 /* skip trailing slash */);
+
			sbuf_finish(sb);
+
			packing_append_file(pack, fts_e->fts_name, sbuf_get(sb));
+
			sbuf_free(sb);
+
			break;
+
		case FTS_DNR:
+
		case FTS_ERR:
+
		case FTS_NS:
+
			/* XXX error cases, check fts_e->fts_errno and
+
			 *     bubble up the call chain */
+
			break;
+
		default:
+
			break;
+
		}
+
	}
+
cleanup:
+
	fts_close(fts);
+
	return EPKG_OK;
+
}
+

+
int
packing_finish(struct packing *pack)
{
	archive_entry_free(pack->entry);
modified libpkg/pkg.h
@@ -493,7 +493,7 @@ typedef enum pkg_formats { TAR, TGZ, TBZ, TXZ } pkg_formats;
/**
 * @todo Document
 */
-
int pkg_create(const char *, pkg_formats, const char *, const char *, struct pkg *);
+
int pkg_create_installed(const char *, pkg_formats, const char *, struct pkg *);

/**
 * Create packages that match
@@ -501,6 +501,11 @@ int pkg_create(const char *, pkg_formats, const char *, const char *, struct pkg
int pkg_create_matches(int, char **, match_t, pkg_formats, const char *, const char *);

/**
+
 * Create package from fakeroot install with a metadata directory
+
 */
+
int pkg_create_fakeroot(const char *, pkg_formats, const char *, const char *);
+

+
/**
 * Remove and unregister the package.
 * @param force If set to one, the function will not fail if the package is
 * required by other packages.
modified libpkg/pkg_create.c
@@ -3,6 +3,7 @@
#include <archive.h>
#include <archive_entry.h>
#include <err.h>
+
#include <errno.h>
#include <stdlib.h>
#include <glob.h>
#include <libgen.h>
@@ -13,29 +14,19 @@
#include "pkg_error.h"
#include "pkg_private.h"

-
static int pkg_create_from_dir(struct pkg *, const char *, struct packing *, const char *);
+
static int pkg_create_from_dir(struct pkg *, const char *, struct packing *);

static int
-
pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archive, const char *mpath)
+
pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archive)
{
	char fpath[MAXPATHLEN];
	struct pkg_file **files;
	struct pkg_script **scripts;
	char *m;
-
	int i, ret;
-
	size_t sz;
+
	int i;
	const char *scriptname = NULL;

-
	/*
-
	 * Read in the manifest file, if specified.  This is required if any
-
	 * of the manifest fields are generated by a libpkg consumer.
-
	 */
-
	if (mpath) {
-
		ret = file_to_buffer(mpath, &m, &sz);
-
		if (ret != EPKG_OK)
-
			return ret;
-
	} else
-
		pkg_emit_manifest(pkg, &m);
+
	pkg_emit_manifest(pkg, &m);

	packing_append_buffer(pkg_archive, m, "+MANIFEST", strlen(m));

@@ -94,12 +85,83 @@ pkg_create_from_dir(struct pkg *pkg, const char *root, struct packing *pkg_archi
	return (EPKG_OK);
}

+
static struct packing *
+
pkg_create_archive(const char *outdir, struct pkg *pkg, pkg_formats format, int required_flags)
+
{
+
	char *pkg_path = NULL;
+
	struct packing *pkg_archive = NULL;
+

+
	/*
+
	 * Ensure that we have all the information we need
+
	 */
+
	if ((pkg->flags & required_flags) != required_flags) {
+
		printf("error: required flags not set\n");
+
		return NULL;
+
	}
+

+
	if (asprintf(&pkg_path, "%s/%s-%s", outdir, pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION)) == -1) {
+
		perror("asprintf");
+
		return NULL; /* XXX do better */
+
	}
+
	if (packing_init(&pkg_archive, pkg_path, format) != EPKG_OK) {
+
		perror("packing_init");
+
		return NULL;
+
	}
+

+
	if (pkg_path != NULL)
+
		free(pkg_path);
+
	return pkg_archive;
+
}
+

int
-
pkg_create(const char *mpath, pkg_formats format, const char *outdir, const char *rootdir, struct pkg *pkg)
+
pkg_create_fakeroot(const char *outdir, pkg_formats format, const char *rootdir, const char *metadatadir)
+
{
+
	struct pkg *pkg = NULL;
+
	struct packing *pkg_archive = NULL;
+
	char *manifest = NULL, *manifest_path = NULL;
+
	int ret = ENOMEM;
+
	size_t sz;
+

+
	/* Load the manifest from the metadata directory */
+
	if (asprintf(&manifest_path, "%s/+MANIFEST", metadatadir) == -1)
+
		goto cleanup;
+
	pkg_new(&pkg);
+
	pkg->type = PKG_FILE;
+
	if (pkg == NULL)
+
		goto cleanup;
+
	ret = file_to_buffer(manifest_path, &manifest, &sz);
+
	if (ret != EPKG_OK)
+
		goto cleanup;
+
	ret = pkg_parse_manifest(pkg, manifest);
+

+
	/* Create the archive */
+
	pkg_archive = pkg_create_archive(outdir, pkg, format, 0);
+
	if (pkg_archive == NULL) {
+
		ret = EPKG_FATAL; /* XXX do better */
+
		goto cleanup;
+
	}
+

+
	/* Now traverse the file directories, adding to the archive */
+
	packing_append_tree(pkg_archive, metadatadir, NULL);
+
	packing_append_tree(pkg_archive, rootdir, "/");
+
	ret = EPKG_OK;
+

+
cleanup:
+
	if (pkg != NULL)
+
		free(pkg);
+
	if (manifest_path != NULL)
+
		free(manifest_path);
+
	if (manifest != NULL)
+
		free(manifest);
+
	if (ret == EPKG_OK)
+
		ret = packing_finish(pkg_archive);
+
	return ret;
+
}
+

+
int
+
pkg_create_installed(const char *outdir, pkg_formats format, const char *rootdir, struct pkg *pkg)
{
-
	char namever[FILENAME_MAX];
	struct packing *pkg_archive;
-
	char archive_path[MAXPATHLEN];
	int required_flags = PKG_LOAD_DEPS | PKG_LOAD_CONFLICTS | PKG_LOAD_FILES |
						 PKG_LOAD_EXECS | PKG_LOAD_SCRIPTS | PKG_LOAD_OPTIONS |
						 PKG_LOAD_MTREE;
@@ -107,25 +169,13 @@ pkg_create(const char *mpath, pkg_formats format, const char *outdir, const char
	if (pkg->type != PKG_INSTALLED)
		return (ERROR_BAD_ARG("pkg"));

-
	/*
-
	 * Ensure that we have all the information we need
-
	 */
-
	if ((pkg->flags & required_flags) != required_flags)
-
		return (ERROR_BAD_ARG("pkg"));
+
	pkg_archive = pkg_create_archive(outdir, pkg, format, required_flags);
+
	if (pkg_archive == NULL)
+
		return pkg_error_set(EPKG_FATAL, "unable to create archive"); /* XXX do better */

-
	snprintf(namever, sizeof(namever), "%s-%s", pkg_get(pkg, PKG_NAME), pkg_get(pkg, PKG_VERSION));
-
	snprintf(archive_path, sizeof(archive_path), "%s/%s", outdir, namever);
+
	pkg_create_from_dir(pkg, rootdir, pkg_archive);

-
	if (packing_init(&pkg_archive, archive_path, format) != EPKG_OK) {
-
		/* TODO do it smarter */
-
		return pkg_error_set(EPKG_FATAL, "unable to create archive");
-
	}
-

-
	pkg_create_from_dir(pkg, rootdir, pkg_archive, mpath);
-

-
	return (packing_finish(pkg_archive));
-

-
	return (EPKG_OK);
+
	return packing_finish(pkg_archive);
}

int
@@ -153,7 +203,7 @@ pkg_create_matches(int argc, char **argv, match_t match, pkg_formats fmt, const
		while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
			printf("Creating package for %s-%s\n", pkg_get(pkg, PKG_NAME),
			    pkg_get(pkg, PKG_VERSION));
-
			if (pkg_create(NULL, fmt, outdir, rootdir, pkg) != EPKG_OK) {
+
			if (pkg_create_installed(outdir, fmt, rootdir, pkg) != EPKG_OK) {
				pkg_error_warn("can not create package");
				retcode++;
			}
modified libpkg/pkg_private.h
@@ -72,6 +72,7 @@ struct packing;
int packing_init(struct packing **pack, const char *path, pkg_formats format);
int packing_append_file(struct packing *pack, const char *filepath, const char *newpath);
int packing_append_buffer(struct packing *pack, const char *buffer, const char *path, int size);
+
int packing_append_tree(struct packing *pack, const char *treepath, const char *newroot);
int packing_finish(struct packing *pack);
pkg_formats packing_format_from_string(const char *str);

modified pkg/Makefile
@@ -12,6 +12,7 @@ SRCS= add.c \
		which.c
BINDIR=		/usr/sbin

+
DEBUG_FLAGS=	-g
CFLAGS+=	-I${.CURDIR}/../libpkg
LDADD+=		-L../libpkg \
		-lpkgng \
modified pkg/create.c
@@ -13,7 +13,7 @@ void
usage_create(void)
{
	fprintf(stderr, "usage: pkg create [-gx] [-r rootdir] [-m manifest] [-f format] [-o outdir] "
-
			"<pkg-name>\n");
+
			"<pkg> ...\n");
	fprintf(stderr, "       pkg create -a [-r rootdir] [-m manifest] [-f format] [-o outdir]\n\n");
	fprintf(stderr, "For more information see 'pkg help create'.\n");
}
@@ -98,6 +98,6 @@ exec_create(int argc, char **argv)
	if (manifestdir == NULL)
		return pkg_create_matches(argc, argv, match, fmt, outdir, rootdir);
	else
-
		return pkg_create(manifestdir, fmt, outdir, rootdir, NULL);
+
		return pkg_create_fakeroot(outdir, fmt, rootdir, manifestdir);
}