diff --git a/libropkg/CMakeLists.txt b/libropkg/CMakeLists.txt index 8ccc136..9c091f4 100644 --- a/libropkg/CMakeLists.txt +++ b/libropkg/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(libropkg SHARED ${sources}) set_target_properties(libropkg PROPERTIES OUTPUT_NAME ropkg) target_link_libraries(libropkg + Bluelib::Io ${ZSTD_LIBRARY}) target_include_directories(libropkg PUBLIC include/ diff --git a/libropkg/include/ropkg/instance.h b/libropkg/include/ropkg/instance.h new file mode 100644 index 0000000..556f184 --- /dev/null +++ b/libropkg/include/ropkg/instance.h @@ -0,0 +1,15 @@ +#ifndef ROPKG_INSTANCE_H_ +#define ROPKG_INSTANCE_H_ + +#include +#include +#include + +struct ropkg_instance; + +ROPKG_API b_result +ropkg_instance_open(const char *path, struct ropkg_instance **out); +ROPKG_API b_result +ropkg_instance_bootstrap(const char *path, struct ropkg_instance **out); + +#endif diff --git a/libropkg/instance.c b/libropkg/instance.c new file mode 100644 index 0000000..8e0616a --- /dev/null +++ b/libropkg/instance.c @@ -0,0 +1,201 @@ +#include "instance.h" + +#include +#include +#include + +#define CREATE_FILE_OR_THROW(inst, path, out_file) \ + do { \ + b_result result = b_file_open( \ + inst->inst_root, \ + B_RV_PATH(path), \ + B_FILE_READ_WRITE | B_FILE_CREATE, \ + out_file); \ + \ + if (b_result_is_error(result)) { \ + return b_error_with_template_caused_by_error( \ + ROPKG_ERROR_VENDOR, \ + ROPKG_ERR_INSTANCE_DIR_CREATE_FAILED, \ + result, \ + B_ERROR_PARAM( \ + "instancepath", \ + b_directory_get_rel_path_cstr( \ + inst->inst_root)), \ + B_ERROR_PARAM("subdirpath", path)); \ + } \ + } while (0) + +#define CREATE_DIRECTORY_OR_THROW(inst, path, out_dir) \ + do { \ + b_result result = b_directory_open( \ + inst->inst_root, \ + B_RV_PATH(path), \ + B_DIRECTORY_OPEN_CREATE_INTERMEDIATE, \ + out_dir); \ + \ + if (b_result_is_error(result)) { \ + return b_error_with_template_caused_by_error( \ + ROPKG_ERROR_VENDOR, \ + ROPKG_ERR_INSTANCE_DIR_CREATE_FAILED, \ + result, \ + B_ERROR_PARAM( \ + "instancepath", \ + b_directory_get_rel_path_cstr( \ + inst->inst_root)), \ + B_ERROR_PARAM("subdirpath", path)); \ + } \ + } while (0) + +static b_result bootstrap_base(struct ropkg_instance *instance) +{ + 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); + + return B_RESULT_SUCCESS; +} + +static b_result bootstrap_config(struct ropkg_instance *instance) +{ + b_directory *dir; + + CREATE_DIRECTORY_OR_THROW( + instance, + ROPKG_INSTANCE_DIRPATH_CONFIG_COLLECTION, + &dir); + + b_directory_release(dir); + + CREATE_DIRECTORY_OR_THROW( + instance, + ROPKG_INSTANCE_DIRPATH_SOURCES, + &dir); + + b_directory_release(dir); + + return B_RESULT_SUCCESS; +} + +static b_result bootstrap_cache(struct ropkg_instance *instance) +{ + b_directory *dir; + + CREATE_DIRECTORY_OR_THROW( + instance, + ROPKG_INSTANCE_DIRPATH_ARCHIVES, + &dir); + + b_directory_release(dir); + + return B_RESULT_SUCCESS; +} + +static b_result bootstrap_database(struct ropkg_instance *instance) +{ + b_file *file; + + CREATE_FILE_OR_THROW( + instance, + ROPKG_INSTANCE_FILEPATH_AVAILABLE, + &file); + + b_file_release(file); + + CREATE_FILE_OR_THROW( + instance, + ROPKG_INSTANCE_FILEPATH_INSTALLED, + &file); + + b_file_release(file); + + return B_RESULT_SUCCESS; +} + +b_result ropkg_instance_open(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); + + b_path *path = b_path_create_from_cstr(cpath); + if (!path) { + free(inst); + return ROPKG_RESULT_ERR(NO_MEMORY); + } + + b_result result = b_directory_open(NULL, path, 0, &inst->inst_root); + b_path_release(path); + + if (b_result_is_error(result)) { + free(inst); + return b_result_propagate(result); + } + + *out = inst; + return ROPKG_RESULT_SUCCESS; +} + +b_result ropkg_instance_bootstrap( + 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); + + b_path *path = b_path_create_from_cstr(cpath); + if (!path) { + free(inst); + return ROPKG_RESULT_ERR(NO_MEMORY); + } + + b_result result = b_directory_open(NULL, path, 0, &inst->inst_root); + b_path_release(path); + + if (b_result_is_error(result)) { + free(inst); + return b_error_with_template_caused_by_error( + ROPKG_ERROR_VENDOR, + ROPKG_ERR_DIR_OPEN_FAILED, + result, + B_ERROR_PARAM("filepath", cpath)); + } + + result = bootstrap_base(inst); + if (b_result_is_error(result)) { + return b_result_propagate(result); + } + + result = bootstrap_config(inst); + if (b_result_is_error(result)) { + return b_result_propagate(result); + } + + result = bootstrap_cache(inst); + if (b_result_is_error(result)) { + return b_result_propagate(result); + } + + result = bootstrap_database(inst); + if (b_result_is_error(result)) { + return b_result_propagate(result); + } + + *out = inst; + return B_RESULT_SUCCESS; +} diff --git a/libropkg/instance.h b/libropkg/instance.h new file mode 100644 index 0000000..c3c9942 --- /dev/null +++ b/libropkg/instance.h @@ -0,0 +1,30 @@ +#ifndef _ROPKG_INSTANCE_H_ +#define _ROPKG_INSTANCE_H_ + +#include + +#define ROPKG_INSTANCE_DIRPATH_CONFIG "etc/ropkg" +#define ROPKG_INSTANCE_DIRPATH_CACHE "var/cache/ropkg" +#define ROPKG_INSTANCE_DIRPATH_DATABASE "var/lib/ropkg" + +#define ROPKG_INSTANCE_DIRPATH_CONFIG_COLLECTION \ + ROPKG_INSTANCE_DIRPATH_CONFIG "/config" +#define ROPKG_INSTANCE_DIRPATH_SOURCES ROPKG_INSTANCE_DIRPATH_CONFIG "/sources" +#define ROPKG_INSTANCE_DIRPATH_AVAILABLE \ + ROPKG_INSTANCE_DIRPATH_DATABASE "/available.d" +#define ROPKG_INSTANCE_DIRPATH_ARCHIVES ROPKG_INSTANCE_DIRPATH_CACHE "/archives" + +#define ROPKG_INSTANCE_FILEPATH_INSTALLED \ + ROPKG_INSTANCE_DIRPATH_DATABASE "/installed" +#define ROPKG_INSTANCE_FILEPATH_AVAILABLE \ + ROPKG_INSTANCE_DIRPATH_DATABASE "/available" + +struct ropkg_instance { + b_directory *inst_root; + + b_directory *inst_dir_config; + b_directory *inst_dir_cache; + b_directory *inst_dir_database; +}; + +#endif