2025-07-21 22:46:20 +01:00
|
|
|
#include "instance.h"
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
#include "ropkg/system-state.h"
|
|
|
|
|
|
2025-07-21 22:46:20 +01:00
|
|
|
#include <ropkg/instance.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#define CREATE_FILE_OR_THROW(inst, path, out_file) \
|
|
|
|
|
do { \
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_path *path_object = fx_path_create_from_cstr(path); \
|
|
|
|
|
fx_result result = fx_file_open( \
|
2025-07-21 22:46:20 +01:00
|
|
|
inst->inst_root, \
|
2026-06-22 17:45:54 +01:00
|
|
|
path_object, \
|
|
|
|
|
FX_FILE_READ_WRITE | FX_FILE_CREATE, \
|
2025-07-21 22:46:20 +01:00
|
|
|
out_file); \
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_path_unref(path_object); \
|
2025-07-21 22:46:20 +01:00
|
|
|
\
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) { \
|
|
|
|
|
return fx_error_with_template_caused_by_error( \
|
2025-07-21 22:46:20 +01:00
|
|
|
ROPKG_ERROR_VENDOR, \
|
|
|
|
|
ROPKG_ERR_INSTANCE_DIR_CREATE_FAILED, \
|
|
|
|
|
result, \
|
2026-06-22 17:45:54 +01:00
|
|
|
FX_ERROR_PARAM( \
|
2025-07-21 22:46:20 +01:00
|
|
|
"instancepath", \
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory_get_rel_path_cstr( \
|
2025-07-21 22:46:20 +01:00
|
|
|
inst->inst_root)), \
|
2026-06-22 17:45:54 +01:00
|
|
|
FX_ERROR_PARAM("subdirpath", path)); \
|
2025-07-21 22:46:20 +01:00
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
#define CREATE_DIRECTORY_OR_THROW(inst, path, out_dir) \
|
|
|
|
|
do { \
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_path *path_object = fx_path_create_from_cstr(path); \
|
|
|
|
|
fx_result result = fx_directory_open( \
|
2025-07-21 22:46:20 +01:00
|
|
|
inst->inst_root, \
|
2026-06-22 17:45:54 +01:00
|
|
|
path_object, \
|
|
|
|
|
FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE, \
|
2025-07-21 22:46:20 +01:00
|
|
|
out_dir); \
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_path_unref(path_object); \
|
2025-07-21 22:46:20 +01:00
|
|
|
\
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) { \
|
|
|
|
|
return fx_error_with_template_caused_by_error( \
|
2025-07-21 22:46:20 +01:00
|
|
|
ROPKG_ERROR_VENDOR, \
|
|
|
|
|
ROPKG_ERR_INSTANCE_DIR_CREATE_FAILED, \
|
|
|
|
|
result, \
|
2026-06-22 17:45:54 +01:00
|
|
|
FX_ERROR_PARAM( \
|
2025-07-21 22:46:20 +01:00
|
|
|
"instancepath", \
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory_get_rel_path_cstr( \
|
2025-07-21 22:46:20 +01:00
|
|
|
inst->inst_root)), \
|
2026-06-22 17:45:54 +01:00
|
|
|
FX_ERROR_PARAM("subdirpath", path)); \
|
2025-07-21 22:46:20 +01:00
|
|
|
} \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
static fx_result bootstrap_base(struct ropkg_instance *instance)
|
2025-07-21 22:46:20 +01:00
|
|
|
{
|
|
|
|
|
CREATE_DIRECTORY_OR_THROW(
|
|
|
|
|
instance,
|
|
|
|
|
ROPKG_INSTANCE_DIRPATH_CACHE,
|
|
|
|
|
&instance->inst_dir_cache);
|
|
|
|
|
CREATE_DIRECTORY_OR_THROW(
|
|
|
|
|
instance,
|
|
|
|
|
ROPKG_INSTANCE_DIRPATH_CONFIG,
|
|
|
|
|
&instance->inst_dir_config);
|
|
|
|
|
CREATE_DIRECTORY_OR_THROW(
|
|
|
|
|
instance,
|
|
|
|
|
ROPKG_INSTANCE_DIRPATH_DATABASE,
|
|
|
|
|
&instance->inst_dir_database);
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
return FX_RESULT_SUCCESS;
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
static fx_result bootstrap_config(struct ropkg_instance *instance)
|
2025-07-21 22:46:20 +01:00
|
|
|
{
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory *dir;
|
2025-07-21 22:46:20 +01:00
|
|
|
|
|
|
|
|
CREATE_DIRECTORY_OR_THROW(
|
|
|
|
|
instance,
|
2026-06-22 17:45:54 +01:00
|
|
|
ROPKG_INSTANCE_DIRPATH_CONFIG_FILES,
|
2025-07-21 22:46:20 +01:00
|
|
|
&dir);
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory_unref(dir);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
|
|
|
|
CREATE_DIRECTORY_OR_THROW(
|
|
|
|
|
instance,
|
|
|
|
|
ROPKG_INSTANCE_DIRPATH_SOURCES,
|
|
|
|
|
&dir);
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory_unref(dir);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
return FX_RESULT_SUCCESS;
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
static fx_result bootstrap_cache(struct ropkg_instance *instance)
|
2025-07-21 22:46:20 +01:00
|
|
|
{
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory *dir;
|
2025-07-21 22:46:20 +01:00
|
|
|
|
|
|
|
|
CREATE_DIRECTORY_OR_THROW(
|
|
|
|
|
instance,
|
|
|
|
|
ROPKG_INSTANCE_DIRPATH_ARCHIVES,
|
|
|
|
|
&dir);
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_directory_unref(dir);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
return FX_RESULT_SUCCESS;
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
static fx_result bootstrap_database(struct ropkg_instance *instance)
|
2025-07-21 22:46:20 +01:00
|
|
|
{
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_result result;
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
result = ropkg_system_state_init(
|
|
|
|
|
instance->inst_root,
|
|
|
|
|
ROPKG_INSTANCE_FILEPATH_STATUS,
|
|
|
|
|
&instance->inst_status);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
return fx_result_propagate(result);
|
|
|
|
|
}
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
result = ropkg_package_db_init(
|
|
|
|
|
instance->inst_root,
|
|
|
|
|
ROPKG_INSTANCE_FILEPATH_AVAILABLE,
|
|
|
|
|
&instance->inst_available);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
return fx_result_propagate(result);
|
|
|
|
|
}
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
return FX_RESULT_SUCCESS;
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_result ropkg_instance_open(const char *cpath, struct ropkg_instance **out)
|
2025-07-21 22:46:20 +01:00
|
|
|
{
|
|
|
|
|
struct ropkg_instance *inst = malloc(sizeof *inst);
|
|
|
|
|
if (!inst) {
|
|
|
|
|
return ROPKG_RESULT_ERR(NO_MEMORY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(inst, 0x0, sizeof *inst);
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_path *path = fx_path_create_from_cstr(cpath);
|
2025-07-21 22:46:20 +01:00
|
|
|
if (!path) {
|
|
|
|
|
free(inst);
|
|
|
|
|
return ROPKG_RESULT_ERR(NO_MEMORY);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_result result = fx_directory_open(NULL, path, 0, &inst->inst_root);
|
|
|
|
|
fx_path_unref(path);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fx_path *path_object
|
|
|
|
|
= fx_path_create_from_cstr(ROPKG_INSTANCE_FILEPATH_LOCK);
|
|
|
|
|
result = fx_file_open(
|
|
|
|
|
inst->inst_root,
|
|
|
|
|
path_object,
|
|
|
|
|
FX_FILE_WRITE_ONLY | FX_FILE_CREATE_ONLY
|
|
|
|
|
| FX_FILE_DELETE_ON_CLOSE,
|
|
|
|
|
&inst->inst_lock);
|
|
|
|
|
fx_path_unref(path_object);
|
|
|
|
|
|
|
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_error_caused_by_error(
|
|
|
|
|
ROPKG_ERROR_VENDOR,
|
|
|
|
|
ROPKG_ERR_INSTANCE_LOCKED,
|
|
|
|
|
result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path_object = fx_path_create_from_cstr(ROPKG_INSTANCE_DIRPATH_CONFIG);
|
|
|
|
|
result = fx_directory_open(
|
|
|
|
|
inst->inst_root,
|
|
|
|
|
path_object,
|
|
|
|
|
0,
|
|
|
|
|
&inst->inst_dir_config);
|
|
|
|
|
fx_path_unref(path_object);
|
|
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path_object = fx_path_create_from_cstr(ROPKG_INSTANCE_DIRPATH_CACHE);
|
|
|
|
|
result = fx_directory_open(
|
|
|
|
|
inst->inst_root,
|
|
|
|
|
path_object,
|
|
|
|
|
0,
|
|
|
|
|
&inst->inst_dir_cache);
|
|
|
|
|
fx_path_unref(path_object);
|
|
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path_object = fx_path_create_from_cstr(ROPKG_INSTANCE_DIRPATH_DATABASE);
|
|
|
|
|
result = fx_directory_open(
|
|
|
|
|
inst->inst_root,
|
|
|
|
|
path_object,
|
|
|
|
|
0,
|
|
|
|
|
&inst->inst_dir_database);
|
|
|
|
|
fx_path_unref(path_object);
|
|
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*out = inst;
|
|
|
|
|
return ROPKG_RESULT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_result ropkg_instance_bootstrap(
|
2025-07-21 22:46:20 +01:00
|
|
|
const char *cpath,
|
|
|
|
|
struct ropkg_instance **out)
|
|
|
|
|
{
|
|
|
|
|
struct ropkg_instance *inst = malloc(sizeof *inst);
|
|
|
|
|
if (!inst) {
|
|
|
|
|
return ROPKG_RESULT_ERR(NO_MEMORY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(inst, 0x0, sizeof *inst);
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_path *path = fx_path_create_from_cstr(cpath);
|
2025-07-21 22:46:20 +01:00
|
|
|
if (!path) {
|
2026-06-22 17:45:54 +01:00
|
|
|
ropkg_instance_close(inst);
|
2025-07-21 22:46:20 +01:00
|
|
|
return ROPKG_RESULT_ERR(NO_MEMORY);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
fx_result result = fx_directory_open(NULL, path, 0, &inst->inst_root);
|
|
|
|
|
fx_path_unref(path);
|
2025-07-21 22:46:20 +01:00
|
|
|
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_error_with_template_caused_by_error(
|
2025-07-21 22:46:20 +01:00
|
|
|
ROPKG_ERROR_VENDOR,
|
|
|
|
|
ROPKG_ERR_DIR_OPEN_FAILED,
|
|
|
|
|
result,
|
2026-06-22 17:45:54 +01:00
|
|
|
FX_ERROR_PARAM("filepath", cpath));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fx_path *path_object
|
|
|
|
|
= fx_path_create_from_cstr(ROPKG_INSTANCE_FILEPATH_LOCK);
|
|
|
|
|
result = fx_file_open(
|
|
|
|
|
inst->inst_root,
|
|
|
|
|
path_object,
|
|
|
|
|
FX_FILE_READ_ONLY,
|
|
|
|
|
&inst->inst_lock);
|
|
|
|
|
fx_path_unref(path_object);
|
|
|
|
|
if (!fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_error_with_code(
|
|
|
|
|
ROPKG_ERROR_VENDOR,
|
|
|
|
|
ROPKG_ERR_INSTANCE_LOCKED);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = bootstrap_base(inst);
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = bootstrap_config(inst);
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = bootstrap_cache(inst);
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = bootstrap_database(inst);
|
2026-06-22 17:45:54 +01:00
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_result_propagate(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path_object = fx_path_create_from_cstr(ROPKG_INSTANCE_FILEPATH_LOCK);
|
|
|
|
|
result = fx_file_open(
|
|
|
|
|
inst->inst_root,
|
|
|
|
|
path_object,
|
|
|
|
|
FX_FILE_WRITE_ONLY | FX_FILE_CREATE_ONLY
|
|
|
|
|
| FX_FILE_DELETE_ON_CLOSE,
|
|
|
|
|
&inst->inst_lock);
|
|
|
|
|
fx_path_unref(path_object);
|
|
|
|
|
if (fx_result_is_error(result)) {
|
|
|
|
|
ropkg_instance_close(inst);
|
|
|
|
|
return fx_error_caused_by_error(
|
|
|
|
|
ROPKG_ERROR_VENDOR,
|
|
|
|
|
ROPKG_ERR_INSTANCE_LOCKED,
|
|
|
|
|
result);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*out = inst;
|
2026-06-22 17:45:54 +01:00
|
|
|
return FX_RESULT_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ropkg_instance_close(struct ropkg_instance *inst)
|
|
|
|
|
{
|
|
|
|
|
if (inst->inst_status) {
|
|
|
|
|
ropkg_system_state_close(inst->inst_status);
|
|
|
|
|
inst->inst_status = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inst->inst_available) {
|
|
|
|
|
ropkg_package_db_close(inst->inst_available);
|
|
|
|
|
inst->inst_available = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inst->inst_dir_config) {
|
|
|
|
|
fx_directory_unref(inst->inst_dir_config);
|
|
|
|
|
inst->inst_dir_config = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inst->inst_dir_cache) {
|
|
|
|
|
fx_directory_unref(inst->inst_dir_cache);
|
|
|
|
|
inst->inst_dir_cache = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inst->inst_dir_database) {
|
|
|
|
|
fx_directory_unref(inst->inst_dir_database);
|
|
|
|
|
inst->inst_dir_database = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inst->inst_root) {
|
|
|
|
|
fx_directory_unref(inst->inst_root);
|
|
|
|
|
inst->inst_root = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inst->inst_lock) {
|
|
|
|
|
fx_file_unref(inst->inst_lock);
|
|
|
|
|
inst->inst_lock = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(inst);
|
2025-07-21 22:46:20 +01:00
|
|
|
}
|