Files
ropkg/libropkg/repo-mgmt.c
T
2026-06-22 17:45:54 +01:00

931 lines
20 KiB
C

#include "db.h"
#include <fx/io/directory.h>
#include <ropkg/repo-mgmt.h>
#include <ropkg/status.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>
struct ropkg_repo_mgmt {
sqlite3 *repo_meta;
sqlite3 *repo_packages;
fx_directory *repo_root;
fx_directory *repo_pool;
fx_directory *repo_news;
fx_directory *repo_channel;
};
struct ropkg_repo_mgmt_channel {
sqlite3 *c_meta;
fx_directory *c_root;
fx_directory *c_news;
};
struct ropkg_repo_mgmt_component {
sqlite3 *c_meta;
sqlite3 *c_packages;
fx_directory *c_root;
fx_directory *c_news;
};
static fx_result init_repo_meta_db(sqlite3 *db)
{
const char *sql = NULL;
sqlite3_stmt *stmt = NULL;
int err = 0;
sql = "CREATE TABLE repo ("
"name TEXT PRIMARY KEY,"
"description TEXT NOT NULL);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sql = "CREATE TABLE architecture ("
"name TEXT PRIMARY KEY);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sql = "CREATE TABLE channel ("
"name TEXT PRIMARY KEY);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sql = "CREATE TABLE news ("
"id NUMBER PRIMARY KEY,"
"title TEXT NOT NULL,"
"importance TEXT,"
"category TEXT,"
"publish_date TEXT NOT NULL,"
"filename TEXT NOT NULL);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
static fx_result init_repo_packages_db(sqlite3 *db)
{
const char *sql = NULL;
sqlite3_stmt *stmt = NULL;
int err = 0;
sql = "CREATE TABLE package ("
"name TEXT NOT NULL,"
"arch TEXT NOT NULL,"
"version TEXT NOT NULL,"
"description TEXT,"
"priority TEXT,"
"category TEXT,"
"maintainer TEXT NOT NULL,"
"provides TEXT,"
"dependencies TEXT,"
"recommends TEXT,"
"suggests TEXT,"
"conflicts TEXT,"
"enhances TEXT,"
"filename TEXT UNIQUE,"
"PRIMARY KEY(name, arch, version));";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
static fx_result init_channel_meta_db(sqlite3 *db)
{
const char *sql = NULL;
sqlite3_stmt *stmt = NULL;
int err = 0;
sql = "CREATE TABLE channel ("
"name TEXT PRIMARY KEY,"
"description TEXT NOT NULL);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sql = "CREATE TABLE component ("
"name TEXT PRIMARY KEY);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sql = "CREATE TABLE news ("
"id NUMBER PRIMARY KEY,"
"title TEXT NOT NULL,"
"importance TEXT,"
"category TEXT,"
"publish_date TEXT NOT NULL,"
"filename TEXT NOT NULL);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
static fx_result init_component_meta_db(sqlite3 *db)
{
const char *sql = NULL;
sqlite3_stmt *stmt = NULL;
int err = 0;
sql = "CREATE TABLE component ("
"name TEXT PRIMARY KEY,"
"description TEXT NOT NULL);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
sql = "CREATE TABLE news ("
"id NUMBER PRIMARY KEY,"
"title TEXT NOT NULL,"
"importance TEXT,"
"category TEXT,"
"publish_date TEXT NOT NULL,"
"filename TEXT NOT NULL);";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
static fx_result init_component_packages_db(sqlite3 *db)
{
const char *sql = NULL;
sqlite3_stmt *stmt = NULL;
int err = 0;
sql = "CREATE TABLE package ("
"name TEXT NOT NULL,"
"arch TEXT NOT NULL,"
"version TEXT NOT NULL,"
"description TEXT,"
"priority TEXT,"
"category TEXT,"
"maintainer TEXT NOT NULL,"
"provides TEXT,"
"dependencies TEXT,"
"recommends TEXT,"
"suggests TEXT,"
"conflicts TEXT,"
"enhances TEXT,"
"repo_name TEXT NOT NULL,"
"channel_name TEXT NOT NULL,"
"PRIMARY KEY(name, arch, version, repo_name, channel_name));";
err = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
err = sqlite3_step(stmt);
if (err != SQLITE_DONE) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
fx_result ropkg_repo_mgmt_open(const char *path, struct ropkg_repo_mgmt **out)
{
struct ropkg_repo_mgmt *repo = malloc(sizeof *repo);
if (!repo) {
return FX_RESULT_ERR(NO_MEMORY);
}
memset(repo, 0x0, sizeof *repo);
fx_result result = fx_directory_open(
NULL,
FX_RV_PATH(path),
0,
&repo->repo_root);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = fx_directory_open(
repo->repo_root,
FX_RV_PATH("pool"),
0,
&repo->repo_pool);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = fx_directory_open(
repo->repo_root,
FX_RV_PATH("news"),
0,
&repo->repo_news);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = fx_directory_open(
repo->repo_root,
FX_RV_PATH("channel"),
0,
&repo->repo_channel);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = open_database(
repo->repo_root,
"meta.rodb",
SQLITE_OPEN_READWRITE,
&repo->repo_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
*out = repo;
return FX_RESULT_SUCCESS;
}
fx_result ropkg_repo_mgmt_create(const char *path, struct ropkg_repo_mgmt **out)
{
struct ropkg_repo_mgmt *repo = malloc(sizeof *repo);
if (!repo) {
return FX_RESULT_ERR(NO_MEMORY);
}
memset(repo, 0x0, sizeof *repo);
fx_result result = fx_directory_open(
NULL,
FX_RV_PATH(path),
FX_DIRECTORY_OPEN_CREATE,
&repo->repo_root);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = fx_directory_open(
repo->repo_root,
FX_RV_PATH("pool"),
FX_DIRECTORY_OPEN_CREATE,
&repo->repo_pool);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = fx_directory_open(
repo->repo_root,
FX_RV_PATH("news"),
FX_DIRECTORY_OPEN_CREATE,
&repo->repo_news);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = fx_directory_open(
repo->repo_root,
FX_RV_PATH("channel"),
FX_DIRECTORY_OPEN_CREATE,
&repo->repo_channel);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = open_database(
repo->repo_root,
"meta.rodb",
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&repo->repo_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = init_repo_meta_db(repo->repo_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = open_database(
repo->repo_root,
"packages.rodb",
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&repo->repo_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
result = init_repo_packages_db(repo->repo_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_close(repo);
return fx_result_propagate(result);
}
*out = repo;
return FX_RESULT_SUCCESS;
}
void ropkg_repo_mgmt_close(struct ropkg_repo_mgmt *repo)
{
if (repo->repo_meta) {
sqlite3_close(repo->repo_meta);
repo->repo_meta = NULL;
}
if (repo->repo_pool) {
fx_directory_unref(repo->repo_pool);
repo->repo_pool = NULL;
}
if (repo->repo_news) {
fx_directory_unref(repo->repo_news);
repo->repo_news = NULL;
}
if (repo->repo_root) {
fx_directory_unref(repo->repo_root);
repo->repo_root = NULL;
}
free(repo);
}
static fx_result channel_exists(
struct ropkg_repo_mgmt *repo,
const char *name,
bool *exists)
{
const char *sql = "SELECT * FROM channel WHERE name = ?;";
sqlite3_stmt *stmt = NULL;
int err = sqlite3_prepare_v2(repo->repo_meta, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(repo->repo_meta));
}
sqlite3_bind_text(stmt, 1, name, strlen(name), NULL);
err = sqlite3_step(stmt);
switch (err) {
case SQLITE_ROW:
*exists = true;
break;
case SQLITE_ERROR:
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(repo->repo_meta));
default:
*exists = false;
break;
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
static fx_result component_exists(
struct ropkg_repo_mgmt_channel *channel,
const char *name,
bool *exists)
{
const char *sql = "SELECT * FROM component WHERE name = ?;";
sqlite3_stmt *stmt = NULL;
int err = sqlite3_prepare_v2(channel->c_meta, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(channel->c_meta));
}
sqlite3_bind_text(stmt, 1, name, strlen(name), NULL);
err = sqlite3_step(stmt);
switch (err) {
case SQLITE_ROW:
*exists = true;
break;
case SQLITE_ERROR:
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(channel->c_meta));
default:
*exists = false;
break;
}
sqlite3_finalize(stmt);
return FX_RESULT_SUCCESS;
}
fx_result ropkg_repo_mgmt_open_channel(
struct ropkg_repo_mgmt *repo,
const char *name,
struct ropkg_repo_mgmt_channel **out)
{
bool exists;
fx_result result = channel_exists(repo, name, &exists);
if (fx_result_is_error(result)) {
return fx_result_propagate(result);
}
if (!exists) {
return fx_error_with_code(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_NO_CHANNEL);
}
struct ropkg_repo_mgmt_channel *channel = malloc(sizeof *channel);
if (!channel) {
return FX_RESULT_ERR(NO_MEMORY);
}
memset(channel, 0x0, sizeof *channel);
result = fx_directory_open(
repo->repo_channel,
FX_RV_PATH(name),
0,
&channel->c_root);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
result = fx_directory_open(
channel->c_root,
FX_RV_PATH("news"),
0,
&channel->c_news);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
result = open_database(
channel->c_root,
"meta.rodb",
SQLITE_OPEN_READWRITE,
&channel->c_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
*out = channel;
return FX_RESULT_SUCCESS;
}
fx_result ropkg_repo_mgmt_create_channel(
struct ropkg_repo_mgmt *repo,
const char *name,
struct ropkg_repo_mgmt_channel **out)
{
struct ropkg_repo_mgmt_channel *channel = malloc(sizeof *channel);
if (!channel) {
return FX_RESULT_ERR(NO_MEMORY);
}
memset(channel, 0x0, sizeof *channel);
fx_result result = fx_directory_open(
repo->repo_channel,
FX_RV_PATH(name),
FX_DIRECTORY_OPEN_CREATE,
&channel->c_root);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
result = fx_directory_open(
channel->c_root,
FX_RV_PATH("news"),
FX_DIRECTORY_OPEN_CREATE,
&channel->c_news);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
result = open_database(
channel->c_root,
"meta.rodb",
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&channel->c_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
result = init_channel_meta_db(channel->c_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_channel_close(channel);
return fx_result_propagate(result);
}
const char *sql = "INSERT INTO channel (name) VALUES (?);";
sqlite3_stmt *stmt;
int err = sqlite3_prepare(repo->repo_meta, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
ropkg_repo_mgmt_channel_close(channel);
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(repo->repo_meta));
}
sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_STATIC);
err = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (err != SQLITE_DONE) {
ropkg_repo_mgmt_channel_close(channel);
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(repo->repo_meta));
}
*out = channel;
return FX_RESULT_SUCCESS;
}
void ropkg_repo_mgmt_channel_close(struct ropkg_repo_mgmt_channel *channel)
{
if (channel->c_meta) {
sqlite3_close(channel->c_meta);
channel->c_meta = NULL;
}
if (channel->c_news) {
fx_directory_unref(channel->c_news);
channel->c_news = NULL;
}
if (channel->c_root) {
fx_directory_unref(channel->c_root);
channel->c_root = NULL;
}
free(channel);
}
fx_result ropkg_repo_mgmt_channel_open_component(
struct ropkg_repo_mgmt_channel *channel,
const char *name,
struct ropkg_repo_mgmt_component **out)
{
bool exists;
fx_result result = component_exists(channel, name, &exists);
if (fx_result_is_error(result)) {
return fx_result_propagate(result);
}
if (!exists) {
return fx_error_with_code(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_NO_COMPONENT);
}
struct ropkg_repo_mgmt_component *component = malloc(sizeof *component);
if (!component) {
return FX_RESULT_ERR(NO_MEMORY);
}
memset(component, 0x0, sizeof *component);
result = fx_directory_open(
channel->c_root,
FX_RV_PATH(name),
0,
&component->c_root);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = fx_directory_open(
component->c_root,
FX_RV_PATH("news"),
0,
&component->c_news);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = open_database(
component->c_root,
"meta.rodb",
SQLITE_OPEN_READWRITE,
&component->c_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = open_database(
component->c_root,
"packages.rodb",
SQLITE_OPEN_READWRITE,
&component->c_packages);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
*out = component;
return FX_RESULT_SUCCESS;
}
fx_result ropkg_repo_mgmt_channel_create_component(
struct ropkg_repo_mgmt_channel *channel,
const char *name,
struct ropkg_repo_mgmt_component **out)
{
struct ropkg_repo_mgmt_component *component = malloc(sizeof *component);
if (!channel) {
return FX_RESULT_ERR(NO_MEMORY);
}
memset(component, 0x0, sizeof *component);
fx_result result = fx_directory_open(
channel->c_root,
FX_RV_PATH(name),
FX_DIRECTORY_OPEN_CREATE,
&component->c_root);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = fx_directory_open(
component->c_root,
FX_RV_PATH("news"),
FX_DIRECTORY_OPEN_CREATE,
&component->c_news);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = open_database(
component->c_root,
"meta.rodb",
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&component->c_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = init_component_meta_db(component->c_meta);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = open_database(
component->c_root,
"packages.rodb",
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
&component->c_packages);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
result = init_component_packages_db(component->c_packages);
if (fx_result_is_error(result)) {
ropkg_repo_mgmt_component_close(component);
return fx_result_propagate(result);
}
const char *sql = "INSERT INTO component (name) VALUES (?);";
sqlite3_stmt *stmt;
int err = sqlite3_prepare(channel->c_meta, sql, -1, &stmt, NULL);
if (err != SQLITE_OK) {
ropkg_repo_mgmt_channel_close(channel);
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(channel->c_meta));
}
sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_STATIC);
err = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (err != SQLITE_DONE) {
ropkg_repo_mgmt_channel_close(channel);
return fx_error_with_string(
ROPKG_ERROR_VENDOR,
ROPKG_ERR_DB_OP_FAILED,
sqlite3_errmsg(channel->c_meta));
}
*out = component;
return FX_RESULT_SUCCESS;
}
void ropkg_repo_mgmt_component_close(
struct ropkg_repo_mgmt_component *component)
{
if (component->c_packages) {
sqlite3_close(component->c_packages);
component->c_packages = NULL;
}
if (component->c_meta) {
sqlite3_close(component->c_meta);
component->c_meta = NULL;
}
if (component->c_news) {
fx_directory_unref(component->c_news);
component->c_news = NULL;
}
if (component->c_root) {
fx_directory_unref(component->c_root);
component->c_root = NULL;
}
free(component);
}