Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Add a forgotten file
Baptiste Daroussin committed 15 years ago
commit 52deec888a14bb65b6c860c49f9b5874b669f39a
parent a995890
1 file changed +193 -0
added libpkg/pkg.c
@@ -0,0 +1,193 @@
+
#include <err.h>
+
#include <stdlib.h>
+
#include <sys/param.h>
+
#include <archive.h>
+
#include <archive_entry.h>
+
#include <pkgdb.h>
+
#include <glob.h>
+
#include <sys/stat.h>
+
#include <libgen.h>
+
#include <string.h>
+
#include <fcntl.h>
+
#include <cJSON.h>
+
#include "util.h"
+

+
#define METADATA_GLOB "+{DEINSTALL,INSTALL,MTREE_DIRS}"
+

+
static int pkg_create_from_dir(char *, char *, struct archive *);
+

+
static int
+
pkg_create_from_dir(char *path, char *root, struct archive *pkg_archive)
+
{
+
	struct archive_entry *entry;
+
	char glob_pattern[MAXPATHLEN + sizeof(METADATA_GLOB)];
+
	glob_t g;
+
	int fd, j;
+
	size_t len, i = 0;
+
	char buf[BUFSIZ];
+
	struct stat st;
+
	cJSON *manifest, *files, *file;
+
	char *buffer;
+
	char manifestpath[MAXPATHLEN];
+
	char *filepath;
+
	void *filebuf;
+

+
	struct archive *ar;
+

+
	ar = archive_read_disk_new();
+
	archive_read_disk_set_standard_lookup(ar);
+

+
	snprintf(manifestpath, sizeof(manifestpath), "%s+MANIFEST", path);
+
	entry = archive_entry_new();
+

+
	if ((file_to_buffer(manifestpath, &buffer)) == -1) {
+
		/* TODO */
+
		warnx("fail");
+
		return (-1);
+
	}
+

+
	if ((manifest = cJSON_Parse(buffer)) == 0) {
+
		warnx("%s: Manifest corrupted, skipping", manifestpath);
+
		free(buffer);
+
		return (-1);
+
	}
+

+
	free(buffer);
+

+
	/* Add the metadatas */
+
	snprintf(glob_pattern, sizeof(glob_pattern), "%s"METADATA_GLOB, path);
+
	
+
	if (glob(glob_pattern, GLOB_NOSORT|GLOB_BRACE, NULL, &g) == 0) {
+
		for ( i = 0; i < g.gl_pathc; i++) {
+
			fd = open(g.gl_pathv[i], O_RDONLY);
+
			archive_entry_copy_sourcepath(entry, g.gl_pathv[i]);
+

+
			if (archive_read_disk_entry_from_file(ar, entry, -1, 0) != ARCHIVE_OK)
+
				warnx(archive_error_string(ar));
+

+
			archive_entry_set_pathname(entry, basename(g.gl_pathv[i]));
+
			archive_write_header(pkg_archive, entry);
+
			while ( (len = read(fd, buf, sizeof(buf))) > 0 )
+
				archive_write_data(pkg_archive, buf, len);
+

+
			close(fd);
+
			archive_entry_clear(entry);
+
		}
+
	}
+
	globfree(&g);
+
	cJSON_DeleteItemFromObject(manifest, "automatic");
+

+
	buffer = cJSON_Print(manifest);
+

+
	archive_entry_copy_sourcepath(entry, manifestpath);
+
	if (archive_read_disk_entry_from_file(ar, entry, -1, 0) != ARCHIVE_OK)
+
		warnx(archive_error_string(ar));
+

+
	archive_entry_set_pathname(entry, "+MANIFEST");
+
	archive_entry_set_size(entry, sizeof(buffer));
+
	archive_write_header(pkg_archive, entry);
+
	archive_write_data(pkg_archive, buffer, sizeof(buffer));
+
	archive_entry_clear(entry);
+

+
	free(buffer);
+

+
	files = cJSON_GetObjectItem(manifest, "files");
+

+
	for (j = 0; j < cJSON_GetArraySize(files); j++) {
+
		file = cJSON_GetArrayItem(files, j);
+
		filepath = cJSON_GetObjectItem(file, "path")->valuestring;
+
		archive_entry_copy_sourcepath(entry, filepath);
+

+
		if (archive_read_disk_entry_from_file(ar, entry, -1, 0) != ARCHIVE_OK)
+
			warnx(archive_error_string(ar));
+

+
		archive_entry_set_pathname(entry, filepath);
+
		archive_write_header(pkg_archive, entry);
+
		fd = open(filepath, O_RDONLY);
+
		if (fd != -1) {
+
			while ( (len = read(fd, buf, sizeof(buf))) > 0 )
+
				archive_write_data(pkg_archive, buf, len);
+

+
			close(fd);
+
		}
+
		archive_entry_clear(entry);
+
	}
+

+
	cJSON_Delete(manifest);
+
	archive_entry_free(entry);
+
	archive_read_finish(ar);
+

+
	return (0);
+
}
+

+
int
+
pkg_create(char *pkgname, pkg_formats format, char *outdir, char *rootdir)
+
{
+
	struct pkgdb db;
+
	struct pkg *pkg;
+
	char *pkgdb_dir;
+
	char pkgpath[MAXPATHLEN];
+
	struct archive *pkg_archive;
+
	char archive_path[MAXPATHLEN];
+
	const char *ext;
+

+
	switch (format) {
+
		case TAR:
+
			ext = "tar";
+
			break;
+
		case TGZ:
+
			ext = "tgz";
+
			break;
+
		case TBZ:
+
			ext = "tbz";
+
			break;
+
		case TXZ:
+
			ext = "txz";
+
			break;
+
		default:
+
			warnx("Unsupport format");
+
			return (-1);
+
			break; /* NOT REACHED */
+
	}
+

+
	pkgdb_dir = getenv("PKG_DBDIR");
+

+
	pkgdb_init(&db, pkgname);
+

+
	if (pkgdb_count(&db) == 0) {
+
		warnx("%s: no such package", pkgname);
+
		return (-1);
+
	}
+

+
	TAILQ_FOREACH(pkg, &db.pkgs, entry) {
+
		printf("Creating package %s/%s-%s.%s\n", outdir, pkg->name, pkg->version, ext);
+
		snprintf(pkgpath, sizeof(pkgpath), "%s/%s-%s/", pkgdb_dir ? pkgdb_dir : PKG_DBDIR, pkg->name, pkg->version);
+
		snprintf(archive_path, sizeof(archive_path), "%s/%s-%s.%s", outdir, pkg->name, pkg->version, ext);
+

+
		pkg_archive = archive_write_new();
+

+
		switch (format) {
+
			case TAR:
+
				archive_write_set_compression_none(pkg_archive);
+
				break;
+
			case TGZ:
+
				archive_write_set_compression_gzip(pkg_archive);
+
				break;
+
			case TBZ:
+
				archive_write_set_compression_bzip2(pkg_archive);
+
				break;
+
			case TXZ:
+
				if (archive_write_set_compression_lzma(pkg_archive) != ARCHIVE_OK) {
+
					warnx(archive_error_string(pkg_archive));
+
				}
+
				break;
+
		}
+

+
		archive_write_set_format_pax_restricted(pkg_archive);
+
		archive_write_open_filename(pkg_archive, archive_path);
+
		pkg_create_from_dir(pkgpath, rootdir, pkg_archive);
+
		archive_write_close(pkg_archive);
+
		archive_write_finish(pkg_archive);
+
	}
+
	return (0);
+
}