Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
HardenedBSD-pkg libpkg repo binary common.c
/* Copyright (c) 2014, Vsevolod Stakhov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *       * Redistributions of source code must retain the above copyright
 *         notice, this list of conditions and the following disclaimer.
 *       * Redistributions in binary form must reproduce the above copyright
 *         notice, this list of conditions and the following disclaimer in the
 *         documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#include <sqlite3.h>

#include "pkg.h"
#include "private/event.h"
#include "private/pkg.h"
#include "private/pkgdb.h"
#include "private/utils.h"
#include "binary_private.h"

static sql_prstmt sql_prepared_statements[PRSTMT_LAST] = {
	[PKG] = {
		NULL,
		"INSERT OR REPLACE INTO packages ("
		"origin, name, version, comment, desc, arch, maintainer, www, "
		"prefix, pkgsize, flatsize, licenselogic, cksum, path, manifestdigest, olddigest, "
		"vital)"
		"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17)",
	},
	[DEPS] = {
		NULL,
		"INSERT OR REPLACE INTO deps (origin, name, version, package_id) "
		"VALUES (?1, ?2, ?3, ?4)",
	},
	[CAT1] = {
		NULL,
		"INSERT OR IGNORE INTO categories(name) VALUES(?1)",
	},
	[CAT2] = {
		NULL,
		"INSERT OR ROLLBACK INTO pkg_categories(package_id, category_id) "
		"VALUES (?1, (SELECT id FROM categories WHERE name = ?2))",
	},
	[LIC1] = {
		NULL,
		"INSERT OR IGNORE INTO licenses(name) VALUES(?1)",
	},
	[LIC2] = {
		NULL,
		"INSERT OR ROLLBACK INTO pkg_licenses(package_id, license_id) "
		"VALUES (?1, (SELECT id FROM licenses WHERE name = ?2))",
	},
	[OPT1] = {
		NULL,
		"INSERT OR IGNORE INTO option(option) "
		"VALUES (?1)",
	},
	[OPT2] = {
		NULL,
		"INSERT OR ROLLBACK INTO pkg_option (option_id, value, package_id) "
		"VALUES (( SELECT option_id FROM option WHERE option = ?1), ?2, ?3)",
	},
	[SHLIB1] = {
		NULL,
		"INSERT OR IGNORE INTO shlibs(name) VALUES(?1)",
	},
	[SHLIB_REQD] = {
		NULL,
		"INSERT OR IGNORE INTO pkg_shlibs_required(package_id, shlib_id) "
		"VALUES (?1, (SELECT id FROM shlibs WHERE name = ?2))",
	},
	[SHLIB_PROV] = {
		NULL,
		"INSERT OR IGNORE INTO pkg_shlibs_provided(package_id, shlib_id) "
		"VALUES (?1, (SELECT id FROM shlibs WHERE name = ?2))",
	},
	[EXISTS] = {
		NULL,
		"SELECT count(*) FROM packages WHERE cksum=?1",
	},
	[ANNOTATE1] = {
		NULL,
		"INSERT OR IGNORE INTO annotation(annotation) "
		"VALUES (?1)",
	},
	[ANNOTATE2] = {
		NULL,
		"INSERT OR ROLLBACK INTO pkg_annotation(package_id, tag_id, value_id) "
		"VALUES (?1,"
		" (SELECT annotation_id FROM annotation WHERE annotation=?2),"
		" (SELECT annotation_id FROM annotation WHERE annotation=?3))",
	},
	[REPO_VERSION] = {
		NULL,
		"SELECT version FROM packages WHERE origin=?1",
	},
	[DELETE] = {
		NULL,
		"DELETE FROM packages WHERE origin=?1;"
		"DELETE FROM pkg_search WHERE origin=?1;",
	},
	[PROVIDE] = {
		NULL,
		"INSERT OR IGNORE INTO provides(provide) VALUES(?1)",
	},
	[PROVIDES] = {
		NULL,
		"INSERT OR IGNORE INTO pkg_provides(package_id, provide_id) "
		"VALUES (?1, (SELECT id FROM provides WHERE provide = ?2))",
	},
	[REQUIRE] = {
		NULL,
		"INSERT OR IGNORE INTO requires(require) VALUES(?1)",
	},
	[REQUIRES] = {
		NULL,
		"INSERT OR IGNORE INTO pkg_requires(package_id, require_id) "
		"VALUES (?1, (SELECT id FROM requires WHERE require = ?2))",
	},
	[FILEDIR1] = {
		NULL,
		"INSERT OR IGNORE INTO file_dirs(path) VALUES(?1)",
	},
	[FILEDIR2] = {
		NULL,
		"INSERT OR IGNORE INTO pkg_files(package_id, dir_id, name) "
		"VALUES (?1, (SELECT id FROM file_dirs WHERE path = ?2), ?3)",
	},
	[PKGID] = {
		NULL,
		"SELECT id FROM packages WHERE name = ?1 AND version = ?2",
	},
	/* PRSTMT_LAST */
};

const char *
pkg_repo_binary_sql_prstatement(sql_prstmt_index s)
{
	if (s < PRSTMT_LAST)
		return (sql_prepared_statements[s].sql);
	else
		return ("unknown");
}

sqlite3_stmt*
pkg_repo_binary_stmt_prstatement(sql_prstmt_index s)
{
	if (s < PRSTMT_LAST)
		return (sql_prepared_statements[s].stmt);
	else
		return (NULL);
}

int
pkg_repo_binary_init_prstatements(sqlite3 *sqlite)
{
	sql_prstmt_index i, last;

	last = PRSTMT_LAST;

	for (i = 0; i < last; i++) {
		STMT(i) = prepare_sql(sqlite, SQL(i));
		if (STMT(i) == NULL)
			return (EPKG_FATAL);
	}

	return (EPKG_OK);
}

int
pkg_repo_binary_run_prstatement(sql_prstmt_index s, const sql_arg_t *args, size_t nargs)
{
	int retcode;	/* Returns SQLITE error code */
	sqlite3_stmt *stmt;
	size_t i;

	stmt = STMT(s);
	sqlite3_reset(stmt);

	for (i = 0; i < nargs; i++) {
		int bind_index = (int)i + 1;
		switch(args[i].type) {
		case ARG_TEXT:
			sqlite3_bind_text(stmt, bind_index, args[i].v.text, -1,
			    SQLITE_STATIC);
			break;
		case ARG_INT64:
			sqlite3_bind_int64(stmt, bind_index, args[i].v.i64);
			break;
		default:
			return (SQLITE_MISUSE);
		}
	}

	retcode = sqlite3_step(stmt);

	return (retcode);
}

/*
 * Returns a path relative to the dbdir.
 */
const char *
pkg_repo_binary_get_filename(struct pkg_repo *repo)
{
	if (repo->dbpath == NULL)
		xasprintf(&repo->dbpath, "repos/%s/db", repo->name);
	return (repo->dbpath);
}

void
pkg_repo_binary_finalize_prstatements(void)
{
	sql_prstmt_index i, last;

	last = PRSTMT_LAST;

	for (i = 0; i < last; i++)
	{
		if (STMT(i) != NULL) {
			sqlite3_finalize(STMT(i));
			STMT(i) = NULL;
		}
	}
}