Beispiel #1
0
void
pkg_shutdown(void)
{
	if (!parsed) {
		pkg_emit_error("pkg_shutdown() must be called after pkg_init()");
		_exit(EX_SOFTWARE);
		/* NOTREACHED */
	}

	ucl_object_unref(config);
	HASH_FREE(repos, pkg_repo_free);

	parsed = false;

	return;
}
Beispiel #2
0
pkg_formats
packing_format_from_string(const char *str)
{
	if (str == NULL)
		return TXZ;
	if (strcmp(str, "txz") == 0)
		return TXZ;
	if (strcmp(str, "tbz") == 0)
		return TBZ;
	if (strcmp(str, "tgz") == 0)
		return TGZ;
	if (strcmp(str, "tar") == 0)
		return TAR;
	pkg_emit_error("unknown format %s, using txz", str);
	return TXZ;
}
Beispiel #3
0
Datei: utils.c Projekt: dpl0/pkg
bool
is_valid_abi(const char *arch, bool emit_error) {
	const char *myarch;

	myarch = pkg_object_string(pkg_config_get("ABI"));

	if (fnmatch(arch, myarch, FNM_CASEFOLD) == FNM_NOMATCH &&
	    strncmp(arch, myarch, strlen(myarch)) != 0) {
		if (emit_error)
			pkg_emit_error("wrong architecture: %s instead of %s",
			    arch, myarch);
		return (false);
	}

	return (true);
}
Beispiel #4
0
static ucl_object_t *
keyword_open_schema(void)
{
	struct ucl_parser *parser;
	static const char keyword_schema_str[] = ""
		"{"
		"  type = object;"
		"  properties {"
		"    actions = { "
		"      type = array; "
		"      items = { type = string }; "
		"      uniqueItems: true "
		"    }; "
		"    attributes = { "
		"      type = object; "
		"      properties { "
		"        owner = { type = string }; "
		"        group = { type = string }; "
		"        mode = { oneOf: [ { type = integer }, { type = string } ] }; "
		"      }"
		"    }; "
		"    pre-install = { type = string }; "
		"    post-install = { type = string }; "
		"    pre-deinstall = { type = string }; "
		"    post-deinstall = { type = string }; "
		"    pre-upgrade = { type = string }; "
		"    post-upgrade = { type = string }; "
		"  }"
		"}";

	if (keyword_schema != NULL)
		return (keyword_schema);

	parser = ucl_parser_new(0);
	if (!ucl_parser_add_chunk(parser, keyword_schema_str,
	    sizeof(keyword_schema_str) -1)) {
		pkg_emit_error("Cannot parse schema for keywords: %s",
		    ucl_parser_get_error(parser));
		ucl_parser_free(parser);
		return (NULL);
	}

	keyword_schema = ucl_parser_get_object(parser);
	ucl_parser_free(parser);

	return (keyword_schema);
}
Beispiel #5
0
static RSA *
_load_rsa_public_key_buf(unsigned char *cert, int certlen)
{
	RSA *rsa = NULL;
	BIO *bp;
	char errbuf[1024];

	bp = BIO_new_mem_buf((void *)cert, certlen);
	if (!PEM_read_bio_RSA_PUBKEY(bp, &rsa, NULL, NULL)) {
		pkg_emit_error("error reading public key: %s",
		    ERR_error_string(ERR_get_error(), errbuf));
		BIO_free(bp);
		return (NULL);
	}
	BIO_free(bp);
	return (rsa);
}
Beispiel #6
0
int
pkg_delete_files(struct pkg *pkg, unsigned force)
	/* force: 0 ... be careful and vocal about it. 
	 *        1 ... remove files without bothering about checksums.
	 *        2 ... like 1, but remain silent if removal fails.
	 */
{
	struct pkg_file	*file = NULL;
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	const char	*path;
	char		fpath[MAXPATHLEN];

	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *sum = pkg_file_cksum(file);
		ucl_object_t *obj;

		if (file->keep == 1)
			continue;

		path = pkg_file_path(file);
		obj = pkg_annotation_lookup(pkg, "relocated");
		snprintf(fpath, sizeof(fpath), "%s%s",
		    obj ? pkg_object_string(obj) : "" , path );

		/* Regular files and links */
		/* check sha256 */
		if (!force && sum[0] != '\0') {
			if (sha256_file(fpath, sha256) != EPKG_OK)
				continue;
			if (strcmp(sha256, sum)) {
				pkg_emit_error("%s fails original SHA256 "
				    "checksum, not removing", path);
				continue;
			}
		}

		if (unlink(fpath) == -1) {
			if (force < 2)
				pkg_emit_errno("unlink", fpath);
			continue;
		}
	}

	return (EPKG_OK);
}
Beispiel #7
0
static int
pkg_repo_fetch_remote_tmp(struct pkg_repo *repo,
		const char *filename, const char *extension, time_t *t, int *rc)
{
	char url[MAXPATHLEN];
	char tmp[MAXPATHLEN];
	int fd;
	const char *tmpdir, *dot;

	/*
	 * XXX: here we support old naming scheme, such as filename.yaml
	 */
	dot = strrchr(filename, '.');
	if (dot != NULL) {
		snprintf(tmp, MIN(sizeof(tmp), dot - filename + 1), "%s", filename);
		snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), tmp,
				extension);
	}
	else {
		snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), filename,
				extension);
	}

	tmpdir = getenv("TMPDIR");
	if (tmpdir == NULL)
		tmpdir = "/tmp";
	mkdirs(tmpdir);
	snprintf(tmp, sizeof(tmp), "%s/%s.%s.XXXXXX", tmpdir, filename, extension);

	fd = mkstemp(tmp);
	if (fd == -1) {
		pkg_emit_error("Could not create temporary file %s, "
		    "aborting update.\n", tmp);
		*rc = EPKG_FATAL;
		return (-1);
	}
	(void)unlink(tmp);

	if ((*rc = pkg_fetch_file_to_fd(repo, url, fd, t)) != EPKG_OK) {
		close(fd);
		fd = -1;
	}

	return (fd);
}
Beispiel #8
0
static int
parse_sequence(struct pkg * pkg, yaml_node_t *node, yaml_document_t *doc, int attr)
{
	yaml_node_item_t *item;
	yaml_node_t *val;

	item = node->data.sequence.items.start;
	while (item < node->data.sequence.items.top) {
		val = yaml_document_get_node(doc, *item);
		switch (attr) {
			case PKG_CONFLICTS:
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_emit_error("Skipping malformed conflict");
				else
					pkg_addconflict(pkg, val->data.scalar.value);
				break;
			case PKG_CATEGORIES:
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_emit_error("Skipping malformed category");
				else
					pkg_addcategory(pkg, val->data.scalar.value);
				break;
			case PKG_LICENSES:
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_emit_error("Skipping malformed license");
				else
					pkg_addlicense(pkg, val->data.scalar.value);
				break;
			case PKG_USERS:
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_emit_error("Skipping malformed license");
				else
					pkg_adduser(pkg, val->data.scalar.value);
				break;
			case PKG_GROUPS:
				if (val->type != YAML_SCALAR_NODE || val->data.scalar.length <= 0)
					pkg_emit_error("Skipping malformed license");
				else
					pkg_addgroup(pkg, val->data.scalar.value);
				break;
			case PKG_DIRS:
				if (val->type == YAML_SCALAR_NODE && val->data.scalar.length > 0)
					pkg_adddir(pkg, val->data.scalar.value, 1);
				else if (val->type == YAML_MAPPING_NODE)
					parse_mapping(pkg, val, doc, attr);
				else
					pkg_emit_error("Skipping malformed dirs");
		}
		++item;
	}
	return (EPKG_OK);
}
Beispiel #9
0
static int
set_repo_user_version(sqlite3 *sqlite, const char *database, int reposcver)
{
    int		 retcode = EPKG_OK;
    char		 sql[BUFSIZ];
    char		*errmsg;
    const char	*fmt = "PRAGMA %Q.user_version = %d;" ;

    assert(database != NULL);

    sqlite3_snprintf(sizeof(sql), sql, fmt, database, reposcver);

    if (sqlite3_exec(sqlite, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
        pkg_emit_error("sqlite: %s", errmsg);
        sqlite3_free(errmsg);
        retcode = EPKG_FATAL;
    }
    return (retcode);
}
Beispiel #10
0
static int
pkg_set_licenselogic_from_node(struct pkg *pkg, yaml_node_t *val,
    __unused yaml_document_t *doc, __unused int attr)
{
	if (!strcmp(val->data.scalar.value, "single"))
		pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t) LICENSE_SINGLE);
	else if (!strcmp(val->data.scalar.value, "or") ||
	    !strcmp(val->data.scalar.value, "dual"))
		pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t)LICENSE_OR);
	else if (!strcmp(val->data.scalar.value, "and") ||
	    !strcmp(val->data.scalar.value, "multi"))
		pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t)LICENSE_AND);
	else {
		pkg_emit_error("Unknown license logic: %s",
		    val->data.scalar.value);
		return (EPKG_FATAL);
	}
	return (EPKG_OK);
}
Beispiel #11
0
int
pkg_create_installed(const char *outdir, pkg_formats format, struct pkg *pkg)
{
	struct packing	*pkg_archive;

	unsigned	 required_flags = PKG_LOAD_DEPS | PKG_LOAD_FILES |
		PKG_LOAD_CATEGORIES | PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS |
		PKG_LOAD_OPTIONS | PKG_LOAD_MTREE | PKG_LOAD_LICENSES ;

	assert(pkg->type == PKG_INSTALLED || pkg->type == PKG_OLD_FILE);

	pkg_archive = pkg_create_archive(outdir, pkg, format, required_flags);
	if (pkg_archive == NULL) {
		pkg_emit_error("unable to create archive");
		return (EPKG_FATAL);
	}

	pkg_create_from_dir(pkg, NULL, pkg_archive);

	return packing_finish(pkg_archive);
}
Beispiel #12
0
static void
walk_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
{
	const ucl_object_t *cur;
	ucl_object_iter_t it = NULL;
	struct pkg_repo *r;
	const char *key;

	while ((cur = ucl_iterate_object(obj, &it, true))) {
		key = ucl_object_key(cur);
		pkg_debug(1, "PkgConfig: parsing key '%s'", key);
		r = pkg_repo_find(key);
		if (r != NULL)
			pkg_debug(1, "PkgConfig: overwriting repository %s", key);
		if (cur->type == UCL_OBJECT)
			add_repo(cur, r, key, flags);
		else
			pkg_emit_error("Ignoring bad configuration entry in %s: %s",
			    file, ucl_object_emit(cur, UCL_EMIT_YAML));
	}
}
Beispiel #13
0
int
pkg_delete_files(struct pkg *pkg, unsigned force)
	/* force: 0 ... be careful and vocal about it. 
	 *        1 ... remove files without bothering about checksums.
	 *        2 ... like 1, but remain silent if removal fails.
	 */
{
	struct pkg_file	*file = NULL;
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	const char	*path;

	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *sum = pkg_file_cksum(file);

		if (file->keep == 1)
			continue;

		path = pkg_file_path(file);

		/* Regular files and links */
		/* check sha256 */
		if (!force && sum[0] != '\0') {
			if (sha256_file(path, sha256) != EPKG_OK)
				continue;
			if (strcmp(sha256, sum)) {
				pkg_emit_error("%s fails original SHA256 "
				    "checksum, not removing", path);
				continue;
			}
		}

		if (unlink(path) == -1) {
			if (force < 2)
				pkg_emit_errno("unlink", path);
			continue;
		}
	}

	return (EPKG_OK);
}
Beispiel #14
0
static int
urldecode(const char *src, struct sbuf **dest)
{
	size_t len;
	size_t i;
	char c;
	char hex[] = {'\0', '\0', '\0'};

	sbuf_init(dest);

	len = strlen(src);
	for (i = 0; i < len; i++) {
		if (src[i] != '%') {
			sbuf_putc(*dest, src[i]);
		} else {
			if (i + 2 > len) {
				pkg_emit_error("unexpected end of string");
				return (EPKG_FATAL);
			}

			hex[0] = src[++i];
			hex[1] = src[++i];
			errno = 0;
			c = strtol(hex, NULL, 16);
			if (errno != 0) {
				/*
				 * if it fails consider this is not a urlencoded
				 * information
				 */
				sbuf_printf(*dest, "%%%s", hex);
			} else {
				sbuf_putc(*dest, c);
			}
		}
	}
	sbuf_finish(*dest);

	return (EPKG_OK);
}
Beispiel #15
0
static RSA *
load_rsa_public_key(const char *rsa_key_path)
{
	FILE *fp;
	RSA *rsa = NULL;
	char errbuf[1024];

	if ((fp = fopen(rsa_key_path, "rb")) == 0) {
		pkg_emit_errno("fopen", rsa_key_path);
		return (NULL);
	}

	if (!PEM_read_RSA_PUBKEY( fp, &rsa, NULL, NULL )) {
		pkg_emit_error("error reading public key(%s): %s", rsa_key_path,
					   ERR_error_string(ERR_get_error(), errbuf));
		fclose(fp);
		return (NULL);
	}

	fclose(fp);
	return (rsa);
}
Beispiel #16
0
bool
pkg_compiled_for_same_os_major(void)
{
#ifdef OSMAJOR
	struct utsname	u;
	int		osmajor;

	/* Are we running the same OS major version as the one we were
	 * compiled under? */

	if (uname(&u) != 0) {
		pkg_emit_error("Cannot determine OS version number");
		return (true);	/* Can't tell, so assume yes  */
	}

	osmajor = (int) strtol(u.release, NULL, 10);

	return (osmajor == OSMAJOR);
#else
	return (true);		/* Can't tell, so assume yes  */
#endif
}
Beispiel #17
0
static int
rsa_verify_cert_cb(int fd, void *ud)
{
	struct rsa_verify_cbdata *cbdata = ud;
	char *sha256;
	char *hash;
	char errbuf[1024];
	RSA *rsa = NULL;
	int ret;

	sha256 = pkg_checksum_fd(fd, PKG_HASH_TYPE_SHA256_HEX);
	if (sha256 == NULL)
		return (EPKG_FATAL);

	hash = pkg_checksum_data(sha256, strlen(sha256),
	    PKG_HASH_TYPE_SHA256_RAW);
	free(sha256);

	rsa = _load_rsa_public_key_buf(cbdata->key, cbdata->keylen);
	if (rsa == NULL) {
		free(hash);
		return (EPKG_FATAL);
	}
	ret = RSA_verify(NID_sha256, hash,
	    pkg_checksum_type_size(PKG_HASH_TYPE_SHA256_RAW), cbdata->sig,
	    cbdata->siglen, rsa);
	free(hash);
	if (ret == 0) {
		pkg_emit_error("rsa verify failed: %s",
				ERR_error_string(ERR_get_error(), errbuf));
		RSA_free(rsa);
		return (EPKG_FATAL);
	}

	RSA_free(rsa);

	return (EPKG_OK);
}
Beispiel #18
0
static int
urldecode(const char *src, struct sbuf **dest)
{
	size_t len;
	size_t i;
	char c;
	char hex[] = {'\0', '\0', '\0'};

	if (*dest == NULL)
		*dest = sbuf_new_auto();
	else
		sbuf_reset(*dest);

	len = strlen(src);
	for (i = 0; i < len; i++) {
		if (src[i] != '%') {
			sbuf_putc(*dest, src[i]);
		} else {
			if (i + 2 > len) {
				pkg_emit_error("unexpected end of string");
				return (EPKG_FATAL);
			}

			hex[0] = src[++i];
			hex[1] = src[++i];
			errno = 0;
			c = strtol(hex, NULL, 16);
			if (errno != 0) {
				pkg_emit_errno("strtol()", hex);
				return (EPKG_FATAL);
			}
			sbuf_putc(*dest, c);
		}
	}
	sbuf_finish(*dest);

	return (EPKG_OK);
}
Beispiel #19
0
/* The "no concessions to old pkg_tools" variant: just get everything
 * from the manifest */
int
pkg_create_from_manifest(const char *outdir, pkg_formats format,
    const char *rootdir, const char *manifest, const char *plist)
{
	struct pkg	*pkg = NULL;
	struct packing	*pkg_archive = NULL;
	int		 ret = ENOMEM;

	pkg_debug(1, "Creating package from stage directory: '%s'", rootdir);

	if(pkg_new(&pkg, PKG_FILE) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}

	if ((ret = pkg_load_metadata(pkg, manifest, NULL, plist, rootdir, false))
	    != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}

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

	if ((ret = pkg_create_from_dir(pkg, rootdir, pkg_archive)) != EPKG_OK)
		pkg_emit_error("package creation failed");

cleanup:
	free(pkg);
	packing_finish(pkg_archive);
	return (ret);
}
Beispiel #20
0
static int
pkg_string(struct pkg *pkg, ucl_object_t *obj, int attr)
{
	int ret = EPKG_OK;
	const char *str;
	str = ucl_object_tostring_forced(obj);

	switch (attr)
	{
	case PKG_INFOS:
		pkg_addannotation(pkg, "_INFOS_", str);
		break;
	case PKG_LICENSE_LOGIC:
		if (!strcmp(str, "single"))
			pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t) LICENSE_SINGLE);
		else if (!strcmp(str, "or") ||
		         !strcmp(str, "dual"))
			pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t)LICENSE_OR);
		else if (!strcmp(str, "and") ||
		         !strcmp(str, "multi"))
			pkg_set(pkg, PKG_LICENSE_LOGIC, (int64_t)LICENSE_AND);
		else {
			pkg_emit_error("Unknown license logic: %s", str);
			ret = EPKG_FATAL;
		}
		break;
	default:
		if (attr == PKG_DESC)
			ret = urldecode(str, &pkg->fields[attr]);
		else
			ret = pkg_set(pkg, attr, str);
		break;
	}

	return (ret);
}
Beispiel #21
0
static int
pkg_repo_binary_update_incremental(const char *name, struct pkg_repo *repo,
	time_t *mtime, bool force)
{
	FILE *fmanifest = NULL, *fdigests = NULL /*, *fconflicts = NULL*/;
	struct pkg *pkg = NULL;
	int rc = EPKG_FATAL;
	sqlite3 *sqlite = NULL;
	sqlite3_stmt *stmt;
	const char *origin, *digest, *offset, *length, *checksum;
	char *linebuf = NULL, *p;
	int updated = 0, removed = 0, added = 0, processed = 0, pushed = 0;
	long num_offset, num_length;
	time_t local_t;
	time_t digest_t;
	time_t packagesite_t;
	struct pkg_increment_task_item *ldel = NULL, *ladd = NULL,
			*item, *tmp_item;
	struct pkg_manifest_key *keys = NULL;
	size_t linecap = 0;
	ssize_t linelen;
	char *map = MAP_FAILED;
	size_t len = 0;
	int hash_it = 0;
	bool in_trans = false, legacy_repo = false;
	/* Required for making iterator */
	struct pkgdb_it *it = NULL;
	struct pkgdb fakedb;

	pkg_debug(1, "Pkgrepo, begin incremental update of '%s'", name);

	/* In forced mode, ignore mtime */
	if (force)
		*mtime = 0;

	/* Fetch meta */
	local_t = *mtime;
	if (pkg_repo_fetch_meta(repo, &local_t) == EPKG_FATAL)
		pkg_emit_notice("repository %s has no meta file, using "
		    "default settings", repo->name);

	/* Fetch digests */
	local_t = *mtime;
	fdigests = pkg_repo_fetch_remote_extract_tmp(repo,
			repo->meta->digests, &local_t, &rc);
	if (fdigests == NULL)
		goto cleanup;

	/* Fetch packagesite */
	digest_t = local_t;
	local_t = *mtime;
	fmanifest = pkg_repo_fetch_remote_extract_tmp(repo,
			repo->meta->manifests, &local_t, &rc);
	if (fmanifest == NULL)
		goto cleanup;

	packagesite_t = local_t;
	*mtime = digest_t;
	/*fconflicts = repo_fetch_remote_extract_tmp(repo,
			repo_conflicts_archive, "txz", &local_t,
			&rc, repo_conflicts_file);*/
	fseek(fmanifest, 0, SEEK_END);
	len = ftell(fmanifest);

	/* Detect whether we have legacy repo */
	if ((linelen = getline(&linebuf, &linecap, fdigests)) > 0) {
		p = linebuf;
		origin = strsep(&p, ":");
		digest = strsep(&p, ":");
		if (digest == NULL) {
			pkg_emit_error("invalid digest file format");
			rc = EPKG_FATAL;
			goto cleanup;
		}
		if (!pkg_checksum_is_valid(digest, strlen(digest))) {
			legacy_repo = true;
			pkg_debug(1, "repository '%s' has a legacy digests format", repo->name);
		}
	}
	fseek(fdigests, 0, SEEK_SET);

	/* Load local repository data */
	rc = pkg_repo_binary_init_update(repo, name, force);
	if (rc == EPKG_END) {
		/* Need to perform forced update */
		repo->ops->close(repo, false);
		return (pkg_repo_binary_update_incremental(name, repo, mtime, true));
	}
	if (rc != EPKG_OK) {
		rc = EPKG_FATAL;
		goto cleanup;
	}

	/* Here sqlite is initialized */
	sqlite = PRIV_GET(repo);

	stmt = pkg_repo_binary_get_origins(sqlite);
	if (stmt == NULL) {
		rc = EPKG_FATAL;
		goto cleanup;
	}
	fakedb.sqlite = sqlite;
	it = pkgdb_it_new_sqlite(&fakedb, stmt, PKG_REMOTE, PKGDB_IT_FLAG_ONCE);

	if (it != NULL) {
		while (pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC) == EPKG_OK) {
			pkg_get(pkg, PKG_ORIGIN, &origin, legacy_repo ? PKG_OLD_DIGEST : PKG_DIGEST,
							&digest, PKG_CKSUM, &checksum);
			pkg_repo_binary_update_item_new(&ldel, origin, digest, 0, 0, checksum);
		}

		pkgdb_it_free(it);
	}
	else {
		sqlite3_finalize(stmt);
	}

	pkg_debug(1, "Pkgrepo, reading new packagesite.yaml for '%s'", name);
	/* load the while digests */
	while ((linelen = getline(&linebuf, &linecap, fdigests)) > 0) {
		p = linebuf;
		origin = strsep(&p, ":");
		digest = strsep(&p, ":");
		offset = strsep(&p, ":");
		/* files offset */
		strsep(&p, ":");
		length = p ? strsep(&p, ":\n") : NULL;
		checksum = p ? strsep(&p, ":\n") : NULL;

		if (origin == NULL || digest == NULL ||
				offset == NULL) {
			pkg_emit_error("invalid digest file format");
			rc = EPKG_FATAL;
			goto cleanup;
		}
		errno = 0;
		num_offset = (long)strtoul(offset, NULL, 10);
		if (errno != 0) {
			pkg_emit_errno("strtoul", "digest format error");
			rc = EPKG_FATAL;
			goto cleanup;
		}
		if (length != NULL) {
			errno = 0;
			num_length = (long)strtoul(length, NULL, 10);
			if (errno != 0) {
				pkg_emit_errno("strtoul", "digest format error");
				rc = EPKG_FATAL;
				goto cleanup;
			}
		}
		else {
			num_length = 0;
		}
		processed++;
		HASH_FIND_STR(ldel, origin, item);
		if (item == NULL) {
			added++;
			pkg_repo_binary_update_item_new(&ladd, origin, digest, num_offset,
					num_length, checksum);
		} else {
			HASH_DEL(ldel, item);
			if (checksum == NULL || item->checksum == NULL) {
				pkg_repo_binary_update_item_new(&ladd, origin, digest,
						num_offset, num_length, checksum);
				updated++;
			}
			else if (strcmp(checksum, item->checksum) != 0) {
				/* Allow checksum to be used as unique mark */
				pkg_repo_binary_update_item_new(&ladd, origin, digest,
					num_offset, num_length, checksum);
				updated++;
			}

			pkg_repo_binary_update_item_free(item);
		}
	}

	rc = EPKG_OK;

	pkg_debug(1, "Pkgrepo, removing old entries for '%s'", name);

	rc = pkgdb_transaction_begin(sqlite, "REPO");
	if (rc != EPKG_OK)
		goto cleanup;

	in_trans = true;

	removed = HASH_COUNT(ldel);
	hash_it = 0;
	if (removed > 0)
		pkg_emit_progress_start("Removing expired repository entries");
	HASH_ITER(hh, ldel, item, tmp_item) {
		pkg_emit_progress_tick(++hash_it, removed);
		if (rc == EPKG_OK) {
			rc = pkgdb_repo_remove_package(item->origin);
		}
		else {
			pkg_emit_progress_tick(removed, removed);
		}
		HASH_DEL(ldel, item);
		pkg_repo_binary_update_item_free(item);
	}
Beispiel #22
0
int
pkgdb_repo_check_version(struct pkgdb *db, const char *database)
{
    int reposcver;
    int repomajor;
    int ret;

    assert(db != NULL);
    assert(database != NULL);

    if ((ret = get_repo_user_version(db->sqlite, database, &reposcver))
            != EPKG_OK)
        return (ret);	/* sqlite error */

    /*
     * If the local pkgng uses a repo schema behind that used to
     * create the repo, we may still be able use it for reading
     * (ie pkg install), but pkg repo can't do an incremental
     * update unless the actual schema matches the compiled in
     * schema version.
     *
     * Use a major - minor version schema: as the user_version
     * PRAGMA takes an integer version, encode this as MAJOR *
     * 1000 + MINOR.
     *
     * So long as the major versions are the same, the local pkgng
     * should be compatible with any repo created by a more recent
     * pkgng, although it may need some modification of the repo
     * schema
     */

    /* --- Temporary ---- Grandfather in the old repo schema
       version so this patch doesn't immediately invalidate all
       the repos out there */

    if (reposcver == 2)
        reposcver = 2000;
    if (reposcver == 3)
        reposcver = 2001;

    repomajor = reposcver / 1000;

    if (repomajor < REPO_SCHEMA_MAJOR) {
        pkg_emit_error("Repo %s (schema version %d) is too old - "
                       "need at least schema %d", database, reposcver,
                       REPO_SCHEMA_MAJOR * 1000);
        return (EPKG_REPOSCHEMA);
    }

    if (repomajor > REPO_SCHEMA_MAJOR) {
        pkg_emit_error("Repo %s (schema version %d) is too new - "
                       "we can accept at most schema %d", database, reposcver,
                       ((REPO_SCHEMA_MAJOR + 1) * 1000) - 1);
        return (EPKG_REPOSCHEMA);
    }

    /* This is a repo schema version we can work with */

    ret = EPKG_OK;

    if (reposcver < REPO_SCHEMA_VERSION) {
        if (sqlite3_db_readonly(db->sqlite, database)) {
            pkg_emit_error("Repo %s needs schema upgrade from "
                           "%d to %d but it is opened readonly", database,
                           reposcver, REPO_SCHEMA_VERSION
                          );
            ret = EPKG_FATAL;
        } else
            ret = upgrade_repo_schema(db, database, reposcver);
    } else if (reposcver > REPO_SCHEMA_VERSION) {
        if (sqlite3_db_readonly(db->sqlite, database)) {
            pkg_emit_error("Repo %s needs schema downgrade from "
                           "%d to %d but it is opened readonly", database,
                           reposcver, REPO_SCHEMA_VERSION
                          );
            ret = EPKG_FATAL;
        } else
            ret = downgrade_repo_schema(db, database, reposcver);
    }

    return (ret);
}
Beispiel #23
0
static int
apply_repo_change(struct pkgdb *db, const char *database,
                  const struct repo_changes *repo_changes, const char *updown,
                  int version, int *next_version)
{
    const struct repo_changes	*change;
    bool			 found = false, in_trans = false;
    int			 ret = EPKG_OK;
    char			 sql[8192];
    char			*errmsg;

    for (change = repo_changes; change->version != -1; change++) {
        if (change->version == version) {
            found = true;
            break;
        }
    }
    if (!found) {
        pkg_emit_error("Failed to %s \"%s\" repo schema "
                       " version %d (target version %d) "
                       "-- change not found", updown, database, version,
                       REPO_SCHEMA_VERSION);
        return (EPKG_FATAL);
    }

    /* substitute the repo database name */
    ret = substitute_into_sql(sql, sizeof(sql), change->sql, database);

    /* begin transaction */
    if (ret == EPKG_OK) {
        in_trans = true;
        ret = pkgdb_transaction_begin(db->sqlite, "SCHEMA");
    }

    /* apply change */
    if (ret == EPKG_OK) {
        pkg_debug(4, "Pkgdb: running '%s'", sql);
        ret = sqlite3_exec(db->sqlite, sql, NULL, NULL, &errmsg);
        if (ret != SQLITE_OK) {
            pkg_emit_error("sqlite: %s", errmsg);
            sqlite3_free(errmsg);
            ret = EPKG_FATAL;
        }
    }

    /* update repo user_version */
    if (ret == EPKG_OK) {
        *next_version = change->next_version;
        ret = set_repo_user_version(db->sqlite, database, *next_version);
    }

    /* commit or rollback */
    if (in_trans) {
        if (ret != EPKG_OK)
            pkgdb_transaction_rollback(db->sqlite, "SCHEMA");

        if (pkgdb_transaction_commit(db->sqlite, "SCHEMA") != EPKG_OK)
            ret = EPKG_FATAL;
    }

    if (ret == EPKG_OK) {
        pkg_emit_notice("Repo \"%s\" %s schema %d to %d: %s",
                        database, updown, version,
                        change->next_version, change->message);
    }

    return (ret);
}
Beispiel #24
0
static int
pkg_create_from_dir(struct pkg *pkg, const char *root,
    struct packing *pkg_archive)
{
	char		 fpath[MAXPATHLEN];
	struct pkg_file	*file = NULL;
	struct pkg_dir	*dir = NULL;
	char		*m;
	int		 ret;
	const char	*mtree;
	bool		 developer;
	struct stat	 st;
	char		 sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	int64_t		 flatsize = 0;
	ucl_object_t	*obj;

	if (pkg_is_valid(pkg) != EPKG_OK) {
		pkg_emit_error("the package is not valid");
		return (EPKG_FATAL);
	}

	obj = pkg_annotation_lookup(pkg, "relocated");

	/*
	 * Get / compute size / checksum if not provided in the manifest
	 */
	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *pkg_path = pkg_file_path(file);
		const char *pkg_sum = pkg_file_cksum(file);

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
		    obj ? pkg_object_string(obj) : "", pkg_path);

		if (lstat(fpath, &st) != 0 || S_ISLNK(st.st_mode))
			continue;

		if (file->size == 0)
			file->size = (int64_t)st.st_size;
		flatsize += file->size;

		if (pkg_sum == NULL || pkg_sum[0] == '\0') {
			if (pkg->type == PKG_OLD_FILE) {
				if (md5_file(fpath, sha256) != EPKG_OK)
					return (EPKG_FATAL);
			} else {
				if (sha256_file(fpath, sha256) != EPKG_OK)
					return (EPKG_FATAL);
			}
			strlcpy(file->sum, sha256, sizeof(file->sum));
		}
	}
	pkg_set(pkg, PKG_FLATSIZE, flatsize);

	if (pkg->type == PKG_OLD_FILE) {
		const char *desc, *display, *comment;
		char oldcomment[BUFSIZ];

		pkg_old_emit_content(pkg, &m);
		packing_append_buffer(pkg_archive, m, "+CONTENTS", strlen(m));
		free(m);

		pkg_get(pkg, PKG_DESC, &desc, PKG_MESSAGE, &display, PKG_COMMENT, &comment);
		packing_append_buffer(pkg_archive, desc, "+DESC", strlen(desc));
		packing_append_buffer(pkg_archive, display, "+DISPLAY", strlen(display));
		snprintf(oldcomment, sizeof(oldcomment), "%s\n", comment);
		packing_append_buffer(pkg_archive, oldcomment, "+COMMENT", strlen(oldcomment));
	} else {
		/*
		 * Register shared libraries used by the package if
		 * SHLIBS enabled in conf.  Deletes shlib info if not.
		 */
		struct sbuf *b = sbuf_new_auto();

		pkg_register_shlibs(pkg, root);

		pkg_emit_manifest_sbuf(pkg, b, PKG_MANIFEST_EMIT_COMPACT, NULL);
		packing_append_buffer(pkg_archive, sbuf_data(b), "+COMPACT_MANIFEST", sbuf_len(b));
		sbuf_clear(b);
		pkg_emit_manifest_sbuf(pkg, b, 0, NULL);
		sbuf_finish(b);
		packing_append_buffer(pkg_archive, sbuf_data(b), "+MANIFEST", sbuf_len(b));
		sbuf_delete(b);
	}

	pkg_get(pkg, PKG_MTREE, &mtree);
	if (mtree != NULL)
		packing_append_buffer(pkg_archive, mtree, "+MTREE_DIRS",
		    strlen(mtree));

	while (pkg_files(pkg, &file) == EPKG_OK) {
		const char *pkg_path = pkg_file_path(file);

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
		    obj ? pkg_object_string(obj) : "", pkg_path);

		ret = packing_append_file_attr(pkg_archive, fpath, pkg_path,
		    file->uname, file->gname, file->perm);
		developer = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
		if (developer && ret != EPKG_OK)
			return (ret);
	}

	while (pkg_dirs(pkg, &dir) == EPKG_OK) {
		const char *pkg_path = pkg_dir_path(dir);

		snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
		    obj ? pkg_object_string(obj) : "", pkg_path);

		ret = packing_append_file_attr(pkg_archive, fpath, pkg_path,
		    dir->uname, dir->gname, dir->perm);
		developer = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
		if (developer && ret != EPKG_OK)
			return (ret);
	}

	return (EPKG_OK);
}
Beispiel #25
0
int
pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
    const char *md_dir, char *plist, bool old)
{
	struct pkg	*pkg = NULL;
	struct pkg_file	*file = NULL;
	struct pkg_dir	*dir = NULL;
	struct packing	*pkg_archive = NULL;
	char		*manifest = NULL;
	char		 path[MAXPATHLEN];
	char		 arch[BUFSIZ];
	int		 ret = ENOMEM;
	char		*buf;
	int		 i;
	regex_t		 preg;
	regmatch_t	 pmatch[2];
	size_t		 size;
	char		*www = NULL;
	struct pkg_manifest_key *keys = NULL;

	pkg_debug(1, "Creating package from stage directory: '%s'", rootdir);

	/* Load the manifest from the metadata directory */
	if (snprintf(path, sizeof(path), "%s/+MANIFEST", md_dir) == -1)
		goto cleanup;

	if(pkg_new(&pkg, old ? PKG_OLD_FILE : PKG_FILE) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}

	pkg_manifest_keys_new(&keys);
	if ((ret = pkg_parse_manifest_file(pkg, path, keys)) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}

	/* if no descriptions provided then try to get it from a file */

	pkg_get(pkg, PKG_DESC, &buf);
	if (buf == NULL) {
		if (snprintf(path, sizeof(path), "%s/+DESC", md_dir) == -1)
			goto cleanup;
		if (access(path, F_OK) == 0) {
			pkg_debug(1, "Taking description from: '%s'", path);
			pkg_set_from_file(pkg, PKG_DESC, path, false);
		}
	}

	/* if no message try to get it from a file */
	pkg_get(pkg, PKG_MESSAGE, &buf);
	if (buf == NULL) {
		ret = snprintf(path, sizeof(path), "%s/+DISPLAY", md_dir);
		if (ret == -1)
			goto cleanup;
		if (access(path, F_OK) == 0) {
			pkg_debug(1, "Taking message from: '%s'", path);
			pkg_set_from_file(pkg, PKG_MESSAGE, path, false);
		}
	}

	/* if no arch autodetermine it */
	pkg_get(pkg, PKG_ARCH, &buf);
	if (buf == NULL) {
		pkg_get_myarch(arch, BUFSIZ);
		pkg_set(pkg, PKG_ARCH, arch);
	}

	/* if no mtree try to get it from a file */
	pkg_get(pkg, PKG_MTREE, &buf);
	if (buf == NULL) {
		ret = snprintf(path, sizeof(path), "%s/+MTREE_DIRS", md_dir);
		if (ret == -1)
			goto cleanup;
		if (access(path, F_OK) == 0) {
			pkg_debug(1, "Taking mtree definition from: '%s'", path);
			pkg_set_from_file(pkg, PKG_MTREE, path, false);
		}
	}

	for (i = 0; scripts[i] != NULL; i++) {
		snprintf(path, sizeof(path), "%s/%s", md_dir, scripts[i]);
		if (access(path, F_OK) == 0)
			pkg_addscript_file(pkg, path);
	}

	if (plist != NULL &&
	    ports_parse_plist(pkg, plist, rootdir) != EPKG_OK) {
		ret = EPKG_FATAL;
		goto cleanup;
	}

	/* if www is not given then try to determine it from description */
	if (www != NULL) {
		pkg_set(pkg, PKG_WWW, www);
		free(www);
	}

	pkg_get(pkg, PKG_WWW, &www);
	if (www == NULL) {
		pkg_get(pkg, PKG_DESC, &buf);
		if (buf == NULL) {
			pkg_emit_error("No www or desc defined in manifest");
			ret = EPKG_FATAL;
			goto cleanup;
		}
		regcomp(&preg, "^WWW:[[:space:]]*(.*)$",
		    REG_EXTENDED|REG_ICASE|REG_NEWLINE);
		if (regexec(&preg, buf, 2, pmatch, 0) == 0) {
			size = pmatch[1].rm_eo - pmatch[1].rm_so;
			www = strndup(&buf[pmatch[1].rm_so], size);
			pkg_set(pkg, PKG_WWW, www);
			free(www);
		} else {
			pkg_set(pkg, PKG_WWW, "UNKNOWN");
		}
		regfree(&preg);
	}

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

	/* XXX: autoplist support doesn't work right with meta-ports */
	if (0 && pkg_files(pkg, &file) != EPKG_OK &&
	    pkg_dirs(pkg, &dir) != EPKG_OK) {
		/* Now traverse the file directories, adding to the archive */
		packing_append_tree(pkg_archive, md_dir, NULL);
		packing_append_tree(pkg_archive, rootdir, "/");
	} else {
		pkg_create_from_dir(pkg, rootdir, pkg_archive);
	}

	ret = EPKG_OK;

cleanup:
	free(pkg);
	free(manifest);
	pkg_manifest_keys_free(keys);
	if (ret == EPKG_OK)
		ret = packing_finish(pkg_archive);
	return ret;
}
Beispiel #26
0
int
packing_append_file_attr(struct packing *pack, const char *filepath,
    const char *newpath, const char *uname, const char *gname, mode_t perm,
    u_long fflags)
{
	int fd;
	int retcode = EPKG_OK;
	int ret;
	time_t source_time;
	struct stat st;
	struct archive_entry *entry, *sparse_entry;
	bool unset_timestamp;
	const char *source_date_epoch;
	char buf[32768];
	int len;

	entry = archive_entry_new();
	archive_entry_copy_sourcepath(entry, filepath);

	pkg_debug(2, "Packing file '%s'", filepath);

	if (lstat(filepath, &st) != 0) {
		pkg_emit_errno("lstat", filepath);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	ret = archive_read_disk_entry_from_file(pack->aread, entry, -1,
			&st);
	if (ret != ARCHIVE_OK) {
		pkg_emit_error("%s: %s", filepath,
				archive_error_string(pack->aread));
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	if (newpath != NULL)
		archive_entry_set_pathname(entry, newpath);

	if (archive_entry_filetype(entry) != AE_IFREG) {
		archive_entry_set_size(entry, 0);
	}

	if (uname != NULL && uname[0] != '\0') {
		archive_entry_set_uname(entry, uname);
	}

	if (gname != NULL && gname[0] != '\0') {
		archive_entry_set_gname(entry, gname);
	}

	if (fflags > 0)
		archive_entry_set_fflags(entry, fflags, 0);

	if (perm != 0)
		archive_entry_set_perm(entry, perm);

	unset_timestamp = pkg_object_bool(pkg_config_get("UNSET_TIMESTAMP"));

	if (unset_timestamp) {
		archive_entry_unset_atime(entry);
		archive_entry_unset_ctime(entry);
		archive_entry_unset_mtime(entry);
		archive_entry_unset_birthtime(entry);
	}

	if ((source_date_epoch = getenv("SOURCE_DATE_EPOCH")) != NULL) {
		if (source_date_epoch[strspn(source_date_epoch, "0123456789")] != '\0') {
			pkg_emit_error("Bad environment variable "
			    "SOURCE_DATE_EPOCH: %s", source_date_epoch);
			retcode = EPKG_FATAL;
			goto cleanup;
		}
		source_time = strtoll(source_date_epoch, NULL, 10);
		archive_entry_set_atime(entry, source_time, 0);
		archive_entry_set_ctime(entry, source_time, 0);
		archive_entry_set_mtime(entry, source_time, 0);
		archive_entry_set_birthtime(entry, source_time, 0);
	}

	archive_entry_linkify(pack->resolver, &entry, &sparse_entry);

	if (sparse_entry != NULL && entry == NULL)
		entry = sparse_entry;

	archive_write_header(pack->awrite, entry);

	if (archive_entry_size(entry) <= 0)
		goto cleanup;

	if ((fd = open(filepath, O_RDONLY)) < 0) {
		pkg_emit_errno("open", filepath);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	while ((len = read(fd, buf, sizeof(buf))) > 0) {
		if (archive_write_data(pack->awrite, buf, len) == -1) {
			pkg_emit_errno("archive_write_data", "archive write error");
			retcode = EPKG_FATAL;
			break;
		}
	}

	if (len == -1) {
		pkg_emit_errno("read", "file read error");
		retcode = EPKG_FATAL;
	}
	close(fd);

cleanup:
	archive_entry_free(entry);
	return (retcode);
}
Beispiel #27
0
int
pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
{
	struct ucl_parser *p = NULL;
	size_t i;
	const char *val = NULL;
	const char *buf, *walk, *value, *key, *k;
	const char *evkey = NULL;
	const char *nsname = NULL;
	const char *evpipe = NULL;
	const ucl_object_t *cur, *object;
	ucl_object_t *obj = NULL, *o, *ncfg;
	ucl_object_iter_t it = NULL;
	struct sbuf *ukey = NULL;
	bool fatal_errors = false;

	k = NULL;
	o = NULL;

	pkg_get_myarch(myabi, BUFSIZ);
	pkg_get_myarch_legacy(myabi_legacy, BUFSIZ);
	if (parsed != false) {
		pkg_emit_error("pkg_init() must only be called once");
		return (EPKG_FATAL);
	}

	if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
	    ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
		pkg_emit_error("Invalid flags for pkg_init()");
		return (EPKG_FATAL);
	}

	config = ucl_object_typed_new(UCL_OBJECT);

	for (i = 0; i < c_size; i++) {
		switch (c[i].type) {
		case PKG_STRING:
			obj = ucl_object_fromstring_common(
			    c[i].def != NULL ? c[i].def : "", 0, UCL_STRING_TRIM);
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_INT:
			ucl_object_insert_key(config,
			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT),
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_BOOL:
			ucl_object_insert_key(config,
			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN),
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_OBJECT:
			obj = ucl_object_typed_new(UCL_OBJECT);
			if (c[i].def != NULL) {
				walk = buf = c[i].def;
				while ((buf = strchr(buf, ',')) != NULL) {
					key = walk;
					value = walk;
					while (*value != ',') {
						if (*value == '=')
							break;
						value++;
					}
					ucl_object_insert_key(obj,
					    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
					    key, value - key, false);
					buf++;
					walk = buf;
				}
				key = walk;
				value = walk;
				while (*value != ',') {
					if (*value == '=')
						break;
					value++;
				}
				if (o == NULL)
					o = ucl_object_typed_new(UCL_OBJECT);
				ucl_object_insert_key(o,
				    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
				    key, value - key, false);
			}
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		case PKG_ARRAY:
			obj = ucl_object_typed_new(UCL_ARRAY);
			if (c[i].def != NULL) {
				walk = buf = c[i].def;
				while ((buf = strchr(buf, ',')) != NULL) {
					ucl_array_append(obj,
					    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
					buf++;
					walk = buf;
				}
				ucl_array_append(obj,
				    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
			}
			ucl_object_insert_key(config, obj,
			    c[i].key, strlen(c[i].key), false);
			break;
		}
	}

	if (path == NULL)
		path = PREFIX"/etc/pkg.conf";

	p = ucl_parser_new(0);

	errno = 0;
	obj = NULL;
	if (!ucl_parser_add_file(p, path)) {
		if (errno != ENOENT)
			pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
	} else {
		obj = ucl_parser_get_object(p);

	}

	ncfg = NULL;
	while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
		sbuf_init(&ukey);
		key = ucl_object_key(cur);
		for (i = 0; key[i] != '\0'; i++)
			sbuf_putc(ukey, toupper(key[i]));
		sbuf_finish(ukey);
		object = ucl_object_find_keyl(config, sbuf_data(ukey), sbuf_len(ukey));

		if (strncasecmp(sbuf_data(ukey), "PACKAGESITE", sbuf_len(ukey))
		    == 0 || strncasecmp(sbuf_data(ukey), "PUBKEY",
		    sbuf_len(ukey)) == 0 || strncasecmp(sbuf_data(ukey),
		    "MIRROR_TYPE", sbuf_len(ukey)) == 0) {
			pkg_emit_error("%s in pkg.conf is no longer "
			    "supported.  Convert to the new repository style."
			    "  See pkg.conf(5)", sbuf_data(ukey));
			fatal_errors = true;
			continue;
		}

		/* ignore unknown keys */
		if (object == NULL)
			continue;

		if (object->type != cur->type) {
			pkg_emit_error("Malformed key %s, ignoring", key);
			continue;
		}

		if (ncfg == NULL)
			ncfg = ucl_object_typed_new(UCL_OBJECT);
		ucl_object_insert_key(ncfg, ucl_object_copy(cur), sbuf_data(ukey), sbuf_len(ukey), true);
	}

	if (fatal_errors) {
		ucl_object_unref(ncfg);
		ucl_parser_free(p);
		return (EPKG_FATAL);
	}

	if (ncfg != NULL) {
		it = NULL;
		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
			key = ucl_object_key(cur);
			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
		}
		ucl_object_unref(ncfg);
	}

	ncfg = NULL;
	it = NULL;
	while ((cur = ucl_iterate_object(config, &it, true))) {
		o = NULL;
		key = ucl_object_key(cur);
		val = getenv(key);
		if (val == NULL)
			continue;
		switch (cur->type) {
		case UCL_STRING:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM);
			break;
		case UCL_INT:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT);
			if (o->type != UCL_INT) {
				pkg_emit_error("Invalid type for environment "
				    "variable %s, got %s, while expecting an integer",
				    key, val);
				ucl_object_unref(o);
				continue;
			}
			break;
		case UCL_BOOLEAN:
			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN);
			if (o->type != UCL_BOOLEAN) {
				pkg_emit_error("Invalid type for environment "
				    "variable %s, got %s, while expecting a boolean",
				    key, val);
				ucl_object_unref(o);
				continue;
			}
			break;
		case UCL_OBJECT:
			o = ucl_object_typed_new(UCL_OBJECT);
			walk = buf = val;
			while ((buf = strchr(buf, ',')) != NULL) {
				k = walk;
				value = walk;
				while (*value != ',') {
					if (*value == '=')
						break;
					value++;
				}
				ucl_object_insert_key(o,
				    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
				    k, value - k, false);
				buf++;
				walk = buf;
			}
			key = walk;
			value = walk;
			while (*value != '\0') {
				if (*value == '=')
					break;
				value++;
			}
			ucl_object_insert_key(o,
			    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
			    k, value - k, false);
			break;
		case UCL_ARRAY:
			o = ucl_object_typed_new(UCL_ARRAY);
			walk = buf = val;
			while ((buf = strchr(buf, ',')) != NULL) {
				ucl_array_append(o,
				    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
				buf++;
				walk = buf;
			}
			ucl_array_append(o,
			    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
			break;
		default:
			/* ignore other types */
			break;
		}
		if (o != NULL) {
			if (ncfg == NULL)
				ncfg = ucl_object_typed_new(UCL_OBJECT);
			ucl_object_insert_key(ncfg, o, key, strlen(key), true);
		}
	}

	if (ncfg != NULL) {
		it = NULL;
		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
			key = ucl_object_key(cur);
			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
		}
		ucl_object_unref(ncfg);
	}

	disable_plugins_if_static();

	parsed = true;
	ucl_object_unref(obj);
	ucl_parser_free(p);

	if (strcmp(pkg_object_string(pkg_config_get("ABI")), "unknown") == 0) {
		pkg_emit_error("Unable to determine ABI");
		return (EPKG_FATAL);
	}

	pkg_debug(1, "%s", "pkg initialized");

	/* Start the event pipe */
	evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE"));
	if (evpipe != NULL)
		connect_evpipe(evpipe);

	debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL"));

	it = NULL;
	object = ucl_object_find_key(config, "PKG_ENV");
	while ((cur = ucl_iterate_object(object, &it, true))) {
		evkey = ucl_object_key(cur);
		pkg_debug(1, "Setting env var: %s", evkey);
		if (evkey != NULL && evkey[0] != '\0')
			setenv(evkey, ucl_object_tostring_forced(cur), 1);
	}

	/* load the repositories */
	load_repositories(reposdir, flags);

	setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1);

	/* bypass resolv.conf with specified NAMESERVER if any */
	nsname = pkg_object_string(pkg_config_get("NAMESERVER"));
	if (nsname != NULL)
		set_nameserver(ucl_object_tostring_forced(o));

	return (EPKG_OK);
}
Beispiel #28
0
int
format_exec_cmd(char **dest, const char *in, const char *prefix, const char *plist_file, char *line)
{
	struct sbuf *buf = sbuf_new_auto();
	char path[MAXPATHLEN + 1];
	char *cp;

	while (in[0] != '\0') {
		if (in[0] == '%') {
			in++;
			switch(in[0]) {
				case 'D':
					sbuf_cat(buf, prefix);
					break;
				case 'F':
					if (plist_file == NULL) {
						pkg_emit_error("No files defined %%F couldn't be expanded, ignoring %s", in);
						sbuf_finish(buf);
						sbuf_free(buf);
						return (EPKG_FATAL);
					}
					sbuf_cat(buf, plist_file);
					break;
				case 'f':
					if (plist_file == NULL) {
						pkg_emit_error("No files defined %%f couldn't be expanded, ignoring %s", in);
						sbuf_finish(buf);
						sbuf_free(buf);
						return (EPKG_FATAL);
					}
					if (prefix[strlen(prefix) - 1] == '/')
						snprintf(path, sizeof(path), "%s%s", prefix, plist_file);
					else
						snprintf(path, sizeof(path), "%s/%s", prefix, plist_file);
					cp = strrchr(path, '/');
					cp ++;
					sbuf_cat(buf, cp);
					break;
				case 'B':
					if (plist_file == NULL) {
						pkg_emit_error("No files defined %%B couldn't be expanded, ignoring %s", in);
						sbuf_finish(buf);
						sbuf_free(buf);
						return (EPKG_FATAL);
					}
					if (prefix[strlen(prefix) - 1] == '/')
						snprintf(path, sizeof(path), "%s%s", prefix, plist_file);
					else
						snprintf(path, sizeof(path), "%s/%s", prefix, plist_file);
					cp = strrchr(path, '/');
					cp[0] = '\0';
					sbuf_cat(buf, path);
					break;
				case '%':
					sbuf_putc(buf, '%');
					break;
				case '@':
					if (line != NULL) {
						sbuf_cat(buf, line);
						break;
					}

					/*
					 * no break here because if line is not
					 * given (default exec) %@ does not
					 * exists
					 */
				default:
					sbuf_putc(buf, '%');
					sbuf_putc(buf, in[0]);
					break;
			}

		} else {
			sbuf_putc(buf, in[0]);
		}

		in++;
	}

	sbuf_finish(buf);
	*dest = strdup(sbuf_data(buf));
	sbuf_free(buf);
	
	return (EPKG_OK);
}
Beispiel #29
0
static void
add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags)
{
	const ucl_object_t *cur, *enabled;
	ucl_object_iter_t it = NULL;
	bool enable = true;
	const char *url = NULL, *pubkey = NULL, *mirror_type = NULL;
	const char *signature_type = NULL, *fingerprints = NULL;
	const char *key;
	const char *type = NULL;
	int use_ipvx = 0;

	pkg_debug(1, "PkgConfig: parsing repository object %s", rname);

	enabled = ucl_object_find_key(obj, "enabled");
	if (enabled == NULL)
		enabled = ucl_object_find_key(obj, "ENABLED");
	if (enabled != NULL) {
		enable = ucl_object_toboolean(enabled);
		if (!enable && r == NULL) {
			pkg_debug(1, "PkgConfig: skipping disabled repo %s", rname);
			return;
		}
		else if (!enable && r != NULL) {
			/*
			 * We basically want to remove the existing repo r and
			 * forget all stuff parsed
			 */
			pkg_debug(1, "PkgConfig: disabling repo %s", rname);
			HASH_DEL(repos, r);
			pkg_repo_free(r);
			return;
		}
	}

	while ((cur = ucl_iterate_object(obj, &it, true))) {
		key = ucl_object_key(cur);
		if (key == NULL)
			continue;

		if (strcasecmp(key, "url") == 0) {
			if (cur->type != UCL_STRING) {
				pkg_emit_error("Expecting a string for the "
				    "'%s' key of the '%s' repo",
				    key, rname);
				return;
			}
			url = ucl_object_tostring(cur);
		} else if (strcasecmp(key, "pubkey") == 0) {
			if (cur->type != UCL_STRING) {
				pkg_emit_error("Expecting a string for the "
				    "'%s' key of the '%s' repo",
				    key, rname);
				return;
			}
			pubkey = ucl_object_tostring(cur);
		} else if (strcasecmp(key, "mirror_type") == 0) {
			if (cur->type != UCL_STRING) {
				pkg_emit_error("Expecting a string for the "
				    "'%s' key of the '%s' repo",
				    key, rname);
				return;
			}
			mirror_type = ucl_object_tostring(cur);
		} else if (strcasecmp(key, "signature_type") == 0) {
			if (cur->type != UCL_STRING) {
				pkg_emit_error("Expecting a string for the "
				    "'%s' key of the '%s' repo",
				    key, rname);
				return;
			}
			signature_type = ucl_object_tostring(cur);
		} else if (strcasecmp(key, "fingerprints") == 0) {
			if (cur->type != UCL_STRING) {
				pkg_emit_error("Expecting a string for the "
				    "'%s' key of the '%s' repo",
				    key, rname);
				return;
			}
			fingerprints = ucl_object_tostring(cur);
		} else if (strcasecmp(key, "type") == 0) {
			if (cur->type != UCL_STRING) {
				pkg_emit_error("Expecting a string for the "
					"'%s' key of the '%s' repo",
					key, rname);
				return;
			}
			type = ucl_object_tostring(cur);
		} else if (strcasecmp(key, "ip_version") == 0) {
			if (cur->type != UCL_INT) {
				pkg_emit_error("Expecting a integer for the "
					"'%s' key of the '%s' repo",
					key, rname);
				return;
			}
			use_ipvx = ucl_object_toint(cur);
			if (use_ipvx != 4 && use_ipvx != 6)
				use_ipvx = 0;
		}
	}

	if (r == NULL && url == NULL) {
		pkg_debug(1, "No repo and no url for %s", rname);
		return;
	}

	if (r == NULL)
		r = pkg_repo_new(rname, url, type);
	else
		pkg_repo_overwrite(r, rname, url, type);

	if (signature_type != NULL) {
		if (strcasecmp(signature_type, "pubkey") == 0)
			r->signature_type = SIG_PUBKEY;
		else if (strcasecmp(signature_type, "fingerprints") == 0)
			r->signature_type = SIG_FINGERPRINT;
		else
			r->signature_type = SIG_NONE;
	}


	if (fingerprints != NULL) {
		free(r->fingerprints);
		r->fingerprints = strdup(fingerprints);
	}

	if (pubkey != NULL) {
		free(r->pubkey);
		r->pubkey = strdup(pubkey);
	}

	r->enable = enable;

	if (mirror_type != NULL) {
		if (strcasecmp(mirror_type, "srv") == 0)
			r->mirror_type = SRV;
		else if (strcasecmp(mirror_type, "http") == 0)
			r->mirror_type = HTTP;
		else
			r->mirror_type = NOMIRROR;
	}

	if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
		use_ipvx = 4;
	else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)
		use_ipvx = 6;

	if (use_ipvx != 4 && use_ipvx != 6)
		use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION"));

	if (use_ipvx == 4)
		r->flags = REPO_FLAGS_USE_IPV4;
	else if (use_ipvx == 6)
		r->flags = REPO_FLAGS_USE_IPV6;
}
Beispiel #30
0
static int
pkg_jobs_universe_process_deps(struct pkg_jobs_universe *universe,
	struct pkg *pkg, unsigned flags)
{
	struct pkg_dep *d = NULL;
	int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
	int rc;
	struct pkg_job_universe_item *unit;
	struct pkg *npkg, *rpkg;
	pkg_chain_t *rpkgs = NULL;
	bool found = false;

	rpkg = NULL;
	rc = EPKG_OK;

	if (flags & DEPS_FLAG_REVERSE) {
		deps_func = pkg_rdeps;
	}
	else {
		deps_func = pkg_deps;
	}

	while (deps_func(pkg, &d) == EPKG_OK) {
		HASH_FIND_STR(universe->items, d->uid, unit);
		if (unit != NULL) {
			continue;
		}

		rpkgs = NULL;
		npkg = NULL;
		if (!(flags & DEPS_FLAG_MIRROR)) {
			npkg = pkg_jobs_universe_get_local(universe, d->uid, 0);
		}

		if (!(flags & DEPS_FLAG_FORCE_LOCAL)) {

			/* Check for remote dependencies */
			rpkgs = pkg_jobs_universe_get_remote(universe, d->uid, 0);
		}

		if (npkg == NULL && rpkgs == NULL) {
			pkg_emit_error("%s has a missing dependency: %s",
				pkg->name, d->name);

			if (flags & DEPS_FLAG_FORCE_MISSING) {
				continue;
			}

			return (EPKG_FATAL);
		}

		if (npkg != NULL) {
			if (pkg_jobs_universe_process_item(universe, npkg, &unit) != EPKG_OK) {
				continue;
			}
		}

		if (rpkgs == NULL)
			continue;
		/*
		 * When processing deps, we should first try to select a dependency
		 * from the same repo.
		 * Otherwise, we would have ping-pong of dependencies instead of
		 * the situation when this behaviour is handled by
		 * CONSERVATIVE_UPGRADES.
		 *
		 * Important notes here:
		 * 1. We are looking for packages that are dependencies of a package
		 * `pkg`
		 * 2. Now if `pkg` belongs to repo `r` and `rpkg` belongs to repo
		 * `r` then we just select it.
		 * 3. If `rpkg` is not found in `r` we just scan all packages
		 */

		/*
		 * XXX: this is the proper place to expand flexible dependencies
		 */

		found = false;
		/* Iteration one */
		for (int i = 0; i < kv_size(*rpkgs); i++) {
			rpkg = kv_A(*rpkgs, i);

			if (pkg->reponame && rpkg->reponame &&
					strcmp (pkg->reponame, rpkg->reponame) == 0) {
				found = true;
				break;
			}
		}

		/* Fallback if a dependency is not found in the same repo */
		if (!found) {
			for (int i = 0; i < kv_size(*rpkgs); i++) {
				rpkg = kv_A(*rpkgs, i);

				if (npkg != NULL) {
					/* Set reason for upgrades */
					if (!pkg_jobs_need_upgrade(rpkg, npkg))
						continue;
					/* Save automatic flag */
					rpkg->automatic = npkg->automatic;
				}

				rc = pkg_jobs_universe_process_item(universe, rpkg, NULL);

				/* Special case if we cannot find any package */
				if (npkg == NULL && rc != EPKG_OK) {
					kv_destroy(*rpkgs);
					free(rpkgs);
					return (rc);
				}
			}
		}
		else {
			assert (rpkg != NULL);

			if (npkg != NULL) {
				/* Set reason for upgrades */
				if (!pkg_jobs_need_upgrade(rpkg, npkg))
					continue;
				/* Save automatic flag */
				rpkg->automatic = npkg->automatic;
			}

			rc = pkg_jobs_universe_process_item(universe, rpkg, NULL);
			if (npkg == NULL && rc != EPKG_OK) {
				kv_destroy(*rpkgs);
				free(rpkgs);
				return (rc);
			}
		}

		kv_destroy(*rpkgs);
		free(rpkgs);
	}

	return (EPKG_OK);
}