#include "instance.h" #include "ropkg/system-state.h" #include #include #include #define CREATE_FILE_OR_THROW(inst, path, out_file) \ do { \ fx_path *path_object = fx_path_create_from_cstr(path); \ fx_result result = fx_file_open( \ inst->inst_root, \ path_object, \ FX_FILE_READ_WRITE | FX_FILE_CREATE, \ out_file); \ fx_path_unref(path_object); \ \ if (fx_result_is_error(result)) { \ return fx_error_with_template_caused_by_error( \ ROPKG_ERROR_VENDOR, \ ROPKG_ERR_INSTANCE_DIR_CREATE_FAILED, \ result, \ FX_ERROR_PARAM( \ "instancepath", \ fx_directory_get_rel_path_cstr( \ inst->inst_root)), \ FX_ERROR_PARAM("subdirpath", path)); \ } \ } while (0) #define CREATE_DIRECTORY_OR_THROW(inst, path, out_dir) \ do { \ fx_path *path_object = fx_path_create_from_cstr(path); \ fx_result result = fx_directory_open( \ inst->inst_root, \ path_object, \ FX_DIRECTORY_OPEN_CREATE_INTERMEDIATE, \ out_dir); \ fx_path_unref(path_object); \ \ if (fx_result_is_error(result)) { \ return fx_error_with_template_caused_by_error( \ ROPKG_ERROR_VENDOR, \ ROPKG_ERR_INSTANCE_DIR_CREATE_FAILED, \ result, \ FX_ERROR_PARAM( \ "instancepath", \ fx_directory_get_rel_path_cstr( \ inst->inst_root)), \ FX_ERROR_PARAM("subdirpath", path)); \ } \ } while (0) static fx_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 FX_RESULT_SUCCESS; } static fx_result bootstrap_config(struct ropkg_instance *instance) { fx_directory *dir; CREATE_DIRECTORY_OR_THROW( instance, ROPKG_INSTANCE_DIRPATH_CONFIG_FILES, &dir); fx_directory_unref(dir); CREATE_DIRECTORY_OR_THROW( instance, ROPKG_INSTANCE_DIRPATH_SOURCES, &dir); fx_directory_unref(dir); return FX_RESULT_SUCCESS; } static fx_result bootstrap_cache(struct ropkg_instance *instance) { fx_directory *dir; CREATE_DIRECTORY_OR_THROW( instance, ROPKG_INSTANCE_DIRPATH_ARCHIVES, &dir); fx_directory_unref(dir); return FX_RESULT_SUCCESS; } static fx_result bootstrap_database(struct ropkg_instance *instance) { fx_result result; result = ropkg_system_state_init( instance->inst_root, ROPKG_INSTANCE_FILEPATH_STATUS, &instance->inst_status); if (fx_result_is_error(result)) { return fx_result_propagate(result); } result = ropkg_package_db_init( instance->inst_root, ROPKG_INSTANCE_FILEPATH_AVAILABLE, &instance->inst_available); if (fx_result_is_error(result)) { return fx_result_propagate(result); } return FX_RESULT_SUCCESS; } fx_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); fx_path *path = fx_path_create_from_cstr(cpath); if (!path) { free(inst); return ROPKG_RESULT_ERR(NO_MEMORY); } fx_result result = fx_directory_open(NULL, path, 0, &inst->inst_root); fx_path_unref(path); 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); } *out = inst; return ROPKG_RESULT_SUCCESS; } fx_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); fx_path *path = fx_path_create_from_cstr(cpath); if (!path) { ropkg_instance_close(inst); return ROPKG_RESULT_ERR(NO_MEMORY); } fx_result result = fx_directory_open(NULL, path, 0, &inst->inst_root); fx_path_unref(path); if (fx_result_is_error(result)) { ropkg_instance_close(inst); return fx_error_with_template_caused_by_error( ROPKG_ERROR_VENDOR, ROPKG_ERR_DIR_OPEN_FAILED, result, 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); } result = bootstrap_base(inst); if (fx_result_is_error(result)) { ropkg_instance_close(inst); return fx_result_propagate(result); } result = bootstrap_config(inst); if (fx_result_is_error(result)) { ropkg_instance_close(inst); return fx_result_propagate(result); } result = bootstrap_cache(inst); if (fx_result_is_error(result)) { ropkg_instance_close(inst); return fx_result_propagate(result); } result = bootstrap_database(inst); 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); } *out = inst; 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); }